0
# Webpack Virtual Modules
1
2
Webpack Virtual Modules is a plugin that enables dynamical generation of in-memory virtual modules for JavaScript builds created with webpack. When virtual modules are created, all parent virtual directories that lead to the module filename are automatically created too. This plugin supports webpack's watch mode, meaning any write to a virtual module is seen by webpack as if a real file stored on disk has changed.
3
4
## Package Information
5
6
- **Package Name**: webpack-virtual-modules
7
- **Package Type**: npm
8
- **Language**: TypeScript
9
- **Installation**: `npm install webpack-virtual-modules --save-dev`
10
11
## Core Imports
12
13
```javascript
14
const VirtualModulesPlugin = require("webpack-virtual-modules");
15
```
16
17
For TypeScript with proper typing:
18
19
```typescript
20
import VirtualModulesPlugin = require("webpack-virtual-modules");
21
import { Compiler } from "webpack";
22
23
// VirtualStats class is also available
24
const { VirtualStats } = VirtualModulesPlugin;
25
26
// Or with CommonJS require
27
const VirtualModulesPlugin = require("webpack-virtual-modules");
28
const { Compiler } = require("webpack"); // For type reference only
29
```
30
31
## Basic Usage
32
33
### Static Virtual Modules
34
35
Define virtual modules at webpack configuration time:
36
37
```javascript
38
const VirtualModulesPlugin = require("webpack-virtual-modules");
39
40
const virtualModules = new VirtualModulesPlugin({
41
'node_modules/module-foo.js': 'module.exports = { foo: "foo" };',
42
'node_modules/module-bar.js': 'module.exports = { bar: "bar" };'
43
});
44
45
// webpack.config.js
46
module.exports = {
47
plugins: [virtualModules],
48
// ...other config
49
};
50
51
// Use in your code
52
const moduleFoo = require('module-foo');
53
console.log(moduleFoo.foo);
54
```
55
56
### Dynamic Virtual Modules
57
58
Create and modify virtual modules during the build process:
59
60
```javascript
61
const VirtualModulesPlugin = require("webpack-virtual-modules");
62
const webpack = require("webpack");
63
64
const virtualModules = new VirtualModulesPlugin();
65
66
const compiler = webpack({
67
plugins: [virtualModules],
68
// ...other config
69
});
70
71
// Create virtual modules dynamically
72
compiler.hooks.compilation.tap('MyPlugin', function(compilation) {
73
virtualModules.writeModule('dynamic-module.js', `
74
module.exports = {
75
timestamp: ${Date.now()},
76
message: "Generated at build time"
77
};
78
`);
79
});
80
```
81
82
## Architecture
83
84
Webpack Virtual Modules works by:
85
86
1. **Filesystem Integration**: Hooks into webpack's input filesystem to provide virtual file access
87
2. **Memory Storage**: Maintains virtual files entirely in memory without touching the actual filesystem
88
3. **Watch Mode Support**: Integrates with webpack's file watching to trigger recompilation when virtual modules change
89
4. **Directory Creation**: Automatically creates parent virtual directories for any virtual module path
90
5. **Version Compatibility**: Supports webpack versions 3, 4, and 5 with internal version detection
91
92
## Capabilities
93
94
### Plugin Constructor
95
96
Creates a new VirtualModulesPlugin instance with optional static modules.
97
98
```typescript { .api }
99
/**
100
* Creates a webpack plugin for virtual modules
101
* @param modules - Optional object mapping file paths to module contents
102
*/
103
constructor(modules?: Record<string, string>)
104
105
interface VirtualModulesPlugin {
106
new (modules?: Record<string, string>): VirtualModulesPlugin;
107
}
108
```
109
110
**Usage Example:**
111
112
```typescript
113
// Empty plugin for dynamic modules only
114
const virtualModules = new VirtualModulesPlugin();
115
116
// Plugin with static modules
117
const virtualModules = new VirtualModulesPlugin({
118
'src/config.js': 'export const API_URL = "https://api.example.com";',
119
'src/version.js': `export const VERSION = "${process.env.npm_package_version}";`
120
});
121
```
122
123
### Plugin Apply Method
124
125
Webpack plugin interface method that attaches necessary hooks to the webpack compiler.
126
127
```typescript { .api }
128
/**
129
* Attaches the plugin to a webpack compiler
130
* @param compiler - The webpack compiler instance
131
*/
132
apply(compiler: Compiler): void
133
```
134
135
### Write Module
136
137
Writes or updates a virtual module dynamically during the build process.
138
139
```typescript { .api }
140
/**
141
* Writes or updates a virtual module
142
* @param filePath - Path to virtual module (relative to webpack context)
143
* @param contents - String content of the virtual module
144
* @throws Error if plugin not initialized with webpack compiler
145
*/
146
writeModule(filePath: string, contents: string): void
147
```
148
149
**Usage Examples:**
150
151
```javascript
152
// Write a simple module
153
virtualModules.writeModule('utils/constants.js', `
154
module.exports = {
155
BUILD_TIME: ${Date.now()},
156
NODE_ENV: "${process.env.NODE_ENV}"
157
};
158
`);
159
160
// Write a JSON module
161
virtualModules.writeModule('data/config.json', JSON.stringify({
162
apiUrl: process.env.API_URL,
163
features: ['feature1', 'feature2']
164
}));
165
166
// Update existing module
167
virtualModules.writeModule('cache/runtime-data.js', `
168
module.exports = { cache: ${JSON.stringify(runtimeCache)} };
169
`);
170
```
171
172
### Get Module List
173
174
Retrieves list of virtual modules based on optional filter criteria.
175
176
```typescript { .api }
177
/**
178
* Retrieves virtual modules based on filter criteria
179
* @param filter - Filter type: 'all' | 'static' | 'dynamic' (defaults to 'all')
180
* @returns Object mapping file paths to module contents
181
*/
182
getModuleList(filter?: 'all' | 'static' | 'dynamic'): Record<string, string>
183
```
184
185
**Usage Examples:**
186
187
```javascript
188
// Get all virtual modules
189
const allModules = virtualModules.getModuleList();
190
191
// Get only static modules (defined at construction)
192
const staticModules = virtualModules.getModuleList('static');
193
194
// Get only dynamic modules (created via writeModule)
195
const dynamicModules = virtualModules.getModuleList('dynamic');
196
197
// Inspect module contents
198
Object.entries(allModules).forEach(([path, contents]) => {
199
console.log(`Virtual module: ${path}`);
200
console.log(`Content: ${contents.substring(0, 100)}...`);
201
});
202
```
203
204
## Types
205
206
### VirtualStats Class
207
208
Mock filesystem stats object for virtual files, used internally by the plugin.
209
210
```typescript { .api }
211
/**
212
* Creates virtual file stats object compatible with Node.js fs.Stats
213
* @param config - Stats configuration object with filesystem properties
214
*/
215
class VirtualStats {
216
constructor(config: VirtualStatsConfig);
217
218
// Properties set from config
219
dev: number;
220
nlink: number;
221
uid: number;
222
gid: number;
223
rdev: number;
224
blksize: number;
225
ino: number;
226
mode: number;
227
size: number;
228
blocks: number;
229
atime: Date;
230
mtime: Date;
231
ctime: Date;
232
birthtime: Date;
233
234
/** Check if represents a directory */
235
isDirectory(): boolean;
236
237
/** Check if represents a file */
238
isFile(): boolean;
239
240
/** Check if represents a block device */
241
isBlockDevice(): boolean;
242
243
/** Check if represents a character device */
244
isCharacterDevice(): boolean;
245
246
/** Check if represents a symbolic link */
247
isSymbolicLink(): boolean;
248
249
/** Check if represents a FIFO */
250
isFIFO(): boolean;
251
252
/** Check if represents a socket */
253
isSocket(): boolean;
254
}
255
256
interface VirtualStatsConfig {
257
dev: number;
258
nlink: number;
259
uid: number;
260
gid: number;
261
rdev: number;
262
blksize: number;
263
ino: number;
264
mode: number;
265
size: number;
266
blocks: number;
267
atime: Date;
268
mtime: Date;
269
ctime: Date;
270
birthtime: Date;
271
}
272
```
273
274
### Webpack Compiler Interface
275
276
The webpack Compiler type used by the apply method (from webpack types).
277
278
```typescript { .api }
279
// Import from webpack for complete typing
280
import { Compiler, SyncHook, AsyncSeriesHook } from "webpack";
281
282
// Key properties used by VirtualModulesPlugin
283
interface Compiler {
284
hooks: {
285
afterEnvironment: SyncHook<[]>;
286
afterResolvers: SyncHook<[]>;
287
watchRun: AsyncSeriesHook<[Compiler]>;
288
};
289
inputFileSystem: any; // webpack's internal filesystem
290
context: string; // webpack context/working directory
291
fileTimestamps: Map<string, number | { safeTime: number; timestamp: number }>;
292
name?: string; // optional compiler name
293
}
294
```
295
296
## Error Handling
297
298
The plugin throws errors in the following scenarios:
299
300
- **Plugin Not Initialized**: Calling `writeModule()` before the plugin has been applied to a webpack compiler
301
- **Webpack Version Incompatibility**: If webpack version cannot be detected or is unsupported
302
- **Filesystem Access**: If webpack's internal filesystem APIs are not available
303
304
```typescript
305
// Proper error handling
306
try {
307
virtualModules.writeModule('test.js', 'module.exports = { test: true };');
308
} catch (error) {
309
if (error.message.includes('Plugin has not been initialized')) {
310
console.error('Plugin must be applied to webpack compiler first');
311
}
312
throw error;
313
}
314
```
315
316
## Watch Mode Integration
317
318
Virtual modules automatically integrate with webpack's watch mode. When a virtual module is updated via `writeModule()`, webpack will detect the change and trigger a recompilation, just as if a physical file had been modified.
319
320
```javascript
321
// This will trigger webpack recompilation in watch mode
322
compiler.hooks.compilation.tap('UpdateVirtualModule', () => {
323
virtualModules.writeModule('runtime-config.js', `
324
module.exports = { timestamp: ${Date.now()} };
325
`);
326
});
327
```