CommonJsPlugin.js 10 KB

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