CommonJsPlugin.js 9.2 KB

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