0
# Runtime Injection
1
2
The Runtime plugin injects runtime code into bundles for features like hot module replacement, dynamic imports, and environment-specific functionality. Runtimes provide the necessary code to support Parcel's advanced features at runtime.
3
4
## Capabilities
5
6
### Runtime Class
7
8
Base class for creating runtime injection plugins.
9
10
```typescript { .api }
11
/**
12
* Base class for runtime injection plugins
13
* @template T - Configuration type for this runtime
14
*/
15
export declare class Runtime<T> {
16
constructor(opts: RuntimeOpts<T>);
17
}
18
19
/**
20
* Runtime plugin configuration interface
21
* @template ConfigType - Type of configuration returned by loadConfig
22
*/
23
interface RuntimeOpts<ConfigType> {
24
/** Load configuration for this runtime */
25
loadConfig?: (args: {
26
config: Config;
27
options: PluginOptions;
28
logger: PluginLogger;
29
tracer: PluginTracer;
30
}) => Promise<ConfigType> | ConfigType;
31
32
/** Apply runtime code to a bundle (required) */
33
apply(args: {
34
bundle: NamedBundle;
35
bundleGraph: BundleGraph<NamedBundle>;
36
config: ConfigType;
37
options: PluginOptions;
38
logger: PluginLogger;
39
tracer: PluginTracer;
40
}): Promise<void | RuntimeAsset | Array<RuntimeAsset>>;
41
}
42
```
43
44
### Runtime Assets
45
46
```typescript { .api }
47
/**
48
* Runtime asset to inject into bundles
49
*/
50
interface RuntimeAsset {
51
/** File path for the runtime asset */
52
filePath: FilePath;
53
54
/** Runtime code content */
55
code: string;
56
57
/** Dependency that triggered this runtime */
58
dependency?: Dependency;
59
60
/** Whether this should be treated as an entry */
61
isEntry?: boolean;
62
63
/** Environment options for this runtime */
64
env?: EnvironmentOptions;
65
66
/** Whether to replace the original resolution */
67
shouldReplaceResolution?: boolean;
68
}
69
```
70
71
**Usage Example:**
72
73
```javascript
74
import { Runtime } from "@parcel/plugin";
75
76
export default new Runtime({
77
// Apply runtime injection (required)
78
async apply({bundle, bundleGraph, options}) {
79
// Check if this bundle needs HMR runtime
80
if (options.mode === 'development' && options.hmrOptions) {
81
return {
82
filePath: '@parcel/runtime-hmr',
83
code: `
84
if (module.hot) {
85
module.hot.accept(() => {
86
window.location.reload();
87
});
88
}
89
`,
90
isEntry: false
91
};
92
}
93
94
// Check if bundle has dynamic imports
95
const hasDynamicImports = this.hasDynamicImports(bundle, bundleGraph);
96
if (hasDynamicImports) {
97
return {
98
filePath: '@parcel/runtime-dynamic-import',
99
code: this.generateDynamicImportRuntime(bundle, bundleGraph),
100
isEntry: false
101
};
102
}
103
},
104
105
hasDynamicImports(bundle, bundleGraph) {
106
const assets = bundleGraph.getBundleAssets(bundle);
107
return assets.some(asset =>
108
asset.getDependencies().some(dep => dep.isAsync)
109
);
110
},
111
112
generateDynamicImportRuntime(bundle, bundleGraph) {
113
return `
114
window.__parcel_require_loader__ = function(id) {
115
return import('./' + id + '.js');
116
};
117
`;
118
}
119
});
120
```