@pmmmwh/react-refresh-webpack-plugin
Version:
An **EXPERIMENTAL** Webpack plugin to enable "Fast Refresh" (also previously known as _Hot Reloading_) for React components.
98 lines (95 loc) • 4.12 kB
JavaScript
/**
* Makes a runtime module to intercept module execution for React Refresh.
* This module creates an isolated __webpak_require__ function for each module
* and injects a $Refresh$ object into it for use by react-refresh.
* @param {import('webpack')} webpack The Webpack exports.
* @returns {ReactRefreshRuntimeModule} The runtime module class.
*/
function makeRefreshRuntimeModule(webpack) {
return class ReactRefreshRuntimeModule extends webpack.RuntimeModule {
constructor() {
// Second argument is the `stage` for this runtime module -
// we'll use the same stage as Webpack's HMR runtime module for safety.
super('react refresh', webpack.RuntimeModule.STAGE_BASIC);
}
/**
* @returns {string} runtime code
*/
generate() {
const { runtimeTemplate } = this.compilation;
const constDeclaration = runtimeTemplate.supportsConst() ? 'const' : 'var';
return webpack.Template.asString([
`${constDeclaration} setup = ${runtimeTemplate.basicFunction('moduleId', [
`${constDeclaration} refresh = {`,
webpack.Template.indent([
`moduleId: moduleId,`,
`register: ${runtimeTemplate.basicFunction('type, id', [
`${constDeclaration} typeId = moduleId + ' ' + id;`,
'refresh.runtime.register(type, typeId);',
])},`,
`signature: ${runtimeTemplate.returningFunction(
'refresh.runtime.createSignatureFunctionForTransform()'
)},`,
`runtime: {`,
webpack.Template.indent([
`createSignatureFunctionForTransform: ${runtimeTemplate.returningFunction(
runtimeTemplate.returningFunction('type', 'type')
)},`,
`register: ${runtimeTemplate.emptyFunction()}`,
]),
`},`,
]),
`};`,
`return refresh;`,
])};`,
'',
`${webpack.RuntimeGlobals.interceptModuleExecution}.push(${runtimeTemplate.basicFunction(
'options',
[
`${constDeclaration} originalFactory = options.factory;`,
`options.factory = ${runtimeTemplate.basicFunction(
'moduleObject, moduleExports, webpackRequire',
[
// Our require function delegates to the original require function
`${constDeclaration} hotRequire = ${runtimeTemplate.returningFunction(
'webpackRequire(request)',
'request'
)};`,
// The propery descriptor factory below
// ensures all properties but $Refresh$ are proxied through to the original require function
`${constDeclaration} createPropertyDescriptor = ${runtimeTemplate.basicFunction(
'name',
[
`return {`,
webpack.Template.indent([
`configurable: true,`,
`enumerable: true,`,
`get: ${runtimeTemplate.returningFunction('webpackRequire[name]')},`,
`set: ${runtimeTemplate.basicFunction('value', [
'webpackRequire[name] = value;',
])},`,
]),
`};`,
]
)};`,
`for (${constDeclaration} name in webpackRequire) {`,
webpack.Template.indent([
'if (name === "$Refresh$") continue;',
'if (Object.prototype.hasOwnProperty.call(webpackRequire, name)) {',
webpack.Template.indent([
`Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));`,
]),
`}`,
]),
`}`,
`hotRequire.$Refresh$ = setup(options.id);`,
`originalFactory.call(this, moduleObject, moduleExports, hotRequire);`,
]
)};`,
]
)});`,
]);
}
};
}
module.exports = makeRefreshRuntimeModule;