UNPKG

webpack

Version:

Packs ECMAScript/CommonJs/AMD modules for the browser. Allows you to split your codebase into multiple bundles, which can be loaded on demand. Supports loaders to preprocess files, i.e. json, jsx, es7, css, less, ... and your custom stuff.

374 lines (334 loc) • 11.6 kB
/* MIT License http://www.opensource.org/licenses/mit-license.php Author Tobias Koppers @sokra */ "use strict"; const { evaluateToIdentifier, expressionIsUnsupported, toConstantDependency } = require("../../javascript/JavascriptParserHelpers"); const { JAVASCRIPT_MODULE_TYPE_AUTO, JAVASCRIPT_MODULE_TYPE_DYNAMIC } = require("../../module/ModuleTypeConstants"); const SelfModuleFactory = require("../../module/SelfModuleFactory"); const RuntimeGlobals = require("../../runtime/RuntimeGlobals"); const RuntimeModule = require("../../runtime/RuntimeModule"); const Template = require("../../template/Template"); const RuntimeRequirementsDependency = require("../core/RuntimeRequirementsDependency"); const CommonJsExportRequireDependency = require("./CommonJsExportRequireDependency"); const CommonJsExportsDependency = require("./CommonJsExportsDependency"); const CommonJsExportsParserPlugin = require("./CommonJsExportsParserPlugin"); const CommonJsFullRequireDependency = require("./CommonJsFullRequireDependency"); const CommonJsImportsParserPlugin = require("./CommonJsImportsParserPlugin"); const CommonJsObjectExportDependency = require("./CommonJsObjectExportDependency"); const CommonJsRequireContextDependency = require("./CommonJsRequireContextDependency"); const CommonJsRequireDependency = require("./CommonJsRequireDependency"); const CommonJsSelfReferenceDependency = require("./CommonJsSelfReferenceDependency"); const ModuleDecoratorDependency = require("./ModuleDecoratorDependency"); const RequireHeaderDependency = require("./RequireHeaderDependency"); const RequireResolveContextDependency = require("./RequireResolveContextDependency"); const RequireResolveDependency = require("./RequireResolveDependency"); const RequireResolveHeaderDependency = require("./RequireResolveHeaderDependency"); const TopLevelThisParserPlugin = require("./TopLevelThisParserPlugin"); /** * @import { * JavascriptParserOptions * } from "../../../declarations/WebpackOptions" */ /** @import Compilation from "../../Compilation" */ /** @import Compiler from "../../Compiler" */ /** @import Parser from "../../javascript/JavascriptParser" */ const PLUGIN_NAME = "CommonJsPlugin"; class CommonJsPlugin { /** * Applies the plugin by registering its hooks on the compiler. * @param {Compiler} compiler the compiler instance * @returns {void} */ apply(compiler) { compiler.hooks.compilation.tap( PLUGIN_NAME, (compilation, { contextModuleFactory, normalModuleFactory }) => { compilation.dependencyFactories.set( CommonJsRequireDependency, normalModuleFactory ); compilation.dependencyTemplates.set( CommonJsRequireDependency, new CommonJsRequireDependency.Template() ); compilation.dependencyFactories.set( CommonJsFullRequireDependency, normalModuleFactory ); compilation.dependencyTemplates.set( CommonJsFullRequireDependency, new CommonJsFullRequireDependency.Template() ); compilation.dependencyFactories.set( CommonJsRequireContextDependency, contextModuleFactory ); compilation.dependencyTemplates.set( CommonJsRequireContextDependency, new CommonJsRequireContextDependency.Template() ); compilation.dependencyFactories.set( RequireResolveDependency, normalModuleFactory ); compilation.dependencyTemplates.set( RequireResolveDependency, new RequireResolveDependency.Template() ); compilation.dependencyFactories.set( RequireResolveContextDependency, contextModuleFactory ); compilation.dependencyTemplates.set( RequireResolveContextDependency, new RequireResolveContextDependency.Template() ); compilation.dependencyTemplates.set( RequireResolveHeaderDependency, new RequireResolveHeaderDependency.Template() ); compilation.dependencyTemplates.set( RequireHeaderDependency, new RequireHeaderDependency.Template() ); compilation.dependencyTemplates.set( CommonJsExportsDependency, new CommonJsExportsDependency.Template() ); compilation.dependencyTemplates.set( CommonJsObjectExportDependency, new CommonJsObjectExportDependency.Template() ); compilation.dependencyFactories.set( CommonJsExportRequireDependency, normalModuleFactory ); compilation.dependencyTemplates.set( CommonJsExportRequireDependency, new CommonJsExportRequireDependency.Template() ); const selfFactory = new SelfModuleFactory(compilation.moduleGraph); compilation.dependencyFactories.set( CommonJsSelfReferenceDependency, selfFactory ); compilation.dependencyTemplates.set( CommonJsSelfReferenceDependency, new CommonJsSelfReferenceDependency.Template() ); compilation.dependencyFactories.set( ModuleDecoratorDependency, selfFactory ); compilation.dependencyTemplates.set( ModuleDecoratorDependency, new ModuleDecoratorDependency.Template() ); compilation.hooks.runtimeRequirementInModule .for(RuntimeGlobals.esmModuleDecorator) .tap(PLUGIN_NAME, (module, set) => { set.add(RuntimeGlobals.module); set.add(RuntimeGlobals.requireScope); }); compilation.hooks.runtimeRequirementInModule .for(RuntimeGlobals.nodeModuleDecorator) .tap(PLUGIN_NAME, (module, set) => { set.add(RuntimeGlobals.module); set.add(RuntimeGlobals.requireScope); }); compilation.hooks.runtimeRequirementInTree .for(RuntimeGlobals.esmModuleDecorator) .tap(PLUGIN_NAME, (chunk, _set) => { compilation.addRuntimeModule( chunk, new ESMModuleDecoratorRuntimeModule() ); }); compilation.hooks.runtimeRequirementInTree .for(RuntimeGlobals.nodeModuleDecorator) .tap(PLUGIN_NAME, (chunk, _set) => { compilation.addRuntimeModule( chunk, new NodeModuleDecoratorRuntimeModule() ); }); /** * Handles the hook callback for this code path. * @param {Parser} parser parser parser * @param {JavascriptParserOptions} parserOptions parserOptions * @returns {void} */ const handler = (parser, parserOptions) => { // what `this` means does not depend on CommonJS syntax being parsed, // so this one is applied before the `commonjs` option is read if (parserOptions.topLevelThis === "global") { new TopLevelThisParserPlugin( compilation.outputOptions.environment.globalThis ).apply(parser); } if (parserOptions.commonjs !== undefined && !parserOptions.commonjs) { return; } parser.hooks.typeof .for("module") .tap( PLUGIN_NAME, toConstantDependency(parser, JSON.stringify("object")) ); parser.hooks.expression .for("require.main") .tap( PLUGIN_NAME, toConstantDependency( parser, `${RuntimeGlobals.moduleCache}[${RuntimeGlobals.entryModuleId}]`, [RuntimeGlobals.moduleCache, RuntimeGlobals.entryModuleId] ) ); parser.hooks.expression .for("require.extensions") .tap( PLUGIN_NAME, expressionIsUnsupported( parser, "require.extensions is not supported by webpack. Use a loader instead." ) ); parser.hooks.expression .for(RuntimeGlobals.moduleLoaded) .tap(PLUGIN_NAME, (expr) => { parser.state.module.buildInfo.moduleConcatenationBailout = RuntimeGlobals.moduleLoaded; const dep = new RuntimeRequirementsDependency([ RuntimeGlobals.moduleLoaded ]); dep.loc = parser.getLocation(expr); parser.state.module.addPresentationalDependency(dep); return true; }); parser.hooks.expression .for(RuntimeGlobals.moduleId) .tap(PLUGIN_NAME, (expr) => { parser.state.module.buildInfo.moduleConcatenationBailout = RuntimeGlobals.moduleId; const dep = new RuntimeRequirementsDependency([ RuntimeGlobals.moduleId ]); dep.loc = parser.getLocation(expr); parser.state.module.addPresentationalDependency(dep); return true; }); parser.hooks.evaluateIdentifier.for("module.hot").tap( PLUGIN_NAME, evaluateToIdentifier("module.hot", "module", () => ["hot"], null) ); new CommonJsImportsParserPlugin(parserOptions).apply(parser); new CommonJsExportsParserPlugin(parserOptions.topLevelThis).apply( parser ); }; normalModuleFactory.hooks.parser .for(JAVASCRIPT_MODULE_TYPE_AUTO) .tap(PLUGIN_NAME, handler); normalModuleFactory.hooks.parser .for(JAVASCRIPT_MODULE_TYPE_DYNAMIC) .tap(PLUGIN_NAME, handler); } ); } } class ESMModuleDecoratorRuntimeModule extends RuntimeModule { constructor() { super("harmony module decorator"); } /** * Returns true, if the runtime module should get it's own scope. * When false, `generate()` must emit complete statements ending with `;` * so a following runtime IIFE is not parsed as a call (ASI). * @returns {boolean} true, if the runtime module should get it's own scope */ shouldIsolate() { return false; } /** * The `[handlerMap, key]` pairs this module installs onto a chunk handler map * such as `__webpack_require__.f`, or `null` where it cannot name them. * @returns {[string, string][] | null} installed chunk handlers (do not mutate) */ getInstalledChunkHandlers() { return RuntimeModule.NO_CHUNK_HANDLERS; } /** * Generates runtime code for this runtime module. * @returns {string | null} runtime code */ generate() { const { runtimeTemplate } = /** @type {Compilation} */ (this.compilation); return Template.asString([ `${RuntimeGlobals.esmModuleDecorator} = ${runtimeTemplate.basicFunction( "module", [ "module = Object.create(module);", "if (!module.children) module.children = [];", "Object.defineProperty(module, 'exports', {", Template.indent([ "enumerable: true,", `${runtimeTemplate.method("set", "", [ "throw new Error('ES Modules may not assign module.exports or exports.*, Use ESM export syntax, instead: ' + module.id);" ])}` ]), "});", "return module;" ] )};` ]); } } class NodeModuleDecoratorRuntimeModule extends RuntimeModule { constructor() { super("node module decorator"); } /** * Returns true, if the runtime module should get it's own scope. * When false, `generate()` must emit complete statements ending with `;` * so a following runtime IIFE is not parsed as a call (ASI). * @returns {boolean} true, if the runtime module should get it's own scope */ shouldIsolate() { return false; } /** * The `[handlerMap, key]` pairs this module installs onto a chunk handler map * such as `__webpack_require__.f`, or `null` where it cannot name them. * @returns {[string, string][] | null} installed chunk handlers (do not mutate) */ getInstalledChunkHandlers() { return RuntimeModule.NO_CHUNK_HANDLERS; } /** * Generates runtime code for this runtime module. * @returns {string | null} runtime code */ generate() { const { runtimeTemplate } = /** @type {Compilation} */ (this.compilation); return Template.asString([ `${RuntimeGlobals.nodeModuleDecorator} = ${runtimeTemplate.basicFunction( "module", [ "module.paths = [];", "if (!module.children) module.children = [];", "return module;" ] )};` ]); } } module.exports = CommonJsPlugin;