0
# @rollup/plugin-virtual
1
2
@rollup/plugin-virtual is a Rollup plugin that loads virtual modules from memory instead of the filesystem. It enables developers to define module content programmatically by mapping module IDs to their source code strings, which is particularly useful for dynamically generated code, configuration modules, or modules that don't exist as physical files.
3
4
## Package Information
5
6
- **Package Name**: @rollup/plugin-virtual
7
- **Package Type**: npm
8
- **Language**: JavaScript/TypeScript
9
- **Installation**: `npm install @rollup/plugin-virtual --save-dev`
10
11
## Core Imports
12
13
```typescript
14
import virtual from "@rollup/plugin-virtual";
15
```
16
17
For CommonJS:
18
19
```javascript
20
const virtual = require("@rollup/plugin-virtual");
21
```
22
23
## Basic Usage
24
25
```javascript
26
import virtual from "@rollup/plugin-virtual";
27
28
export default {
29
input: "src/entry.js",
30
plugins: [
31
virtual({
32
// Define virtual modules by mapping IDs to source code
33
batman: `export default 'na na na na na'`,
34
"src/robin.js": `export default 'batmannnnn'`
35
})
36
]
37
};
38
```
39
40
**Important**: Place this plugin **before** other plugins like `@rollup/plugin-node-resolve` or `@rollup/plugin-commonjs` in your plugin array to ensure proper module transformation.
41
42
## Architecture
43
44
The plugin implements a virtual module system with several key components:
45
46
- **Virtual Module Prefix**: All virtual modules are internally prefixed with `\0virtual:` to distinguish them from filesystem modules
47
- **Dual Resolution Strategy**: Supports both direct key lookups and path-based resolution for relative imports
48
- **Memory Storage**: Module content is stored in memory as strings, with no filesystem interaction
49
- **Resolution Map**: Maintains an internal map of resolved absolute paths to module content for relative import handling
50
51
**Module Resolution Flow:**
52
1. **Direct Match**: If a module ID exists directly in the modules object, it's resolved with the virtual prefix
53
2. **Relative Resolution**: For relative imports, the plugin resolves paths relative to the importing virtual module
54
3. **Path Normalization**: File paths are converted to absolute paths for consistent lookup
55
56
## Capabilities
57
58
### Virtual Module Creation
59
60
Creates a Rollup plugin that loads virtual modules from memory.
61
62
```typescript { .api }
63
/**
64
* A Rollup plugin which loads virtual modules from memory.
65
* @param modules - Object mapping module IDs to their source code strings
66
* @returns Virtual plugin instance with resolveId and load hooks
67
*/
68
function virtual(modules: RollupVirtualOptions): VirtualPlugin;
69
70
interface RollupVirtualOptions {
71
[id: string]: string;
72
}
73
```
74
75
**Parameters:**
76
- `modules`: Object where keys are module identifiers and values are the module source code as strings
77
78
**Module ID Patterns:**
79
- **Bare module names**: `"batman"` - Direct module name lookup
80
- **Relative paths**: `"./robin.js"` - Resolved relative to importing module
81
- **Absolute paths**: `"src/foo.js"` - Resolved to absolute filesystem path
82
83
**Usage Examples:**
84
85
```javascript
86
// Bare module example
87
virtual({
88
"my-module": `
89
export const config = { debug: true };
90
export default function() { return "Hello!"; }
91
`
92
})
93
94
// Relative path example
95
virtual({
96
"./utils.js": `
97
export function formatDate(date) {
98
return date.toISOString().split('T')[0];
99
}
100
`
101
})
102
103
// Dynamic entry point example
104
virtual({
105
entry: `
106
import batman from 'batcave';
107
import { formatDate } from './utils.js';
108
console.log(batman, formatDate(new Date()));
109
`
110
})
111
```
112
113
### Bundle Entry Point Usage
114
115
The plugin can be used to specify virtual entry points for bundles:
116
117
```javascript
118
import virtual from "@rollup/plugin-virtual";
119
120
export default {
121
input: "entry", // Virtual module name
122
plugins: [
123
virtual({
124
entry: `
125
import batman from 'batcave';
126
import robin from './robin.js';
127
console.log(batman, robin);
128
`,
129
batcave: `export default 'I am Batman!'`,
130
"./robin.js": `export default 'I am Robin!'`
131
})
132
]
133
};
134
```
135
136
## Types
137
138
```typescript { .api }
139
import { Plugin } from 'rollup';
140
141
interface RollupVirtualOptions {
142
/** Module ID to source code mapping */
143
[id: string]: string;
144
}
145
146
/**
147
* Plugin instance returned by virtual() function
148
* Implements Rollup's Plugin interface with virtual module support
149
*/
150
interface VirtualPlugin extends Plugin {
151
name: 'virtual';
152
153
/**
154
* Resolves virtual module IDs with internal prefix system
155
* @param id - Module identifier to resolve
156
* @param importer - Path of the importing module
157
* @returns Prefixed virtual module ID or null if not found
158
*/
159
resolveId(id: string, importer?: string): string | null;
160
161
/**
162
* Loads virtual module content from memory
163
* @param id - Resolved module ID (with virtual prefix)
164
* @returns Module source code or null if not a virtual module
165
*/
166
load(id: string): string | null;
167
}
168
```
169
170
## Module Resolution Behavior
171
172
The plugin implements custom module resolution through two main hooks:
173
174
### resolveId Hook Implementation
175
176
```typescript { .api }
177
/**
178
* Resolves module IDs to virtual modules with prefix system
179
* @param id - The module ID to resolve (e.g., 'batman', './robin.js')
180
* @param importer - The path of the importing module
181
* @returns Virtual module ID with '\0virtual:' prefix, or null if not found
182
*/
183
resolveId(id: string, importer?: string): string | null;
184
```
185
186
**Resolution Logic:**
187
1. **Direct Key Match**: If `id` exists directly in the modules object, returns `\0virtual:${id}`
188
2. **Relative Path Resolution**: When an importer is present:
189
- Strips `\0virtual:` prefix from importer if present
190
- Resolves the relative path using Node.js path resolution
191
- Checks if the resolved absolute path exists in the internal resolved IDs map
192
- Returns `\0virtual:${resolvedPath}` if found
193
3. **No Match**: Returns `null` to let other plugins handle the module
194
195
### load Hook Implementation
196
197
```typescript { .api }
198
/**
199
* Loads virtual module content from memory
200
* @param id - The resolved module ID (must start with '\0virtual:')
201
* @returns Module source code string or null for non-virtual modules
202
*/
203
load(id: string): string | null;
204
```
205
206
**Loading Logic:**
207
1. **Virtual Module Check**: Only processes IDs starting with `\0virtual:`
208
2. **ID Normalization**: Removes the `\0virtual:` prefix to get the original ID
209
3. **Content Lookup**: Checks both direct module keys and the resolved paths map
210
4. **Content Return**: Returns the string content or null if not found
211
212
**Internal Data Structures:**
213
- **modules**: Original object mapping IDs to source code
214
- **resolvedIds**: Map of absolute paths to source code for relative import support
215
- **PREFIX**: Constant `\0virtual:` used to identify virtual modules
216
217
## Requirements
218
219
- **Node.js**: v8.0.0+
220
- **Rollup**: v1.20.0+ or v2.0.0+
221
- **Plugin Order**: Must be placed before other resolution plugins (node-resolve, commonjs)
222
223
## Common Use Cases
224
225
1. **Dynamic Code Generation**: Generate modules programmatically based on build-time data
226
2. **Configuration Modules**: Create configuration modules without physical files
227
3. **Testing**: Mock modules for testing scenarios
228
4. **Bundling Virtual Entry Points**: Combine multiple virtual modules into a single entry point
229
5. **Inline Templates**: Embed template strings as importable modules