makeRefreshRuntimeModule.js 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596
  1. /**
  2. * Makes a runtime module to intercept module execution for React Refresh.
  3. * This module creates an isolated `__webpack_require__` function for each module,
  4. * and injects a `$Refresh$` object into it for use by React Refresh.
  5. * @param {import('webpack')} webpack The Webpack exports.
  6. * @returns {new () => import('webpack').RuntimeModule} The runtime module class.
  7. */
  8. function makeRefreshRuntimeModule(webpack) {
  9. return class ReactRefreshRuntimeModule extends webpack.RuntimeModule {
  10. constructor() {
  11. // Second argument is the `stage` for this runtime module -
  12. // we'll use the same stage as Webpack's HMR runtime module for safety.
  13. super('react refresh', webpack.RuntimeModule.STAGE_BASIC);
  14. }
  15. /**
  16. * @returns {string} runtime code
  17. */
  18. generate() {
  19. if (!this.compilation) throw new Error('Webpack compilation missing!');
  20. const { runtimeTemplate } = this.compilation;
  21. const declareVar = runtimeTemplate.supportsConst() ? 'const' : 'var';
  22. return webpack.Template.asString([
  23. `${declareVar} setup = ${runtimeTemplate.basicFunction('moduleId', [
  24. `${declareVar} refresh = {`,
  25. webpack.Template.indent([
  26. `moduleId: moduleId,`,
  27. `register: ${runtimeTemplate.basicFunction('type, id', [
  28. `${declareVar} typeId = moduleId + " " + id;`,
  29. `refresh.runtime.register(type, typeId);`,
  30. ])},`,
  31. `signature: ${runtimeTemplate.returningFunction(
  32. 'refresh.runtime.createSignatureFunctionForTransform()'
  33. )},`,
  34. `runtime: {`,
  35. webpack.Template.indent([
  36. `createSignatureFunctionForTransform: ${runtimeTemplate.returningFunction(
  37. runtimeTemplate.returningFunction('type', 'type')
  38. )},`,
  39. `register: ${runtimeTemplate.emptyFunction()}`,
  40. ]),
  41. `},`,
  42. ]),
  43. `};`,
  44. `return refresh;`,
  45. ])}`,
  46. '',
  47. `${webpack.RuntimeGlobals.interceptModuleExecution}.push(${runtimeTemplate.basicFunction(
  48. 'options',
  49. [
  50. `${declareVar} originalFactory = options.factory;`,
  51. // Using a function declaration -
  52. // ensures `this` would propagate for modules relying on it
  53. `options.factory = function(moduleObject, moduleExports, webpackRequire) {`,
  54. webpack.Template.indent([
  55. // Our require function delegates to the original require function
  56. `${declareVar} hotRequire = ${runtimeTemplate.returningFunction(
  57. 'webpackRequire(request)',
  58. 'request'
  59. )};`,
  60. // The propery descriptor factory below ensures all properties but `$Refresh$`
  61. // are proxied through to the original require function
  62. `${declareVar} createPropertyDescriptor = ${runtimeTemplate.basicFunction('name', [
  63. `return {`,
  64. webpack.Template.indent([
  65. `configurable: true,`,
  66. `enumerable: true,`,
  67. `get: ${runtimeTemplate.returningFunction('webpackRequire[name]')},`,
  68. `set: ${runtimeTemplate.basicFunction('value', [
  69. 'webpackRequire[name] = value;',
  70. ])},`,
  71. ]),
  72. `};`,
  73. ])};`,
  74. `for (${declareVar} name in webpackRequire) {`,
  75. webpack.Template.indent([
  76. `if (Object.prototype.hasOwnProperty.call(webpackRequire, name) && name !== "$Refresh$") {`,
  77. webpack.Template.indent([
  78. `Object.defineProperty(hotRequire, name, createPropertyDescriptor(name));`,
  79. ]),
  80. `}`,
  81. ]),
  82. `}`,
  83. `hotRequire.$Refresh$ = setup(options.id);`,
  84. `originalFactory.call(this, moduleObject, moduleExports, hotRequire);`,
  85. ]),
  86. '};',
  87. ]
  88. )});`,
  89. ]);
  90. }
  91. };
  92. }
  93. module.exports = makeRefreshRuntimeModule;