CommonJsPlugin.js 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319
  1. /*
  2. MIT License http://www.opensource.org/licenses/mit-license.php
  3. Author Tobias Koppers @sokra
  4. */
  5. "use strict";
  6. const {
  7. JAVASCRIPT_MODULE_TYPE_AUTO,
  8. JAVASCRIPT_MODULE_TYPE_DYNAMIC
  9. } = require("../ModuleTypeConstants");
  10. const RuntimeGlobals = require("../RuntimeGlobals");
  11. const RuntimeModule = require("../RuntimeModule");
  12. const SelfModuleFactory = require("../SelfModuleFactory");
  13. const Template = require("../Template");
  14. const {
  15. evaluateToIdentifier,
  16. expressionIsUnsupported,
  17. toConstantDependency
  18. } = require("../javascript/JavascriptParserHelpers");
  19. const CommonJsExportRequireDependency = require("./CommonJsExportRequireDependency");
  20. const CommonJsExportsDependency = require("./CommonJsExportsDependency");
  21. const CommonJsExportsParserPlugin = require("./CommonJsExportsParserPlugin");
  22. const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency");
  23. const CommonJsImportsParserPlugin = require("./CommonJsImportsParserPlugin");
  24. const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency");
  25. const CommonJsRequireDependency = require("./CommonJsRequireDependency");
  26. const CommonJsSelfReferenceDependency = require("./CommonJsSelfReferenceDependency");
  27. const ModuleDecoratorDependency = require("./ModuleDecoratorDependency");
  28. const RequireHeaderDependency = require("./RequireHeaderDependency");
  29. const RequireResolveContextDependency = require("./RequireResolveContextDependency");
  30. const RequireResolveDependency = require("./RequireResolveDependency");
  31. const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency");
  32. const RuntimeRequirementsDependency = require("./RuntimeRequirementsDependency");
  33. /** @typedef {import("../../declarations/WebpackOptions").JavascriptParserOptions} JavascriptParserOptions */
  34. /** @typedef {import("../Compilation")} Compilation */
  35. /** @typedef {import("../Compiler")} Compiler */
  36. /** @typedef {import("../Dependency").DependencyLocation} DependencyLocation */
  37. /** @typedef {import("../Module").BuildInfo} BuildInfo */
  38. /** @typedef {import("../javascript/JavascriptParser")} Parser */
  39. const PLUGIN_NAME = "CommonJsPlugin";
  40. class CommonJsPlugin {
  41. /**
  42. * Applies the plugin by registering its hooks on the compiler.
  43. * @param {Compiler} compiler the compiler instance
  44. * @returns {void}
  45. */
  46. apply(compiler) {
  47. compiler.hooks.compilation.tap(
  48. PLUGIN_NAME,
  49. (compilation, { contextModuleFactory, normalModuleFactory }) => {
  50. compilation.dependencyFactories.set(
  51. CommonJsRequireDependency,
  52. normalModuleFactory
  53. );
  54. compilation.dependencyTemplates.set(
  55. CommonJsRequireDependency,
  56. new CommonJsRequireDependency.Template()
  57. );
  58. compilation.dependencyFactories.set(
  59. CommonJsFullRequireDependency,
  60. normalModuleFactory
  61. );
  62. compilation.dependencyTemplates.set(
  63. CommonJsFullRequireDependency,
  64. new CommonJsFullRequireDependency.Template()
  65. );
  66. compilation.dependencyFactories.set(
  67. CommonJsRequireContextDependency,
  68. contextModuleFactory
  69. );
  70. compilation.dependencyTemplates.set(
  71. CommonJsRequireContextDependency,
  72. new CommonJsRequireContextDependency.Template()
  73. );
  74. compilation.dependencyFactories.set(
  75. RequireResolveDependency,
  76. normalModuleFactory
  77. );
  78. compilation.dependencyTemplates.set(
  79. RequireResolveDependency,
  80. new RequireResolveDependency.Template()
  81. );
  82. compilation.dependencyFactories.set(
  83. RequireResolveContextDependency,
  84. contextModuleFactory
  85. );
  86. compilation.dependencyTemplates.set(
  87. RequireResolveContextDependency,
  88. new RequireResolveContextDependency.Template()
  89. );
  90. compilation.dependencyTemplates.set(
  91. RequireResolveHeaderDependency,
  92. new RequireResolveHeaderDependency.Template()
  93. );
  94. compilation.dependencyTemplates.set(
  95. RequireHeaderDependency,
  96. new RequireHeaderDependency.Template()
  97. );
  98. compilation.dependencyTemplates.set(
  99. CommonJsExportsDependency,
  100. new CommonJsExportsDependency.Template()
  101. );
  102. compilation.dependencyFactories.set(
  103. CommonJsExportRequireDependency,
  104. normalModuleFactory
  105. );
  106. compilation.dependencyTemplates.set(
  107. CommonJsExportRequireDependency,
  108. new CommonJsExportRequireDependency.Template()
  109. );
  110. const selfFactory = new SelfModuleFactory(compilation.moduleGraph);
  111. compilation.dependencyFactories.set(
  112. CommonJsSelfReferenceDependency,
  113. selfFactory
  114. );
  115. compilation.dependencyTemplates.set(
  116. CommonJsSelfReferenceDependency,
  117. new CommonJsSelfReferenceDependency.Template()
  118. );
  119. compilation.dependencyFactories.set(
  120. ModuleDecoratorDependency,
  121. selfFactory
  122. );
  123. compilation.dependencyTemplates.set(
  124. ModuleDecoratorDependency,
  125. new ModuleDecoratorDependency.Template()
  126. );
  127. compilation.hooks.runtimeRequirementInModule
  128. .for(RuntimeGlobals.harmonyModuleDecorator)
  129. .tap(PLUGIN_NAME, (module, set) => {
  130. set.add(RuntimeGlobals.module);
  131. set.add(RuntimeGlobals.requireScope);
  132. });
  133. compilation.hooks.runtimeRequirementInModule
  134. .for(RuntimeGlobals.nodeModuleDecorator)
  135. .tap(PLUGIN_NAME, (module, set) => {
  136. set.add(RuntimeGlobals.module);
  137. set.add(RuntimeGlobals.requireScope);
  138. });
  139. compilation.hooks.runtimeRequirementInTree
  140. .for(RuntimeGlobals.harmonyModuleDecorator)
  141. .tap(PLUGIN_NAME, (chunk, _set) => {
  142. compilation.addRuntimeModule(
  143. chunk,
  144. new HarmonyModuleDecoratorRuntimeModule()
  145. );
  146. });
  147. compilation.hooks.runtimeRequirementInTree
  148. .for(RuntimeGlobals.nodeModuleDecorator)
  149. .tap(PLUGIN_NAME, (chunk, _set) => {
  150. compilation.addRuntimeModule(
  151. chunk,
  152. new NodeModuleDecoratorRuntimeModule()
  153. );
  154. });
  155. /**
  156. * Handles the hook callback for this code path.
  157. * @param {Parser} parser parser parser
  158. * @param {JavascriptParserOptions} parserOptions parserOptions
  159. * @returns {void}
  160. */
  161. const handler = (parser, parserOptions) => {
  162. if (parserOptions.commonjs !== undefined && !parserOptions.commonjs) {
  163. return;
  164. }
  165. parser.hooks.typeof
  166. .for("module")
  167. .tap(
  168. PLUGIN_NAME,
  169. toConstantDependency(parser, JSON.stringify("object"))
  170. );
  171. parser.hooks.expression
  172. .for("require.main")
  173. .tap(
  174. PLUGIN_NAME,
  175. toConstantDependency(
  176. parser,
  177. `${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}]`,
  178. [RuntimeGlobals.moduleCache, RuntimeGlobals.entryModuleId]
  179. )
  180. );
  181. parser.hooks.expression
  182. .for("require.extensions")
  183. .tap(
  184. PLUGIN_NAME,
  185. expressionIsUnsupported(
  186. parser,
  187. "require.extensions is not supported by webpack. Use a loader instead."
  188. )
  189. );
  190. parser.hooks.expression
  191. .for(RuntimeGlobals.moduleLoaded)
  192. .tap(PLUGIN_NAME, (expr) => {
  193. /** @type {BuildInfo} */
  194. (parser.state.module.buildInfo).moduleConcatenationBailout =
  195. RuntimeGlobals.moduleLoaded;
  196. const dep = new RuntimeRequirementsDependency([
  197. RuntimeGlobals.moduleLoaded
  198. ]);
  199. dep.loc = /** @type {DependencyLocation} */ (expr.loc);
  200. parser.state.module.addPresentationalDependency(dep);
  201. return true;
  202. });
  203. parser.hooks.expression
  204. .for(RuntimeGlobals.moduleId)
  205. .tap(PLUGIN_NAME, (expr) => {
  206. /** @type {BuildInfo} */
  207. (parser.state.module.buildInfo).moduleConcatenationBailout =
  208. RuntimeGlobals.moduleId;
  209. const dep = new RuntimeRequirementsDependency([
  210. RuntimeGlobals.moduleId
  211. ]);
  212. dep.loc = /** @type {DependencyLocation} */ (expr.loc);
  213. parser.state.module.addPresentationalDependency(dep);
  214. return true;
  215. });
  216. parser.hooks.evaluateIdentifier.for("module.hot").tap(
  217. PLUGIN_NAME,
  218. evaluateToIdentifier("module.hot", "module", () => ["hot"], null)
  219. );
  220. new CommonJsImportsParserPlugin(parserOptions).apply(parser);
  221. new CommonJsExportsParserPlugin(compilation.moduleGraph).apply(
  222. parser
  223. );
  224. };
  225. normalModuleFactory.hooks.parser
  226. .for(JAVASCRIPT_MODULE_TYPE_AUTO)
  227. .tap(PLUGIN_NAME, handler);
  228. normalModuleFactory.hooks.parser
  229. .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC)
  230. .tap(PLUGIN_NAME, handler);
  231. }
  232. );
  233. }
  234. }
  235. class HarmonyModuleDecoratorRuntimeModule extends RuntimeModule {
  236. constructor() {
  237. super("harmony module decorator");
  238. }
  239. /**
  240. * Generates runtime code for this runtime module.
  241. * @returns {string | null} runtime code
  242. */
  243. generate() {
  244. const { runtimeTemplate } = /** @type {Compilation} */ (this.compilation);
  245. return Template.asString([
  246. `${
  247. RuntimeGlobals.harmonyModuleDecorator
  248. } = ${runtimeTemplate.basicFunction("module", [
  249. "module = Object.create(module);",
  250. "if (!module.children) module.children = [];",
  251. "Object.defineProperty(module, 'exports', {",
  252. Template.indent([
  253. "enumerable: true,",
  254. `set: ${runtimeTemplate.basicFunction("", [
  255. "throw new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);"
  256. ])}`
  257. ]),
  258. "});",
  259. "return module;"
  260. ])};`
  261. ]);
  262. }
  263. }
  264. class NodeModuleDecoratorRuntimeModule extends RuntimeModule {
  265. constructor() {
  266. super("node module decorator");
  267. }
  268. /**
  269. * Generates runtime code for this runtime module.
  270. * @returns {string | null} runtime code
  271. */
  272. generate() {
  273. const { runtimeTemplate } = /** @type {Compilation} */ (this.compilation);
  274. return Template.asString([
  275. `${RuntimeGlobals.nodeModuleDecorator} = ${runtimeTemplate.basicFunction(
  276. "module",
  277. [
  278. "module.paths = [];",
  279. "if (!module.children) module.children = [];",
  280. "return module;"
  281. ]
  282. )};`
  283. ]);
  284. }
  285. }
  286. module.exports = CommonJsPlugin;