mirror of https://github.com/webpack/webpack.git
Deprecate MainTemplate, ChunkTemplate, ModuleTemplate
move logic and hooks to JavascriptModulesPlugin
This commit is contained in:
parent
f45ba2408e
commit
69a545c444
|
@ -1,7 +1,7 @@
|
|||
/node_modules
|
||||
/test/js
|
||||
/test/browsertest/js
|
||||
/test/fixtures/temp-cache-fixture*
|
||||
/test/fixtures/temp-*
|
||||
/benchmark/js
|
||||
/benchmark/fixtures
|
||||
/examples/**/dist
|
||||
|
|
|
@ -1302,7 +1302,12 @@ export interface OutputOptions {
|
|||
/**
|
||||
* The `publicPath` specifies the public URL address of the output files when referenced in a browser.
|
||||
*/
|
||||
publicPath?: string | Function;
|
||||
publicPath?:
|
||||
| string
|
||||
| ((
|
||||
pathData: import("../lib/Compilation").PathData,
|
||||
assetInfo?: import("../lib/Compilation").AssetInfo
|
||||
) => string);
|
||||
/**
|
||||
* The filename of the SourceMaps for the JavaScript files. They are inside the `output.path` directory.
|
||||
*/
|
||||
|
|
|
@ -5,78 +5,119 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { SyncWaterfallHook, SyncHook } = require("tapable");
|
||||
const util = require("util");
|
||||
const memorize = require("./util/memorize");
|
||||
|
||||
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
|
||||
/** @typedef {import("./Chunk")} Chunk */
|
||||
/** @typedef {import("./Module")} Module} */
|
||||
/** @typedef {import("./util/Hash")} Hash} */
|
||||
/** @typedef {import("webpack-sources").Source} Source} */
|
||||
/** @typedef {import("./ModuleTemplate").RenderContext} RenderContext} */
|
||||
/** @typedef {import("./MainTemplate").UpdateHashForChunkContext} UpdateHashForChunkContext} */
|
||||
/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions} */
|
||||
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry} */
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
|
||||
module.exports = class ChunkTemplate {
|
||||
constructor(outputOptions) {
|
||||
this.outputOptions = outputOptions || {};
|
||||
const getJavascriptModulesPlugin = memorize(() =>
|
||||
require("./JavascriptModulesPlugin")
|
||||
);
|
||||
|
||||
// TODO webpack 6 remove this class
|
||||
class ChunkTemplate {
|
||||
/**
|
||||
* @param {TODO} outputOptions TODO
|
||||
* @param {Compilation} compilation the compilation
|
||||
*/
|
||||
constructor(outputOptions, compilation) {
|
||||
this._outputOptions = outputOptions || {};
|
||||
const moduleTemplate = null; // TODO add deprecated ModuleTemplate
|
||||
this.hooks = Object.freeze({
|
||||
/** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */
|
||||
renderManifest: new SyncWaterfallHook(["result", "options"]),
|
||||
/** @type {SyncWaterfallHook<[Source, ModuleTemplate, RenderContext]>} */
|
||||
modules: new SyncWaterfallHook([
|
||||
"source",
|
||||
"moduleTemplate",
|
||||
"renderContext"
|
||||
]),
|
||||
/** @type {SyncWaterfallHook<[Source, ModuleTemplate, RenderContext]>} */
|
||||
render: new SyncWaterfallHook([
|
||||
"source",
|
||||
"moduleTemplate",
|
||||
"renderContext"
|
||||
]),
|
||||
/** @type {SyncWaterfallHook<[Source, Chunk]>} */
|
||||
renderWithEntry: new SyncWaterfallHook(["source", "chunk"]),
|
||||
/** @type {SyncHook<[Hash]>} */
|
||||
hash: new SyncHook(["hash"]),
|
||||
/** @type {SyncHook<[Hash, Chunk]>} */
|
||||
hashForChunk: new SyncHook(["hash", "chunk"])
|
||||
renderManifest: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
compilation.hooks.renderManifest.tap(
|
||||
options,
|
||||
(entries, options) => {
|
||||
if (options.chunk.hasRuntime()) return entries;
|
||||
return fn(entries, options);
|
||||
}
|
||||
);
|
||||
},
|
||||
"ChunkTemplate.hooks.renderManifest is deprecated (use Compilation.hooks.renderManifest instead)",
|
||||
"DEP_WEBPACK_CHUNK_TEMPLATE_RENDER_MANIFEST"
|
||||
)
|
||||
},
|
||||
modules: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderChunk.tap(options, (source, renderContext) =>
|
||||
fn(source, moduleTemplate, renderContext)
|
||||
);
|
||||
},
|
||||
"ChunkTemplate.hooks.modules is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderChunk instead)",
|
||||
"DEP_WEBPACK_CHUNK_TEMPLATE_MODULES"
|
||||
)
|
||||
},
|
||||
render: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderChunk.tap(options, (source, renderContext) =>
|
||||
fn(source, moduleTemplate, renderContext)
|
||||
);
|
||||
},
|
||||
"ChunkTemplate.hooks.render is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderChunk instead)",
|
||||
"DEP_WEBPACK_CHUNK_TEMPLATE_RENDER"
|
||||
)
|
||||
},
|
||||
renderWithEntry: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderWithEntry.tap(options, (source, renderContext) => {
|
||||
if (renderContext.chunk.hasRuntime()) return source;
|
||||
return fn(source, renderContext.chunk);
|
||||
});
|
||||
},
|
||||
"ChunkTemplate.hooks.renderWithEntry is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderWithEntry instead)",
|
||||
"DEP_WEBPACK_CHUNK_TEMPLATE_RENDER_WITH_ENTRY"
|
||||
)
|
||||
},
|
||||
hash: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
compilation.hooks.fullHash.tap(options, fn);
|
||||
},
|
||||
"ChunkTemplate.hooks.hash is deprecated (use Compilation.hooks.fullHash instead)",
|
||||
"DEP_WEBPACK_CHUNK_TEMPLATE_HASH"
|
||||
)
|
||||
},
|
||||
hashForChunk: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.chunkHash.tap(options, (chunk, hash, context) => {
|
||||
if (chunk.hasRuntime()) return;
|
||||
fn(hash, chunk, context);
|
||||
});
|
||||
},
|
||||
"ChunkTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)",
|
||||
"DEP_WEBPACK_CHUNK_TEMPLATE_HASH_FOR_CHUNK"
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {RenderManifestOptions} options render manifest options
|
||||
* @returns {RenderManifestEntry[]} returns render manifest
|
||||
*/
|
||||
getRenderManifest(options) {
|
||||
const result = [];
|
||||
Object.defineProperty(ChunkTemplate.prototype, "outputOptions", {
|
||||
get: util.deprecate(
|
||||
/**
|
||||
* @this {ChunkTemplate}
|
||||
* @returns {TODO} output options
|
||||
*/
|
||||
function() {
|
||||
return this._outputOptions;
|
||||
},
|
||||
"ChunkTemplate.outputOptions is deprecated (use Compilation.outputOptions instead)",
|
||||
"DEP_WEBPACK_CHUNK_TEMPLATE_OUTPUT_OPTIONS"
|
||||
)
|
||||
});
|
||||
|
||||
this.hooks.renderManifest.call(result, options);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates hash with information from this template
|
||||
* @param {Hash} hash the hash to update
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHash(hash) {
|
||||
hash.update("ChunkTemplate");
|
||||
hash.update("3");
|
||||
this.hooks.hash.call(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates hash with chunk-specific information from this template
|
||||
* @param {Hash} hash the hash to update
|
||||
* @param {Chunk} chunk the chunk
|
||||
* @param {UpdateHashForChunkContext} context options object
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHashForChunk(hash, chunk, context) {
|
||||
this.updateHash(hash);
|
||||
this.hooks.hashForChunk.call(hash, chunk);
|
||||
}
|
||||
};
|
||||
module.exports = ChunkTemplate;
|
||||
|
|
|
@ -68,6 +68,7 @@ const { arrayToSetDeprecation } = require("./util/deprecation");
|
|||
/** @typedef {import("./ModuleFactory")} ModuleFactory */
|
||||
/** @typedef {import("./RuntimeModule")} RuntimeModule */
|
||||
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry */
|
||||
/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions */
|
||||
/** @typedef {import("./WebpackError")} WebpackError */
|
||||
/** @typedef {import("./dependencies/DependencyReference")} DependencyReference */
|
||||
/** @typedef {import("./dependencies/DllEntryDependency")} DllEntryDependency */
|
||||
|
@ -127,6 +128,13 @@ const { arrayToSetDeprecation } = require("./util/deprecation");
|
|||
* @property {(Record<string, (length: number) => string>)=} contentHashWithLength
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ChunkHashContext
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} LogEntry
|
||||
* @property {string} type
|
||||
|
@ -407,15 +415,21 @@ class Compilation {
|
|||
/** @type {AsyncSeriesHook<[]>} */
|
||||
afterSeal: new AsyncSeriesHook([]),
|
||||
|
||||
/** @type {SyncHook<[Chunk, Hash]>} */
|
||||
chunkHash: new SyncHook(["chunk", "chunkHash"]),
|
||||
/** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */
|
||||
renderManifest: new SyncWaterfallHook(["result", "options"]),
|
||||
|
||||
/** @type {SyncHook<[Hash]>} */
|
||||
fullHash: new SyncHook(["hash"]),
|
||||
/** @type {SyncHook<[Chunk, Hash, ChunkHashContext]>} */
|
||||
chunkHash: new SyncHook(["chunk", "chunkHash", "ChunkHashContext"]),
|
||||
|
||||
/** @type {SyncHook<[Module, string]>} */
|
||||
moduleAsset: new SyncHook(["module", "filename"]),
|
||||
/** @type {SyncHook<[Chunk, string]>} */
|
||||
chunkAsset: new SyncHook(["chunk", "filename"]),
|
||||
|
||||
/** @type {SyncWaterfallHook<[string, TODO]>} */
|
||||
assetPath: new SyncWaterfallHook(["filename", "data"]), // TODO MainTemplate
|
||||
/** @type {SyncWaterfallHook<[string, object, AssetInfo]>} */
|
||||
assetPath: new SyncWaterfallHook(["path", "options", "assetInfo"]),
|
||||
|
||||
/** @type {SyncBailHook<[], boolean>} */
|
||||
needAdditionalPass: new SyncBailHook([]),
|
||||
|
@ -471,18 +485,36 @@ class Compilation {
|
|||
/** @type {boolean} */
|
||||
this.profile = (options && options.profile) || false;
|
||||
|
||||
this.mainTemplate = new MainTemplate(this.outputOptions);
|
||||
this.chunkTemplate = new ChunkTemplate(this.outputOptions);
|
||||
this.mainTemplate = new MainTemplate(this.outputOptions, this);
|
||||
this.chunkTemplate = new ChunkTemplate(this.outputOptions, this);
|
||||
this.runtimeTemplate = new RuntimeTemplate(
|
||||
this.outputOptions,
|
||||
this.requestShortener
|
||||
);
|
||||
/** @type {{asset: ModuleTemplate, javascript: ModuleTemplate, webassembly: ModuleTemplate}} */
|
||||
/** @type {{javascript: ModuleTemplate}} */
|
||||
this.moduleTemplates = {
|
||||
asset: new ModuleTemplate(this.runtimeTemplate, "asset"),
|
||||
javascript: new ModuleTemplate(this.runtimeTemplate, "javascript"),
|
||||
webassembly: new ModuleTemplate(this.runtimeTemplate, "webassembly")
|
||||
javascript: new ModuleTemplate(this.runtimeTemplate, this)
|
||||
};
|
||||
Object.defineProperties(this.moduleTemplates, {
|
||||
asset: {
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
get() {
|
||||
throw new WebpackError(
|
||||
"Compilation.moduleTemplates.asset has been removed"
|
||||
);
|
||||
}
|
||||
},
|
||||
webassembly: {
|
||||
enumerable: false,
|
||||
configurable: false,
|
||||
get() {
|
||||
throw new WebpackError(
|
||||
"Compilation.moduleTemplates.webassembly has been removed"
|
||||
);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
this.moduleGraph = new ModuleGraph();
|
||||
this.chunkGraph = undefined;
|
||||
|
@ -1941,11 +1973,7 @@ class Compilation {
|
|||
if (outputOptions.hashSalt) {
|
||||
hash.update(outputOptions.hashSalt);
|
||||
}
|
||||
this.mainTemplate.updateHash(hash);
|
||||
this.chunkTemplate.updateHash(hash);
|
||||
for (const key of Object.keys(this.moduleTemplates).sort()) {
|
||||
this.moduleTemplates[key].updateHash(hash);
|
||||
}
|
||||
this.hooks.fullHash.call(hash);
|
||||
for (const child of this.children) {
|
||||
hash.update(child.hash);
|
||||
}
|
||||
|
@ -1993,15 +2021,11 @@ class Compilation {
|
|||
chunkHash.update(outputOptions.hashSalt);
|
||||
}
|
||||
chunk.updateHash(chunkHash, chunkGraph);
|
||||
const template = chunk.hasRuntime()
|
||||
? this.mainTemplate
|
||||
: this.chunkTemplate;
|
||||
template.updateHashForChunk(chunkHash, chunk, {
|
||||
this.hooks.chunkHash.call(chunk, chunkHash, {
|
||||
chunkGraph,
|
||||
moduleGraph: this.moduleGraph,
|
||||
runtimeTemplate: this.runtimeTemplate
|
||||
});
|
||||
this.hooks.chunkHash.call(chunk, chunkHash);
|
||||
chunk.hash = /** @type {string} */ (chunkHash.digest(hashDigest));
|
||||
hash.update(chunk.hash);
|
||||
chunk.renderedHash = chunk.hash.substr(0, hashDigestLength);
|
||||
|
@ -2150,6 +2174,14 @@ class Compilation {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RenderManifestOptions} options options object
|
||||
* @returns {RenderManifestEntry[]} manifest entries
|
||||
*/
|
||||
getRenderManifest(options) {
|
||||
return this.hooks.renderManifest.call([], options);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Callback} callback signals when the call finishes
|
||||
* @returns {void}
|
||||
|
@ -2166,10 +2198,7 @@ class Compilation {
|
|||
/** @type {RenderManifestEntry[]} */
|
||||
let manifest;
|
||||
try {
|
||||
const template = chunk.hasRuntime()
|
||||
? this.mainTemplate
|
||||
: this.chunkTemplate;
|
||||
manifest = template.getRenderManifest({
|
||||
manifest = this.getRenderManifest({
|
||||
chunk,
|
||||
hash: this.hash,
|
||||
fullHash: this.fullHash,
|
||||
|
@ -2179,7 +2208,7 @@ class Compilation {
|
|||
chunkGraph: this.chunkGraph,
|
||||
moduleGraph: this.moduleGraph,
|
||||
runtimeTemplate: this.runtimeTemplate
|
||||
}); // [{ render(), filenameTemplate, pathOptions, identifier, hash }]
|
||||
});
|
||||
} catch (err) {
|
||||
this.errors.push(new ChunkRenderError(chunk, "", err));
|
||||
return callback();
|
||||
|
@ -2294,14 +2323,14 @@ class Compilation {
|
|||
* @param {PathData} data context data
|
||||
* @returns {string} interpolated path
|
||||
*/
|
||||
getPath(filename, data) {
|
||||
getPath(filename, data = {}) {
|
||||
if (!data.hash) {
|
||||
data = {
|
||||
hash: this.hash,
|
||||
...data
|
||||
};
|
||||
}
|
||||
return this.mainTemplate.getAssetPath(filename, data);
|
||||
return this.getAssetPath(filename, data);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -2309,10 +2338,43 @@ class Compilation {
|
|||
* @param {PathData} data context data
|
||||
* @returns {{ path: string, info: AssetInfo }} interpolated path and asset info
|
||||
*/
|
||||
getPathWithInfo(filename, data) {
|
||||
data = data || {};
|
||||
data.hash = data.hash || this.hash;
|
||||
return this.mainTemplate.getAssetPathWithInfo(filename, data);
|
||||
getPathWithInfo(filename, data = {}) {
|
||||
if (!data.hash) {
|
||||
data = {
|
||||
hash: this.hash,
|
||||
...data
|
||||
};
|
||||
}
|
||||
return this.getAssetPathWithInfo(filename, data);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | function(PathData, AssetInfo=): string} filename used to get asset path with hash
|
||||
* @param {PathData} data context data
|
||||
* @returns {string} interpolated path
|
||||
*/
|
||||
getAssetPath(filename, data) {
|
||||
return this.hooks.assetPath.call(
|
||||
typeof filename === "function" ? filename(data) : filename,
|
||||
data,
|
||||
undefined
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {string | function(PathData, AssetInfo=): string} filename used to get asset path with hash
|
||||
* @param {PathData} data context data
|
||||
* @returns {{ path: string, info: AssetInfo }} interpolated path and asset info
|
||||
*/
|
||||
getAssetPathWithInfo(filename, data) {
|
||||
const assetInfo = {};
|
||||
// TODO webpack 5: refactor assetPath hook to receive { path, info } object
|
||||
const newPath = this.hooks.assetPath.call(
|
||||
typeof filename === "function" ? filename(data, assetInfo) : filename,
|
||||
data,
|
||||
assetInfo
|
||||
);
|
||||
return { path: newPath, info: assetInfo };
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -1,27 +0,0 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
Author Tobias Koppers @sokra
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const FunctionModuleTemplatePlugin = require("./FunctionModuleTemplatePlugin");
|
||||
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
|
||||
class FunctionModulePlugin {
|
||||
/**
|
||||
* Apply the plugin
|
||||
* @param {Compiler} compiler the compiler instance
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap("FunctionModulePlugin", compilation => {
|
||||
new FunctionModuleTemplatePlugin({
|
||||
compilation
|
||||
}).apply(compilation.moduleTemplates.javascript);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = FunctionModulePlugin;
|
|
@ -69,4 +69,26 @@ const makeWebpackErrorCallback = (callback, hook) => {
|
|||
callback(null, result);
|
||||
};
|
||||
};
|
||||
|
||||
module.exports.makeWebpackErrorCallback = makeWebpackErrorCallback;
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {function(): T} fn function which will be wrapping in try catch
|
||||
* @param {string} hook name of hook
|
||||
* @returns {T} the result
|
||||
*/
|
||||
const tryRunOrWebpackError = (fn, hook) => {
|
||||
let r;
|
||||
try {
|
||||
r = fn();
|
||||
} catch (err) {
|
||||
if (err instanceof WebpackError) {
|
||||
throw err;
|
||||
}
|
||||
throw new HookWebpackError(err, hook);
|
||||
}
|
||||
return r;
|
||||
};
|
||||
|
||||
module.exports.tryRunOrWebpackError = tryRunOrWebpackError;
|
||||
|
|
|
@ -342,7 +342,7 @@ class HotModuleReplacementPlugin {
|
|||
newRuntimeModules
|
||||
);
|
||||
hotUpdateChunk.removedModules = removedModules;
|
||||
const renderManifest = chunkTemplate.getRenderManifest({
|
||||
const renderManifest = compilation.getRenderManifest({
|
||||
chunk: hotUpdateChunk,
|
||||
hash: records.hash,
|
||||
fullHash: records.hash,
|
||||
|
|
|
@ -5,10 +5,18 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { ConcatSource } = require("webpack-sources");
|
||||
const { SyncWaterfallHook, SyncHook } = require("tapable");
|
||||
const {
|
||||
ConcatSource,
|
||||
OriginalSource,
|
||||
PrefixSource
|
||||
} = require("webpack-sources");
|
||||
const Compilation = require("./Compilation");
|
||||
const { tryRunOrWebpackError } = require("./HookWebpackError");
|
||||
const HotUpdateChunk = require("./HotUpdateChunk");
|
||||
const JavascriptGenerator = require("./JavascriptGenerator");
|
||||
const JavascriptParser = require("./JavascriptParser");
|
||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
||||
const Template = require("./Template");
|
||||
const { compareModulesByIdOrIdentifier } = require("./util/comparators");
|
||||
const createHash = require("./util/createHash");
|
||||
|
@ -17,12 +25,13 @@ const createHash = require("./util/createHash");
|
|||
/** @typedef {import("./Chunk")} Chunk */
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./ChunkTemplate")} ChunkTemplate */
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
/** @typedef {import("./Compilation").ChunkHashContext} ChunkHashContext */
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
|
||||
/** @typedef {import("./Module")} Module */
|
||||
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
|
||||
/** @typedef {import("./ModuleTemplate").RenderContext} RenderContext */
|
||||
/** @typedef {import("./ModuleGraph")} ModuleGraph */
|
||||
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
|
||||
/** @typedef {import("./util/Hash")} Hash */
|
||||
|
||||
/**
|
||||
* @param {Chunk} chunk a chunk
|
||||
|
@ -40,7 +49,89 @@ const chunkHasJs = (chunk, chunkGraph) => {
|
|||
return false;
|
||||
};
|
||||
|
||||
/**
|
||||
* @typedef {Object} RenderContext
|
||||
* @property {Chunk} chunk the chunk
|
||||
* @property {DependencyTemplates} dependencyTemplates the dependency templates
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} MainRenderContext
|
||||
* @property {Chunk} chunk the chunk
|
||||
* @property {DependencyTemplates} dependencyTemplates the dependency templates
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
* @property {string} hash hash to be used for render call
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} RenderBootstrapContext
|
||||
* @property {Chunk} chunk the chunk
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
* @property {string} hash hash to be used for render call
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CompilationHooks
|
||||
* @property {SyncWaterfallHook<[Source, Module, RenderContext]>} renderModuleContent
|
||||
* @property {SyncWaterfallHook<[Source, Module, RenderContext]>} renderModuleContainer
|
||||
* @property {SyncWaterfallHook<[Source, Module, RenderContext]>} renderModulePackage
|
||||
* @property {SyncWaterfallHook<[Source, RenderContext]>} renderChunk
|
||||
* @property {SyncWaterfallHook<[Source, RenderContext]>} renderMain
|
||||
* @property {SyncWaterfallHook<[Source, RenderContext]>} renderWithEntry
|
||||
* @property {SyncWaterfallHook<[string, RenderBootstrapContext]>} renderRequire
|
||||
* @property {SyncHook<[Chunk, Hash, ChunkHashContext]>} chunkHash
|
||||
*/
|
||||
|
||||
/** @type {WeakMap<Compilation, CompilationHooks>} */
|
||||
const compilationHooksMap = new WeakMap();
|
||||
|
||||
class JavascriptModulesPlugin {
|
||||
/**
|
||||
* @param {Compilation} compilation the compilation
|
||||
* @returns {CompilationHooks} the attached hooks
|
||||
*/
|
||||
static getCompilationHooks(compilation) {
|
||||
if (!(compilation instanceof Compilation)) {
|
||||
throw new TypeError(
|
||||
"The 'compilation' argument must be an instance of JavascriptParser"
|
||||
);
|
||||
}
|
||||
let hooks = compilationHooksMap.get(compilation);
|
||||
if (hooks === undefined) {
|
||||
hooks = {
|
||||
renderModuleContent: new SyncWaterfallHook([
|
||||
"source",
|
||||
"module",
|
||||
"renderContext"
|
||||
]),
|
||||
renderModuleContainer: new SyncWaterfallHook([
|
||||
"source",
|
||||
"module",
|
||||
"renderContext"
|
||||
]),
|
||||
renderModulePackage: new SyncWaterfallHook([
|
||||
"source",
|
||||
"module",
|
||||
"renderContext"
|
||||
]),
|
||||
renderWithEntry: new SyncWaterfallHook(["source", "renderContext"]),
|
||||
renderChunk: new SyncWaterfallHook(["source", "renderContext"]),
|
||||
renderMain: new SyncWaterfallHook(["source", "renderContext"]),
|
||||
renderRequire: new SyncWaterfallHook(["code", "renderContext"]),
|
||||
chunkHash: new SyncHook(["chunk", "hash", "context"])
|
||||
};
|
||||
compilationHooksMap.set(compilation, hooks);
|
||||
}
|
||||
return hooks;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compiler} compiler webpack compiler
|
||||
* @returns {void}
|
||||
|
@ -49,6 +140,7 @@ class JavascriptModulesPlugin {
|
|||
compiler.hooks.compilation.tap(
|
||||
"JavascriptModulesPlugin",
|
||||
(compilation, { normalModuleFactory }) => {
|
||||
const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
|
||||
const moduleGraph = compilation.moduleGraph;
|
||||
normalModuleFactory.hooks.createParser
|
||||
.for("javascript/auto")
|
||||
|
@ -86,7 +178,6 @@ class JavascriptModulesPlugin {
|
|||
const chunk = options.chunk;
|
||||
const hash = options.hash;
|
||||
const outputOptions = options.outputOptions;
|
||||
const moduleTemplates = options.moduleTemplates;
|
||||
const dependencyTemplates = options.dependencyTemplates;
|
||||
|
||||
const filenameTemplate =
|
||||
|
@ -94,14 +185,17 @@ class JavascriptModulesPlugin {
|
|||
|
||||
result.push({
|
||||
render: () =>
|
||||
compilation.mainTemplate.render(moduleTemplates.javascript, {
|
||||
hash,
|
||||
chunk,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate: options.runtimeTemplate,
|
||||
moduleGraph: options.moduleGraph,
|
||||
chunkGraph: options.chunkGraph
|
||||
}),
|
||||
this.renderMain(
|
||||
{
|
||||
hash,
|
||||
chunk,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate: options.runtimeTemplate,
|
||||
moduleGraph: options.moduleGraph,
|
||||
chunkGraph: options.chunkGraph
|
||||
},
|
||||
hooks
|
||||
),
|
||||
filenameTemplate,
|
||||
pathOptions: {
|
||||
chunk,
|
||||
|
@ -121,7 +215,6 @@ class JavascriptModulesPlugin {
|
|||
const hotUpdateChunk =
|
||||
chunk instanceof HotUpdateChunk ? chunk : null;
|
||||
const outputOptions = options.outputOptions;
|
||||
const moduleTemplates = options.moduleTemplates;
|
||||
const dependencyTemplates = options.dependencyTemplates;
|
||||
|
||||
if (!hotUpdateChunk && !chunkHasJs(chunk, chunkGraph)) {
|
||||
|
@ -141,17 +234,17 @@ class JavascriptModulesPlugin {
|
|||
|
||||
result.push({
|
||||
render: () =>
|
||||
this.renderJavascript(
|
||||
this.renderChunk(
|
||||
compilation,
|
||||
compilation.chunkTemplate,
|
||||
moduleTemplates.javascript,
|
||||
{
|
||||
chunk,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate: compilation.runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph: compilation.chunkGraph
|
||||
}
|
||||
},
|
||||
hooks
|
||||
),
|
||||
filenameTemplate,
|
||||
pathOptions: {
|
||||
|
@ -166,6 +259,30 @@ class JavascriptModulesPlugin {
|
|||
return result;
|
||||
}
|
||||
);
|
||||
compilation.hooks.chunkHash.tap(
|
||||
"JavascriptModulesPlugin",
|
||||
(chunk, hash, context) => {
|
||||
hooks.chunkHash.call(chunk, hash, context);
|
||||
if (chunk.hasRuntime()) {
|
||||
const bootstrap = this.renderBootstrap(
|
||||
{
|
||||
hash: "0000",
|
||||
chunk,
|
||||
chunkGraph: context.chunkGraph,
|
||||
moduleGraph: context.moduleGraph,
|
||||
runtimeTemplate: context.runtimeTemplate
|
||||
},
|
||||
hooks
|
||||
);
|
||||
for (const key of Object.keys(bootstrap)) {
|
||||
hash.update(key);
|
||||
for (const line of bootstrap[key]) {
|
||||
hash.update(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
compilation.hooks.contentHash.tap("JavascriptModulesPlugin", chunk => {
|
||||
const {
|
||||
chunkGraph,
|
||||
|
@ -181,12 +298,9 @@ class JavascriptModulesPlugin {
|
|||
const hotUpdateChunk = chunk instanceof HotUpdateChunk ? chunk : null;
|
||||
const hash = createHash(hashFunction);
|
||||
if (hashSalt) hash.update(hashSalt);
|
||||
const template = chunk.hasRuntime()
|
||||
? compilation.mainTemplate
|
||||
: compilation.chunkTemplate;
|
||||
hash.update(`${chunk.id} `);
|
||||
hash.update(chunk.ids ? chunk.ids.join(",") : "");
|
||||
template.updateHashForChunk(hash, chunk, {
|
||||
hooks.chunkHash.call(chunk, hash, {
|
||||
chunkGraph,
|
||||
moduleGraph,
|
||||
runtimeTemplate
|
||||
|
@ -209,36 +323,411 @@ class JavascriptModulesPlugin {
|
|||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module the rendered module
|
||||
* @param {RenderContext} renderContext options object
|
||||
* @param {CompilationHooks} hooks hooks
|
||||
* @returns {Source} the newly generated source from rendering
|
||||
*/
|
||||
renderModule(module, renderContext, hooks) {
|
||||
const {
|
||||
chunkGraph,
|
||||
moduleGraph,
|
||||
runtimeTemplate,
|
||||
dependencyTemplates
|
||||
} = renderContext;
|
||||
try {
|
||||
const moduleSource = module.source({
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph,
|
||||
type: "javascript"
|
||||
});
|
||||
const moduleSourcePostContent = tryRunOrWebpackError(
|
||||
() =>
|
||||
hooks.renderModuleContent.call(moduleSource, module, renderContext),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderModuleContent"
|
||||
);
|
||||
const source = new ConcatSource();
|
||||
const args = [];
|
||||
const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
|
||||
module
|
||||
);
|
||||
const needModule = runtimeRequirements.has(RuntimeGlobals.module);
|
||||
const needExports = runtimeRequirements.has(RuntimeGlobals.exports);
|
||||
const needRequire =
|
||||
runtimeRequirements.has(RuntimeGlobals.require) ||
|
||||
runtimeRequirements.has(RuntimeGlobals.requireScope);
|
||||
const needThisAsExports = runtimeRequirements.has(
|
||||
RuntimeGlobals.thisAsExports
|
||||
);
|
||||
if (needExports || needRequire || needModule)
|
||||
args.push(
|
||||
needModule
|
||||
? module.moduleArgument
|
||||
: "__unused_webpack_" + module.moduleArgument
|
||||
);
|
||||
if (needExports || needRequire)
|
||||
args.push(
|
||||
needExports
|
||||
? module.exportsArgument
|
||||
: "__unused_webpack_" + module.exportsArgument
|
||||
);
|
||||
if (needRequire) args.push("__webpack_require__");
|
||||
if (!needThisAsExports && runtimeTemplate.supportsArrowFunction()) {
|
||||
source.add("/***/ ((" + args.join(", ") + ") => {\n\n");
|
||||
} else {
|
||||
source.add("/***/ (function(" + args.join(", ") + ") {\n\n");
|
||||
}
|
||||
if (module.buildInfo.strict) source.add('"use strict";\n');
|
||||
source.add(moduleSourcePostContent);
|
||||
source.add("\n\n/***/ })");
|
||||
const moduleSourcePostContainer = tryRunOrWebpackError(
|
||||
() => hooks.renderModuleContainer.call(source, module, renderContext),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderModuleContainer"
|
||||
);
|
||||
return tryRunOrWebpackError(
|
||||
() =>
|
||||
hooks.renderModulePackage.call(
|
||||
moduleSourcePostContainer,
|
||||
module,
|
||||
renderContext
|
||||
),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderModulePackage"
|
||||
);
|
||||
} catch (e) {
|
||||
e.module = module;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Compilation} compilation the compilation
|
||||
* @param {ChunkTemplate} chunkTemplate the chunk template
|
||||
* @param {ModuleTemplate} moduleTemplate the module template
|
||||
* @param {RenderContext} renderContext the render context
|
||||
* @param {CompilationHooks} hooks hooks
|
||||
* @returns {Source} the rendered source
|
||||
*/
|
||||
renderJavascript(compilation, chunkTemplate, moduleTemplate, renderContext) {
|
||||
renderChunk(compilation, chunkTemplate, renderContext, hooks) {
|
||||
const chunk = renderContext.chunk;
|
||||
const moduleSources = Template.renderChunkModules(
|
||||
renderContext,
|
||||
m => m.getSourceTypes().has("javascript"),
|
||||
moduleTemplate
|
||||
module => this.renderModule(module, renderContext, hooks)
|
||||
);
|
||||
const core = chunkTemplate.hooks.modules.call(
|
||||
moduleSources,
|
||||
moduleTemplate,
|
||||
renderContext
|
||||
);
|
||||
let source = chunkTemplate.hooks.render.call(
|
||||
core,
|
||||
moduleTemplate,
|
||||
renderContext
|
||||
let source = tryRunOrWebpackError(
|
||||
() => hooks.renderChunk.call(moduleSources, renderContext),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderChunk"
|
||||
);
|
||||
if (renderContext.chunkGraph.getNumberOfEntryModules(chunk) > 0) {
|
||||
source = chunkTemplate.hooks.renderWithEntry.call(source, chunk);
|
||||
source = tryRunOrWebpackError(
|
||||
() => hooks.renderWithEntry.call(source, renderContext),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderWithEntry"
|
||||
);
|
||||
}
|
||||
chunk.rendered = true;
|
||||
return new ConcatSource(source, ";");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {MainRenderContext} renderContext options object
|
||||
* @param {CompilationHooks} hooks hooks
|
||||
* @returns {Source} the newly generated source from rendering
|
||||
*/
|
||||
renderMain(renderContext, hooks) {
|
||||
const { chunk, chunkGraph, runtimeTemplate } = renderContext;
|
||||
|
||||
let source = new ConcatSource();
|
||||
if (runtimeTemplate.supportsConst()) {
|
||||
source.add("/******/ (() => { // webpackBootstrap\n");
|
||||
} else {
|
||||
source.add("/******/ (function() { // webpackBootstrap\n");
|
||||
}
|
||||
|
||||
source.add("/******/ \tvar __webpack_modules__ = (");
|
||||
source.add(
|
||||
Template.renderChunkModules(
|
||||
renderContext,
|
||||
m => m.getSourceTypes().has("javascript"),
|
||||
module => this.renderModule(module, renderContext, hooks),
|
||||
"/******/ \t"
|
||||
)
|
||||
);
|
||||
source.add(");\n");
|
||||
|
||||
const bootstrap = this.renderBootstrap(renderContext, hooks);
|
||||
|
||||
source.add(
|
||||
"/************************************************************************/\n"
|
||||
);
|
||||
source.add(
|
||||
new PrefixSource(
|
||||
"/******/",
|
||||
new OriginalSource(
|
||||
Template.prefix(bootstrap.header, " \t") + "\n",
|
||||
"webpack/bootstrap"
|
||||
)
|
||||
)
|
||||
);
|
||||
|
||||
const runtimeModules = renderContext.chunkGraph.getChunkRuntimeModulesInOrder(
|
||||
chunk
|
||||
);
|
||||
|
||||
if (runtimeModules.length > 0) {
|
||||
source.add(
|
||||
"/************************************************************************/\n"
|
||||
);
|
||||
source.add(
|
||||
Template.renderMainRuntimeModules(runtimeModules, renderContext)
|
||||
);
|
||||
}
|
||||
source.add(
|
||||
"/************************************************************************/\n"
|
||||
);
|
||||
source.add(
|
||||
new PrefixSource(
|
||||
"/******/",
|
||||
new OriginalSource(
|
||||
Template.prefix(bootstrap.startup, " \t") + "\n",
|
||||
"webpack/startup"
|
||||
)
|
||||
)
|
||||
);
|
||||
source.add("/******/ })()\n");
|
||||
|
||||
/** @type {Source} */
|
||||
let finalSource = tryRunOrWebpackError(
|
||||
() => hooks.renderMain.call(source, renderContext),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderMain"
|
||||
);
|
||||
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
|
||||
finalSource = tryRunOrWebpackError(
|
||||
() => hooks.renderWithEntry.call(finalSource, renderContext),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderWithEntry"
|
||||
);
|
||||
}
|
||||
if (!finalSource) {
|
||||
throw new Error(
|
||||
"Compiler error: MainTemplate plugin 'render' should return something"
|
||||
);
|
||||
}
|
||||
chunk.rendered = true;
|
||||
return new ConcatSource(finalSource, ";");
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RenderBootstrapContext} renderContext options object
|
||||
* @param {CompilationHooks} hooks hooks
|
||||
* @returns {{ header: string[], startup: string[] }} the generated source of the bootstrap code
|
||||
*/
|
||||
renderBootstrap(renderContext, hooks) {
|
||||
const { chunkGraph, chunk, runtimeTemplate } = renderContext;
|
||||
|
||||
const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
|
||||
|
||||
const requireFunction = runtimeRequirements.has(RuntimeGlobals.require);
|
||||
const moduleCache = runtimeRequirements.has(RuntimeGlobals.moduleCache);
|
||||
const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
|
||||
const exportsUsed = runtimeRequirements.has(RuntimeGlobals.exports);
|
||||
const requireScopeUsed = runtimeRequirements.has(
|
||||
RuntimeGlobals.requireScope
|
||||
);
|
||||
const interceptModuleExecution = runtimeRequirements.has(
|
||||
RuntimeGlobals.interceptModuleExecution
|
||||
);
|
||||
const returnExportsFromRuntime = runtimeRequirements.has(
|
||||
RuntimeGlobals.returnExportsFromRuntime
|
||||
);
|
||||
|
||||
const useRequire =
|
||||
requireFunction ||
|
||||
interceptModuleExecution ||
|
||||
returnExportsFromRuntime ||
|
||||
moduleUsed ||
|
||||
exportsUsed;
|
||||
|
||||
const result = {
|
||||
header: [],
|
||||
startup: []
|
||||
};
|
||||
|
||||
let buf = result.header;
|
||||
let startup = result.startup;
|
||||
|
||||
if (useRequire || moduleCache) {
|
||||
buf.push("// The module cache");
|
||||
buf.push("var __webpack_module_cache__ = {};");
|
||||
buf.push("");
|
||||
}
|
||||
|
||||
if (useRequire) {
|
||||
buf.push("// The require function");
|
||||
buf.push(`function __webpack_require__(moduleId) {`);
|
||||
buf.push(Template.indent('"use strict";'));
|
||||
buf.push(Template.indent(this.renderRequire(renderContext, hooks)));
|
||||
buf.push("}");
|
||||
buf.push("");
|
||||
} else if (runtimeRequirements.has(RuntimeGlobals.requireScope)) {
|
||||
buf.push("// The require scope");
|
||||
buf.push("var __webpack_require__ = {};");
|
||||
}
|
||||
|
||||
if (runtimeRequirements.has(RuntimeGlobals.moduleFactories)) {
|
||||
buf.push("");
|
||||
buf.push("// expose the modules object (__webpack_modules__)");
|
||||
buf.push(`${RuntimeGlobals.moduleFactories} = __webpack_modules__;`);
|
||||
}
|
||||
|
||||
if (moduleCache) {
|
||||
buf.push("");
|
||||
buf.push("// expose the module cache");
|
||||
buf.push(`${RuntimeGlobals.moduleCache} = __webpack_module_cache__;`);
|
||||
}
|
||||
|
||||
if (interceptModuleExecution) {
|
||||
buf.push("");
|
||||
buf.push("// expose the module execution interceptor");
|
||||
buf.push(`${RuntimeGlobals.interceptModuleExecution} = [];`);
|
||||
}
|
||||
|
||||
buf.push("");
|
||||
if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
|
||||
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
|
||||
/** @type {string[]} */
|
||||
const buf2 = [];
|
||||
const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(
|
||||
chunk
|
||||
);
|
||||
buf2.push(
|
||||
returnExportsFromRuntime
|
||||
? "// Load entry module and return exports"
|
||||
: "// Load entry module"
|
||||
);
|
||||
let i = chunkGraph.getNumberOfEntryModules(chunk);
|
||||
for (const entryModule of chunkGraph.getChunkEntryModulesIterable(
|
||||
chunk
|
||||
)) {
|
||||
const mayReturn =
|
||||
--i === 0 && returnExportsFromRuntime ? "return " : "";
|
||||
const moduleId = chunkGraph.getModuleId(entryModule);
|
||||
let moduleIdExpr = JSON.stringify(moduleId);
|
||||
if (runtimeRequirements.has(RuntimeGlobals.entryModuleId)) {
|
||||
moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
|
||||
}
|
||||
if (useRequire) {
|
||||
buf2.push(`${mayReturn}__webpack_require__(${moduleIdExpr});`);
|
||||
} else if (requireScopeUsed) {
|
||||
buf2.push(
|
||||
`__webpack_modules__[${moduleIdExpr}](0, 0, __webpack_require__);`
|
||||
);
|
||||
} else {
|
||||
buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
|
||||
}
|
||||
}
|
||||
if (runtimeRequirements.has(RuntimeGlobals.startup)) {
|
||||
buf.push(
|
||||
Template.asString([
|
||||
"// the startup function",
|
||||
`${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
|
||||
"",
|
||||
buf2
|
||||
)};`
|
||||
])
|
||||
);
|
||||
startup.push("// run startup");
|
||||
startup.push(`return ${RuntimeGlobals.startup}();`);
|
||||
} else {
|
||||
startup.push(
|
||||
Template.asString(["// startup", Template.asString(buf2)])
|
||||
);
|
||||
}
|
||||
} else if (runtimeRequirements.has(RuntimeGlobals.startup)) {
|
||||
buf.push(
|
||||
Template.asString([
|
||||
"// the startup function",
|
||||
"// It's empty as no entry modules are in this chunk",
|
||||
`${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
|
||||
"",
|
||||
""
|
||||
)}`
|
||||
])
|
||||
);
|
||||
}
|
||||
} else if (runtimeRequirements.has(RuntimeGlobals.startup)) {
|
||||
startup.push("// run startup");
|
||||
startup.push(`return ${RuntimeGlobals.startup}();`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RenderBootstrapContext} renderContext options object
|
||||
* @param {CompilationHooks} hooks hooks
|
||||
* @returns {string} the generated source of the require function
|
||||
*/
|
||||
renderRequire(renderContext, hooks) {
|
||||
const {
|
||||
chunk,
|
||||
chunkGraph,
|
||||
runtimeTemplate: { outputOptions }
|
||||
} = renderContext;
|
||||
const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
|
||||
const moduleExecution = runtimeRequirements.has(
|
||||
RuntimeGlobals.interceptModuleExecution
|
||||
)
|
||||
? Template.asString([
|
||||
"var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };",
|
||||
`${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
|
||||
"module = execOptions.module;",
|
||||
"execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
|
||||
])
|
||||
: runtimeRequirements.has(RuntimeGlobals.thisAsExports)
|
||||
? Template.asString([
|
||||
"__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);"
|
||||
])
|
||||
: Template.asString([
|
||||
"__webpack_modules__[moduleId](module, module.exports, __webpack_require__);"
|
||||
]);
|
||||
const content = Template.asString([
|
||||
"// Check if module is in cache",
|
||||
"if(__webpack_module_cache__[moduleId]) {",
|
||||
Template.indent("return __webpack_module_cache__[moduleId].exports;"),
|
||||
"}",
|
||||
"// Create a new module (and put it into the cache)",
|
||||
"var module = __webpack_module_cache__[moduleId] = {",
|
||||
Template.indent(["i: moduleId,", "l: false,", "exports: {}"]),
|
||||
"};",
|
||||
"",
|
||||
outputOptions.strictModuleExceptionHandling
|
||||
? Template.asString([
|
||||
"// Execute the module function",
|
||||
"var threw = true;",
|
||||
"try {",
|
||||
Template.indent([moduleExecution, "threw = false;"]),
|
||||
"} finally {",
|
||||
Template.indent([
|
||||
"if(threw) delete __webpack_module_cache__[moduleId];"
|
||||
]),
|
||||
"}"
|
||||
])
|
||||
: Template.asString([
|
||||
"// Execute the module function",
|
||||
moduleExecution
|
||||
]),
|
||||
"",
|
||||
"// Flag the module as loaded",
|
||||
"module.l = true;",
|
||||
"",
|
||||
"// Return the exports of the module",
|
||||
"return module.exports;"
|
||||
]);
|
||||
return tryRunOrWebpackError(
|
||||
() => hooks.renderRequire.call(content, renderContext),
|
||||
"JavascriptModulesPlugin.getCompilationHooks().renderRequire"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = JavascriptModulesPlugin;
|
||||
|
|
|
@ -5,19 +5,16 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { SyncWaterfallHook, SyncHook } = require("tapable");
|
||||
const {
|
||||
ConcatSource,
|
||||
OriginalSource,
|
||||
PrefixSource
|
||||
} = require("webpack-sources");
|
||||
const { SyncWaterfallHook } = require("tapable");
|
||||
const util = require("util");
|
||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
||||
const Template = require("./Template");
|
||||
const memorize = require("./util/memorize");
|
||||
|
||||
/** @typedef {import("webpack-sources").ConcatSource} ConcatSource */
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
|
||||
/** @typedef {import("./Chunk")} Chunk */
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
/** @typedef {import("./Compilation").AssetInfo} AssetInfo */
|
||||
/** @typedef {import("./Module")} Module} */
|
||||
/** @typedef {import("./util/Hash")} Hash} */
|
||||
|
@ -29,53 +26,93 @@ const Template = require("./Template");
|
|||
/** @typedef {import("./Template").RenderManifestOptions} RenderManifestOptions} */
|
||||
/** @typedef {import("./Template").RenderManifestEntry} RenderManifestEntry} */
|
||||
|
||||
/**
|
||||
* @typedef {Object} MainRenderContext
|
||||
* @property {Chunk} chunk the chunk
|
||||
* @property {DependencyTemplates} dependencyTemplates the dependency templates
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
* @property {string} hash hash to be used for render call
|
||||
*/
|
||||
const getJavascriptModulesPlugin = memorize(() =>
|
||||
require("./JavascriptModulesPlugin")
|
||||
);
|
||||
|
||||
/**
|
||||
* @typedef {Object} RenderBootstrapContext
|
||||
* @property {Chunk} chunk the chunk
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
* @property {string} hash hash to be used for render call
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} UpdateHashForChunkContext
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
*/
|
||||
|
||||
module.exports = class MainTemplate {
|
||||
// TODO webpack 6 remove this class
|
||||
class MainTemplate {
|
||||
/**
|
||||
*
|
||||
* @param {TODO=} outputOptions output options for the MainTemplate
|
||||
* @param {Compilation} compilation the compilation
|
||||
*/
|
||||
constructor(outputOptions) {
|
||||
constructor(outputOptions, compilation) {
|
||||
/** @type {TODO?} */
|
||||
this.outputOptions = outputOptions || {};
|
||||
this._outputOptions = outputOptions || {};
|
||||
this.hooks = Object.freeze({
|
||||
/** @type {SyncWaterfallHook<[RenderManifestEntry[], RenderManifestOptions]>} */
|
||||
renderManifest: new SyncWaterfallHook(["result", "options"]),
|
||||
/** @type {SyncWaterfallHook<[string, RenderBootstrapContext]>} */
|
||||
require: new SyncWaterfallHook(["source", "renderContext"]),
|
||||
/** @type {SyncWaterfallHook<[Source, Chunk, string]>} */
|
||||
renderWithEntry: new SyncWaterfallHook(["source", "chunk", "hash"]),
|
||||
/** @type {SyncWaterfallHook<[string, object, AssetInfo]>} */
|
||||
assetPath: new SyncWaterfallHook(["path", "options", "assetInfo"]),
|
||||
/** @type {SyncHook<[Hash]>} */
|
||||
hash: new SyncHook(["hash"]),
|
||||
/** @type {SyncHook<[Hash, Chunk]>} */
|
||||
hashForChunk: new SyncHook(["hash", "chunk"]),
|
||||
renderManifest: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
compilation.hooks.renderManifest.tap(
|
||||
options,
|
||||
(entries, options) => {
|
||||
if (!options.chunk.hasRuntime()) return entries;
|
||||
return fn(entries, options);
|
||||
}
|
||||
);
|
||||
},
|
||||
"MainTemplate.hooks.renderManifest is deprecated (use Compilation.hooks.renderManifest instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_RENDER_MANIFEST"
|
||||
)
|
||||
},
|
||||
require: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderRequire.tap(options, fn);
|
||||
},
|
||||
"MainTemplate.hooks.require is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderRequire instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_REQUIRE"
|
||||
)
|
||||
},
|
||||
renderWithEntry: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderWithEntry.tap(options, (source, renderContext) => {
|
||||
if (!renderContext.chunk.hasRuntime()) return source;
|
||||
return fn(source, renderContext.chunk, compilation.hash);
|
||||
});
|
||||
},
|
||||
"MainTemplate.hooks.renderWithEntry is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderWithEntry instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_RENDER_WITH_ENTRY"
|
||||
)
|
||||
},
|
||||
assetPath: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
compilation.hooks.assetPath.tap(options, fn);
|
||||
},
|
||||
"MainTemplate.hooks.assetPath is deprecated (use Compilation.hooks.assetPath instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_ASSET_PATH"
|
||||
)
|
||||
},
|
||||
hash: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
compilation.hooks.fullHash.tap(options, fn);
|
||||
},
|
||||
"MainTemplate.hooks.hash is deprecated (use Compilation.hooks.fullHash instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_HASH"
|
||||
)
|
||||
},
|
||||
hashForChunk: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.chunkHash.tap(options, (chunk, hash) => {
|
||||
if (!chunk.hasRuntime()) return;
|
||||
return fn(hash, chunk);
|
||||
});
|
||||
},
|
||||
"MainTemplate.hooks.hashForChunk is deprecated (use JavascriptModulesPlugin.getCompilationHooks().chunkHash instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_HASH_FOR_CHUNK"
|
||||
)
|
||||
},
|
||||
|
||||
// for compatibility:
|
||||
/** @type {SyncWaterfallHook<[string, Chunk, string, ModuleTemplate, DependencyTemplates]>} */
|
||||
|
@ -98,379 +135,78 @@ module.exports = class MainTemplate {
|
|||
"chunkIdExpression"
|
||||
])
|
||||
});
|
||||
this.hooks.require.tap("MainTemplate", (source, renderContext) => {
|
||||
const { chunk, chunkGraph } = renderContext;
|
||||
const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
|
||||
const moduleExecution = runtimeRequirements.has(
|
||||
RuntimeGlobals.interceptModuleExecution
|
||||
)
|
||||
? Template.asString([
|
||||
"var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };",
|
||||
`${RuntimeGlobals.interceptModuleExecution}.forEach(function(handler) { handler(execOptions); });`,
|
||||
"module = execOptions.module;",
|
||||
"execOptions.factory.call(module.exports, module, module.exports, execOptions.require);"
|
||||
])
|
||||
: runtimeRequirements.has(RuntimeGlobals.thisAsExports)
|
||||
? Template.asString([
|
||||
"__webpack_modules__[moduleId].call(module.exports, module, module.exports, __webpack_require__);"
|
||||
])
|
||||
: Template.asString([
|
||||
"__webpack_modules__[moduleId](module, module.exports, __webpack_require__);"
|
||||
]);
|
||||
return Template.asString([
|
||||
source,
|
||||
"// Check if module is in cache",
|
||||
"if(__webpack_module_cache__[moduleId]) {",
|
||||
Template.indent("return __webpack_module_cache__[moduleId].exports;"),
|
||||
"}",
|
||||
"// Create a new module (and put it into the cache)",
|
||||
"var module = __webpack_module_cache__[moduleId] = {",
|
||||
Template.indent(["i: moduleId,", "l: false,", "exports: {}"]),
|
||||
"};",
|
||||
"",
|
||||
outputOptions.strictModuleExceptionHandling
|
||||
? Template.asString([
|
||||
"// Execute the module function",
|
||||
"var threw = true;",
|
||||
"try {",
|
||||
Template.indent([moduleExecution, "threw = false;"]),
|
||||
"} finally {",
|
||||
Template.indent([
|
||||
"if(threw) delete __webpack_module_cache__[moduleId];"
|
||||
]),
|
||||
"}"
|
||||
])
|
||||
: Template.asString([
|
||||
"// Execute the module function",
|
||||
moduleExecution
|
||||
]),
|
||||
"",
|
||||
"// Flag the module as loaded",
|
||||
"module.l = true;",
|
||||
"",
|
||||
"// Return the exports of the module",
|
||||
"return module.exports;"
|
||||
]);
|
||||
});
|
||||
}
|
||||
|
||||
// TODO webpack 6 remove
|
||||
// BACKWARD COMPAT START
|
||||
get requireFn() {
|
||||
return "__webpack_require__";
|
||||
}
|
||||
|
||||
/**
|
||||
* @deprecated
|
||||
* @param {string} hash the hash
|
||||
* @param {number=} length length of the hash
|
||||
* @returns {string} generated code
|
||||
*/
|
||||
renderCurrentHashCode(hash, length) {
|
||||
if (length) {
|
||||
return `${RuntimeGlobals.getFullHash} ? ${
|
||||
RuntimeGlobals.getFullHash
|
||||
}().slice(0, ${length}) : ${hash.slice(0, length)}`;
|
||||
}
|
||||
return `${RuntimeGlobals.getFullHash} ? ${RuntimeGlobals.getFullHash}() : ${hash}`;
|
||||
}
|
||||
// BACKWARD COMPAT END
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {RenderManifestOptions} options render manifest options
|
||||
* @returns {RenderManifestEntry[]} returns render manifest
|
||||
*/
|
||||
getRenderManifest(options) {
|
||||
const result = [];
|
||||
|
||||
this.hooks.renderManifest.call(result, options);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {RenderBootstrapContext} renderContext options object
|
||||
* @returns {{ header: string[], startup: string[] }} the generated source of the bootstrap code
|
||||
*/
|
||||
renderBootstrap(renderContext) {
|
||||
const { chunkGraph, chunk, runtimeTemplate } = renderContext;
|
||||
|
||||
const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(chunk);
|
||||
|
||||
const requireFunction = runtimeRequirements.has(RuntimeGlobals.require);
|
||||
const moduleCache = runtimeRequirements.has(RuntimeGlobals.moduleCache);
|
||||
const moduleUsed = runtimeRequirements.has(RuntimeGlobals.module);
|
||||
const exportsUsed = runtimeRequirements.has(RuntimeGlobals.exports);
|
||||
const requireScopeUsed = runtimeRequirements.has(
|
||||
RuntimeGlobals.requireScope
|
||||
);
|
||||
const interceptModuleExecution = runtimeRequirements.has(
|
||||
RuntimeGlobals.interceptModuleExecution
|
||||
);
|
||||
const returnExportsFromRuntime = runtimeRequirements.has(
|
||||
RuntimeGlobals.returnExportsFromRuntime
|
||||
);
|
||||
|
||||
const useRequire =
|
||||
requireFunction ||
|
||||
interceptModuleExecution ||
|
||||
returnExportsFromRuntime ||
|
||||
moduleUsed ||
|
||||
exportsUsed;
|
||||
|
||||
const result = {
|
||||
header: [],
|
||||
startup: []
|
||||
};
|
||||
|
||||
let buf = result.header;
|
||||
let startup = result.startup;
|
||||
|
||||
if (useRequire || moduleCache) {
|
||||
buf.push("// The module cache");
|
||||
buf.push("var __webpack_module_cache__ = {};");
|
||||
buf.push("");
|
||||
}
|
||||
|
||||
if (useRequire) {
|
||||
buf.push("// The require function");
|
||||
buf.push(`function __webpack_require__(moduleId) {`);
|
||||
buf.push(Template.indent('"use strict";'));
|
||||
buf.push(Template.indent(this.hooks.require.call("", renderContext)));
|
||||
buf.push("}");
|
||||
buf.push("");
|
||||
} else if (runtimeRequirements.has(RuntimeGlobals.requireScope)) {
|
||||
buf.push("// The require scope");
|
||||
buf.push("var __webpack_require__ = {};");
|
||||
}
|
||||
|
||||
if (runtimeRequirements.has(RuntimeGlobals.moduleFactories)) {
|
||||
buf.push("");
|
||||
buf.push("// expose the modules object (__webpack_modules__)");
|
||||
buf.push(`${RuntimeGlobals.moduleFactories} = __webpack_modules__;`);
|
||||
}
|
||||
|
||||
if (moduleCache) {
|
||||
buf.push("");
|
||||
buf.push("// expose the module cache");
|
||||
buf.push(`${RuntimeGlobals.moduleCache} = __webpack_module_cache__;`);
|
||||
}
|
||||
|
||||
if (interceptModuleExecution) {
|
||||
buf.push("");
|
||||
buf.push("// expose the module execution interceptor");
|
||||
buf.push(`${RuntimeGlobals.interceptModuleExecution} = [];`);
|
||||
}
|
||||
|
||||
buf.push("");
|
||||
if (!runtimeRequirements.has(RuntimeGlobals.startupNoDefault)) {
|
||||
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
|
||||
/** @type {string[]} */
|
||||
const buf2 = [];
|
||||
const runtimeRequirements = chunkGraph.getTreeRuntimeRequirements(
|
||||
chunk
|
||||
);
|
||||
buf2.push(
|
||||
returnExportsFromRuntime
|
||||
? "// Load entry module and return exports"
|
||||
: "// Load entry module"
|
||||
);
|
||||
let i = chunkGraph.getNumberOfEntryModules(chunk);
|
||||
for (const entryModule of chunkGraph.getChunkEntryModulesIterable(
|
||||
chunk
|
||||
)) {
|
||||
const mayReturn =
|
||||
--i === 0 && returnExportsFromRuntime ? "return " : "";
|
||||
const moduleId = chunkGraph.getModuleId(entryModule);
|
||||
let moduleIdExpr = JSON.stringify(moduleId);
|
||||
if (runtimeRequirements.has(RuntimeGlobals.entryModuleId)) {
|
||||
moduleIdExpr = `${RuntimeGlobals.entryModuleId} = ${moduleIdExpr}`;
|
||||
}
|
||||
if (useRequire) {
|
||||
buf2.push(`${mayReturn}__webpack_require__(${moduleIdExpr});`);
|
||||
} else if (requireScopeUsed) {
|
||||
buf2.push(
|
||||
`__webpack_modules__[${moduleIdExpr}](0, 0, __webpack_require__);`
|
||||
);
|
||||
} else {
|
||||
buf2.push(`__webpack_modules__[${moduleIdExpr}]();`);
|
||||
}
|
||||
this.renderCurrentHashCode = util.deprecate(
|
||||
/**
|
||||
* @deprecated
|
||||
* @param {string} hash the hash
|
||||
* @param {number=} length length of the hash
|
||||
* @returns {string} generated code
|
||||
*/ (hash, length) => {
|
||||
if (length) {
|
||||
return `${RuntimeGlobals.getFullHash} ? ${
|
||||
RuntimeGlobals.getFullHash
|
||||
}().slice(0, ${length}) : ${hash.slice(0, length)}`;
|
||||
}
|
||||
if (runtimeRequirements.has(RuntimeGlobals.startup)) {
|
||||
buf.push(
|
||||
Template.asString([
|
||||
"// the startup function",
|
||||
`${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
|
||||
"",
|
||||
buf2
|
||||
)};`
|
||||
])
|
||||
);
|
||||
startup.push("// run startup");
|
||||
startup.push(`return ${RuntimeGlobals.startup}();`);
|
||||
} else {
|
||||
startup.push(
|
||||
Template.asString(["// startup", Template.asString(buf2)])
|
||||
);
|
||||
}
|
||||
} else if (runtimeRequirements.has(RuntimeGlobals.startup)) {
|
||||
buf.push(
|
||||
Template.asString([
|
||||
"// the startup function",
|
||||
"// It's empty as no entry modules are in this chunk",
|
||||
`${RuntimeGlobals.startup} = ${runtimeTemplate.basicFunction(
|
||||
"",
|
||||
""
|
||||
)}`
|
||||
])
|
||||
return `${RuntimeGlobals.getFullHash} ? ${RuntimeGlobals.getFullHash}() : ${hash}`;
|
||||
},
|
||||
"MainTemplate.renderCurrentHashCode is deprecated (use RuntimeGlobals.getFullHash runtime function instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_RENDER_CURRENT_HASH_CODE"
|
||||
);
|
||||
|
||||
this.getPublicPath = util.deprecate(
|
||||
/**
|
||||
*
|
||||
* @param {object} options get public path options
|
||||
* @returns {string} hook call
|
||||
*/ options => {
|
||||
return compilation.getAssetPath(
|
||||
compilation.outputOptions.publicPath,
|
||||
options
|
||||
);
|
||||
}
|
||||
} else if (runtimeRequirements.has(RuntimeGlobals.startup)) {
|
||||
startup.push("// run startup");
|
||||
startup.push(`return ${RuntimeGlobals.startup}();`);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {ModuleTemplate} moduleTemplate ModuleTemplate instance for render
|
||||
* @param {MainRenderContext} renderContext options object
|
||||
* @returns {Source} the newly generated source from rendering
|
||||
*/
|
||||
render(moduleTemplate, renderContext) {
|
||||
const { hash, chunk, chunkGraph, runtimeTemplate } = renderContext;
|
||||
|
||||
let source = new ConcatSource();
|
||||
if (runtimeTemplate.supportsConst()) {
|
||||
source.add("/******/ (() => { // webpackBootstrap\n");
|
||||
} else {
|
||||
source.add("/******/ (function() { // webpackBootstrap\n");
|
||||
}
|
||||
|
||||
source.add("/******/ \tvar __webpack_modules__ = (");
|
||||
source.add(
|
||||
Template.renderChunkModules(
|
||||
renderContext,
|
||||
m => m.getSourceTypes().has("javascript"),
|
||||
moduleTemplate,
|
||||
"/******/ \t"
|
||||
)
|
||||
);
|
||||
source.add(");\n");
|
||||
|
||||
const bootstrap = this.renderBootstrap(renderContext);
|
||||
|
||||
source.add(
|
||||
"/************************************************************************/\n"
|
||||
);
|
||||
source.add(
|
||||
new PrefixSource(
|
||||
"/******/",
|
||||
new OriginalSource(
|
||||
Template.prefix(bootstrap.header, " \t") + "\n",
|
||||
"webpack/bootstrap"
|
||||
)
|
||||
)
|
||||
},
|
||||
"MainTemplate.getPublicPath is depreacted (use Compilation.getAssetPath(compilation.outputOptions.publicPath, options) instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_GET_PUBLIC_PATH"
|
||||
);
|
||||
|
||||
const runtimeModules = renderContext.chunkGraph.getChunkRuntimeModulesInOrder(
|
||||
chunk
|
||||
this.getAssetPath = util.deprecate(
|
||||
(path, options) => {
|
||||
return compilation.getAssetPath(path, options);
|
||||
},
|
||||
"MainTemplate.getAssetPath is deprecated (use Compilation.getAssetPath instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_GET_ASSET_PATH"
|
||||
);
|
||||
|
||||
if (runtimeModules.length > 0) {
|
||||
source.add(
|
||||
"/************************************************************************/\n"
|
||||
);
|
||||
source.add(
|
||||
Template.renderMainRuntimeModules(runtimeModules, renderContext)
|
||||
);
|
||||
}
|
||||
source.add(
|
||||
"/************************************************************************/\n"
|
||||
);
|
||||
source.add(
|
||||
new PrefixSource(
|
||||
"/******/",
|
||||
new OriginalSource(
|
||||
Template.prefix(bootstrap.startup, " \t") + "\n",
|
||||
"webpack/startup"
|
||||
)
|
||||
)
|
||||
);
|
||||
source.add("/******/ })()\n");
|
||||
|
||||
/** @type {Source} */
|
||||
let finalSource = source;
|
||||
if (chunkGraph.getNumberOfEntryModules(chunk) > 0) {
|
||||
finalSource = this.hooks.renderWithEntry.call(finalSource, chunk, hash);
|
||||
}
|
||||
if (!finalSource) {
|
||||
throw new Error(
|
||||
"Compiler error: MainTemplate plugin 'render' should return something"
|
||||
);
|
||||
}
|
||||
chunk.rendered = true;
|
||||
return new ConcatSource(finalSource, ";");
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {object} options get public path options
|
||||
* @returns {string} hook call
|
||||
*/
|
||||
getPublicPath(options) {
|
||||
return this.hooks.assetPath.call(
|
||||
this.outputOptions.publicPath || "",
|
||||
options,
|
||||
undefined
|
||||
this.getAssetPathWithInfo = util.deprecate(
|
||||
(path, options) => {
|
||||
return compilation.getAssetPathWithInfo(path, options);
|
||||
},
|
||||
"MainTemplate.getAssetPathWithInfo is deprecated (use Compilation.getAssetPath instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_GET_ASSET_PATH_WITH_INFO"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
getAssetPath(path, options) {
|
||||
return this.hooks.assetPath.call(path, options, undefined);
|
||||
}
|
||||
Object.defineProperty(MainTemplate.prototype, "requireFn", {
|
||||
get: util.deprecate(
|
||||
() => "__webpack_require__",
|
||||
'MainTemplate.requireFn is deprecated (use "__webpack_require__")',
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_REQUIRE_FN"
|
||||
)
|
||||
});
|
||||
|
||||
getAssetPathWithInfo(path, options) {
|
||||
const assetInfo = {};
|
||||
// TODO webpack 5: refactor assetPath hook to receive { path, info } object
|
||||
const newPath = this.hooks.assetPath.call(path, options, assetInfo);
|
||||
return { path: newPath, info: assetInfo };
|
||||
}
|
||||
Object.defineProperty(MainTemplate.prototype, "outputOptions", {
|
||||
get: util.deprecate(
|
||||
/**
|
||||
* @this {MainTemplate}
|
||||
* @returns {TODO} output options
|
||||
*/
|
||||
function() {
|
||||
return this._outputOptions;
|
||||
},
|
||||
"MainTemplate.outputOptions is deprecated (use Compilation.outputOptions instead)",
|
||||
"DEP_WEBPACK_MAIN_TEMPLATE_OUTPUT_OPTIONS"
|
||||
)
|
||||
});
|
||||
|
||||
/**
|
||||
* Updates hash with information from this template
|
||||
* @param {Hash} hash the hash to update
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHash(hash) {
|
||||
hash.update("maintemplate");
|
||||
hash.update("3");
|
||||
this.hooks.hash.call(hash);
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates hash with chunk-specific information from this template
|
||||
* @param {Hash} hash the hash to update
|
||||
* @param {Chunk} chunk the chunk
|
||||
* @param {UpdateHashForChunkContext} context options object
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHashForChunk(hash, chunk, context) {
|
||||
this.updateHash(hash);
|
||||
this.hooks.hashForChunk.call(hash, chunk);
|
||||
const bootstrap = this.renderBootstrap({
|
||||
hash: "0000",
|
||||
chunk,
|
||||
chunkGraph: context.chunkGraph,
|
||||
moduleGraph: context.moduleGraph,
|
||||
runtimeTemplate: context.runtimeTemplate
|
||||
});
|
||||
for (const key of Object.keys(bootstrap)) {
|
||||
hash.update(key);
|
||||
for (const line of bootstrap[key]) {
|
||||
hash.update(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
module.exports = MainTemplate;
|
||||
|
|
|
@ -6,9 +6,10 @@
|
|||
"use strict";
|
||||
|
||||
const { ConcatSource } = require("webpack-sources");
|
||||
const RuntimeGlobals = require("./RuntimeGlobals");
|
||||
const JavascriptModulesPlugin = require("./JavascriptModulesPlugin");
|
||||
const Template = require("./Template");
|
||||
|
||||
/** @typedef {import("./Compiler")} Compiler */
|
||||
/** @typedef {import("./ModuleTemplate")} ModuleTemplate */
|
||||
|
||||
const joinIterableWithComma = iterable => {
|
||||
|
@ -53,66 +54,24 @@ const printExportsInfoToSource = (source, indent, exportsInfo) => {
|
|||
}
|
||||
};
|
||||
|
||||
class FunctionModuleTemplatePlugin {
|
||||
constructor({ compilation }) {
|
||||
this.compilation = compilation;
|
||||
}
|
||||
|
||||
class ModuleInfoHeaderPlugin {
|
||||
/**
|
||||
* @param {ModuleTemplate} moduleTemplate a module template
|
||||
* @param {Compiler} compiler the compiler
|
||||
* @returns {void}
|
||||
*/
|
||||
apply(moduleTemplate) {
|
||||
const arrow = this.compilation.runtimeTemplate.supportsArrowFunction();
|
||||
moduleTemplate.hooks.render.tap(
|
||||
"FunctionModuleTemplatePlugin",
|
||||
(moduleSource, module) => {
|
||||
const { chunkGraph } = this.compilation;
|
||||
const source = new ConcatSource();
|
||||
const args = [];
|
||||
const runtimeRequirements = chunkGraph.getModuleRuntimeRequirements(
|
||||
module
|
||||
);
|
||||
const needModule = runtimeRequirements.has(RuntimeGlobals.module);
|
||||
const needExports = runtimeRequirements.has(RuntimeGlobals.exports);
|
||||
const needRequire =
|
||||
runtimeRequirements.has(RuntimeGlobals.require) ||
|
||||
runtimeRequirements.has(RuntimeGlobals.requireScope);
|
||||
const needThisAsExports = runtimeRequirements.has(
|
||||
RuntimeGlobals.thisAsExports
|
||||
);
|
||||
if (needExports || needRequire || needModule)
|
||||
args.push(
|
||||
needModule
|
||||
? module.moduleArgument
|
||||
: "__unused" + module.moduleArgument
|
||||
);
|
||||
if (needExports || needRequire)
|
||||
args.push(
|
||||
needExports
|
||||
? module.exportsArgument
|
||||
: "__unused" + module.exportsArgument
|
||||
);
|
||||
if (needRequire) args.push("__webpack_require__");
|
||||
if (arrow && !needThisAsExports) {
|
||||
source.add("/***/ ((" + args.join(", ") + ") => {\n\n");
|
||||
} else {
|
||||
source.add("/***/ (function(" + args.join(", ") + ") {\n\n");
|
||||
}
|
||||
if (module.buildInfo.strict) source.add('"use strict";\n');
|
||||
source.add(moduleSource);
|
||||
source.add("\n\n/***/ })");
|
||||
return source;
|
||||
}
|
||||
);
|
||||
|
||||
moduleTemplate.hooks.package.tap(
|
||||
"FunctionModuleTemplatePlugin",
|
||||
(moduleSource, module, { moduleGraph, chunkGraph }) => {
|
||||
if (moduleTemplate.runtimeTemplate.outputOptions.pathinfo) {
|
||||
apply(compiler) {
|
||||
compiler.hooks.compilation.tap("ModuleInfoHeaderPlugin", compilation => {
|
||||
const hooks = JavascriptModulesPlugin.getCompilationHooks(compilation);
|
||||
hooks.renderModulePackage.tap(
|
||||
"ModuleInfoHeaderPlugin",
|
||||
(
|
||||
moduleSource,
|
||||
module,
|
||||
{ chunkGraph, moduleGraph, runtimeTemplate }
|
||||
) => {
|
||||
const source = new ConcatSource();
|
||||
const req = module.readableIdentifier(
|
||||
moduleTemplate.runtimeTemplate.requestShortener
|
||||
runtimeTemplate.requestShortener
|
||||
);
|
||||
const reqStr = req.replace(/\*\//g, "*_/");
|
||||
const reqStrStar = "*".repeat(reqStr.length);
|
||||
|
@ -135,7 +94,7 @@ class FunctionModuleTemplatePlugin {
|
|||
for (const text of optimizationBailout) {
|
||||
let code;
|
||||
if (typeof text === "function") {
|
||||
code = text(moduleTemplate.runtimeTemplate.requestShortener);
|
||||
code = text(runtimeTemplate.requestShortener);
|
||||
} else {
|
||||
code = text;
|
||||
}
|
||||
|
@ -145,14 +104,12 @@ class FunctionModuleTemplatePlugin {
|
|||
source.add(moduleSource);
|
||||
return source;
|
||||
}
|
||||
return moduleSource;
|
||||
}
|
||||
);
|
||||
|
||||
moduleTemplate.hooks.hash.tap("FunctionModuleTemplatePlugin", hash => {
|
||||
hash.update("FunctionModuleTemplatePlugin");
|
||||
hash.update("2");
|
||||
);
|
||||
hooks.chunkHash.tap("ModuleInfoHeaderPlugin", (chunk, hash) => {
|
||||
hash.update("ModuleInfoHeaderPlugin");
|
||||
hash.update("1");
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
module.exports = FunctionModuleTemplatePlugin;
|
||||
module.exports = ModuleInfoHeaderPlugin;
|
|
@ -5,17 +5,23 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { SyncWaterfallHook, SyncHook } = require("tapable");
|
||||
const util = require("util");
|
||||
const memorize = require("./util/memorize");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("./Chunk")} Chunk */
|
||||
/** @typedef {import("./ChunkGraph")} ChunkGraph */
|
||||
/** @typedef {import("./Compilation")} Compilation */
|
||||
/** @typedef {import("./DependencyTemplates")} DependencyTemplates */
|
||||
/** @typedef {import("./Module")} Module */
|
||||
/** @typedef {import("./ModuleGraph")} ModuleGraph */
|
||||
/** @typedef {import("./RuntimeTemplate")} RuntimeTemplate */
|
||||
/** @typedef {import("./util/Hash")} Hash */
|
||||
|
||||
const getJavascriptModulesPlugin = memorize(() =>
|
||||
require("./JavascriptModulesPlugin")
|
||||
);
|
||||
|
||||
/**
|
||||
* @typedef {Object} RenderContext
|
||||
* @property {Chunk} chunk the chunk
|
||||
|
@ -25,77 +31,69 @@ const { SyncWaterfallHook, SyncHook } = require("tapable");
|
|||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
*/
|
||||
|
||||
// TODO webpack 6: remove this class
|
||||
module.exports = class ModuleTemplate {
|
||||
/**
|
||||
* @param {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @param {string} type the module template type
|
||||
* @param {Compilation} compilation the compilation
|
||||
*/
|
||||
constructor(runtimeTemplate, type) {
|
||||
constructor(runtimeTemplate, compilation) {
|
||||
this.runtimeTemplate = runtimeTemplate;
|
||||
this.type = type;
|
||||
this.type = "javascript";
|
||||
this.hooks = Object.freeze({
|
||||
/** @type {SyncWaterfallHook<[Source, Module, RenderContext]>} */
|
||||
content: new SyncWaterfallHook(["source", "module", "context"]),
|
||||
/** @type {SyncWaterfallHook<[Source, Module, RenderContext]>} */
|
||||
module: new SyncWaterfallHook(["source", "module", "context"]),
|
||||
/** @type {SyncWaterfallHook<[Source, Module, RenderContext]>} */
|
||||
render: new SyncWaterfallHook(["source", "module", "context"]),
|
||||
/** @type {SyncWaterfallHook<[Source, Module, RenderContext]>} */
|
||||
package: new SyncWaterfallHook(["source", "module", "context"]),
|
||||
/** @type {SyncHook<[Hash]>} */
|
||||
hash: new SyncHook(["hash"])
|
||||
content: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderModuleContent.tap(options, fn);
|
||||
},
|
||||
"ModuleTemplate.hooks.content is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderModuleContent instead)",
|
||||
"DEP_MODULE_TEMPLATE_CONTENT"
|
||||
)
|
||||
},
|
||||
module: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderModuleContent.tap(options, fn);
|
||||
},
|
||||
"ModuleTemplate.hooks.module is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderModuleContent instead)",
|
||||
"DEP_MODULE_TEMPLATE_MODULE"
|
||||
)
|
||||
},
|
||||
render: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderModuleContainer.tap(options, fn);
|
||||
},
|
||||
"ModuleTemplate.hooks.render is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderModuleContainer instead)",
|
||||
"DEP_MODULE_TEMPLATE_RENDER"
|
||||
)
|
||||
},
|
||||
package: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
getJavascriptModulesPlugin()
|
||||
.getCompilationHooks(compilation)
|
||||
.renderModulePackage.tap(options, fn);
|
||||
},
|
||||
"ModuleTemplate.hooks.package is deprecated (use JavascriptModulesPlugin.getCompilationHooks().renderModulePackage instead)",
|
||||
"DEP_MODULE_TEMPLATE_PACKAGE"
|
||||
)
|
||||
},
|
||||
hash: {
|
||||
tap: util.deprecate(
|
||||
(options, fn) => {
|
||||
compilation.hooks.fullHash.tap(options, fn);
|
||||
},
|
||||
"ModuleTemplate.hooks.package is deprecated (use Compilation.hooks.fullHash instead)",
|
||||
"DEP_MODULE_TEMPLATE_HASH"
|
||||
)
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module the module
|
||||
* @param {RenderContext} ctx render ctx
|
||||
* @returns {Source} the source
|
||||
*/
|
||||
render(module, ctx) {
|
||||
try {
|
||||
const {
|
||||
runtimeTemplate,
|
||||
dependencyTemplates,
|
||||
moduleGraph,
|
||||
chunkGraph
|
||||
} = ctx;
|
||||
const moduleSource = module.source({
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph,
|
||||
type: this.type
|
||||
});
|
||||
const moduleSourcePostContent = this.hooks.content.call(
|
||||
moduleSource,
|
||||
module,
|
||||
ctx
|
||||
);
|
||||
const moduleSourcePostModule = this.hooks.module.call(
|
||||
moduleSourcePostContent,
|
||||
module,
|
||||
ctx
|
||||
);
|
||||
const moduleSourcePostRender = this.hooks.render.call(
|
||||
moduleSourcePostModule,
|
||||
module,
|
||||
ctx
|
||||
);
|
||||
return this.hooks.package.call(moduleSourcePostRender, module, ctx);
|
||||
} catch (e) {
|
||||
e.message = `${module.identifier()}\n${e.message}`;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates hash with information from this template
|
||||
* @param {Hash} hash the hash to update
|
||||
* @returns {void}
|
||||
*/
|
||||
updateHash(hash) {
|
||||
hash.update("1");
|
||||
this.hooks.hash.call(hash);
|
||||
}
|
||||
};
|
||||
|
|
|
@ -44,7 +44,7 @@ const MATCH_PADDED_HYPHENS_REPLACE_REGEX = /^-|-$/g;
|
|||
* @property {string} hash
|
||||
* @property {string} fullHash
|
||||
* @property {TODO} outputOptions
|
||||
* @property {{asset: ModuleTemplate, javascript: ModuleTemplate, webassembly: ModuleTemplate}} moduleTemplates
|
||||
* @property {{javascript: ModuleTemplate}} moduleTemplates
|
||||
* @property {DependencyTemplates} dependencyTemplates
|
||||
* @property {RuntimeTemplate} runtimeTemplate
|
||||
* @property {ModuleGraph} moduleGraph
|
||||
|
@ -226,14 +226,14 @@ class Template {
|
|||
/**
|
||||
* @param {RenderContext} renderContext render context
|
||||
* @param {ModuleFilterPredicate} filterFn function used to filter modules from chunk to render
|
||||
* @param {ModuleTemplate} moduleTemplate ModuleTemplate instance used to render modules
|
||||
* @param {function(Module): Source} renderModule function to render a module
|
||||
* @param {string=} prefix applying prefix strings
|
||||
* @returns {Source} rendered chunk modules in a Source object
|
||||
*/
|
||||
static renderChunkModules(
|
||||
renderContext,
|
||||
filterFn,
|
||||
moduleTemplate,
|
||||
renderModule,
|
||||
prefix = ""
|
||||
) {
|
||||
const { chunk, chunkGraph } = renderContext;
|
||||
|
@ -256,7 +256,7 @@ class Template {
|
|||
const allModules = modules.map(module => {
|
||||
return {
|
||||
id: chunkGraph.getModuleId(module),
|
||||
source: moduleTemplate.render(module, renderContext)
|
||||
source: renderModule(module)
|
||||
};
|
||||
});
|
||||
if (removedModules && removedModules.length > 0) {
|
||||
|
|
|
@ -12,8 +12,8 @@ const JsonModulesPlugin = require("./JsonModulesPlugin");
|
|||
|
||||
const EvalDevToolModulePlugin = require("./EvalDevToolModulePlugin");
|
||||
const EvalSourceMapDevToolPlugin = require("./EvalSourceMapDevToolPlugin");
|
||||
const FunctionModulePlugin = require("./FunctionModulePlugin");
|
||||
const LoaderTargetPlugin = require("./LoaderTargetPlugin");
|
||||
const ModuleInfoHeaderPlugin = require("./ModuleInfoHeaderPlugin");
|
||||
const SourceMapDevToolPlugin = require("./SourceMapDevToolPlugin");
|
||||
|
||||
const EntryOptionPlugin = require("./EntryOptionPlugin");
|
||||
|
@ -81,7 +81,6 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
mangleImports: options.optimization.mangleWasmImports
|
||||
}).apply(compiler);
|
||||
new FetchCompileAsyncWasmPlugin().apply(compiler);
|
||||
new FunctionModulePlugin().apply(compiler);
|
||||
new NodeSourcePlugin(options.node).apply(compiler);
|
||||
new LoaderTargetPlugin(options.target).apply(compiler);
|
||||
break;
|
||||
|
@ -97,7 +96,6 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
mangleImports: options.optimization.mangleWasmImports
|
||||
}).apply(compiler);
|
||||
new FetchCompileAsyncWasmPlugin().apply(compiler);
|
||||
new FunctionModulePlugin().apply(compiler);
|
||||
new NodeSourcePlugin(options.node).apply(compiler);
|
||||
new LoaderTargetPlugin(options.target).apply(compiler);
|
||||
new StartupChunkDependenciesPlugin({
|
||||
|
@ -119,7 +117,6 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
mangleImports: options.optimization.mangleWasmImports
|
||||
}).apply(compiler);
|
||||
new ReadFileCompileAsyncWasmPlugin().apply(compiler);
|
||||
new FunctionModulePlugin().apply(compiler);
|
||||
new NodeTargetPlugin().apply(compiler);
|
||||
new LoaderTargetPlugin("node").apply(compiler);
|
||||
new StartupChunkDependenciesPlugin({
|
||||
|
@ -133,7 +130,6 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
const ExternalsPlugin = require("./ExternalsPlugin");
|
||||
const StartupChunkDependenciesPlugin = require("./runtime/StartupChunkDependenciesPlugin");
|
||||
new JsonpTemplatePlugin().apply(compiler);
|
||||
new FunctionModulePlugin().apply(compiler);
|
||||
new NodeTargetPlugin().apply(compiler);
|
||||
new ExternalsPlugin("commonjs", "nw.gui").apply(compiler);
|
||||
new LoaderTargetPlugin(options.target).apply(compiler);
|
||||
|
@ -150,7 +146,6 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
new NodeTemplatePlugin({
|
||||
asyncChunkLoading: true
|
||||
}).apply(compiler);
|
||||
new FunctionModulePlugin().apply(compiler);
|
||||
new NodeTargetPlugin().apply(compiler);
|
||||
new ExternalsPlugin("commonjs", [
|
||||
"app",
|
||||
|
@ -202,7 +197,6 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
mangleImports: options.optimization.mangleWasmImports
|
||||
}).apply(compiler);
|
||||
new FetchCompileAsyncWasmPlugin().apply(compiler);
|
||||
new FunctionModulePlugin().apply(compiler);
|
||||
new NodeTargetPlugin().apply(compiler);
|
||||
new ExternalsPlugin("commonjs", [
|
||||
"clipboard",
|
||||
|
@ -250,6 +244,10 @@ class WebpackOptionsApply extends OptionsApply {
|
|||
).apply(compiler);
|
||||
}
|
||||
|
||||
if (options.output.pathinfo) {
|
||||
new ModuleInfoHeaderPlugin().apply(compiler);
|
||||
}
|
||||
|
||||
if (
|
||||
options.devtool &&
|
||||
(options.devtool.includes("sourcemap") ||
|
||||
|
|
|
@ -17,8 +17,6 @@ const AssetParser = require("./AssetParser");
|
|||
/** @typedef {import("../Compiler")} Compiler */
|
||||
/** @typedef {import("../MainTemplate")} MainTemplate */
|
||||
/** @typedef {import("../Module")} Module */
|
||||
/** @typedef {import("../ModuleTemplate")} ModuleTemplate */
|
||||
/** @typedef {import("../ModuleTemplate").RenderContext} RenderContext */
|
||||
|
||||
const type = "asset";
|
||||
const plugin = "AssetModulesPlugin";
|
||||
|
@ -47,12 +45,7 @@ class AssetModulesPlugin {
|
|||
plugin,
|
||||
(result, options) => {
|
||||
const { chunkGraph, moduleGraph } = compilation;
|
||||
const {
|
||||
chunk,
|
||||
moduleTemplates,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate
|
||||
} = options;
|
||||
const { chunk, dependencyTemplates, runtimeTemplate } = options;
|
||||
|
||||
const { outputOptions } = runtimeTemplate;
|
||||
|
||||
|
@ -66,12 +59,12 @@ class AssetModulesPlugin {
|
|||
|
||||
result.push({
|
||||
render: () =>
|
||||
this.renderAsset(module, moduleTemplates.asset, {
|
||||
chunk,
|
||||
chunkGraph,
|
||||
moduleGraph,
|
||||
module.source({
|
||||
dependencyTemplates,
|
||||
runtimeTemplate
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph,
|
||||
type
|
||||
}),
|
||||
filenameTemplate,
|
||||
pathOptions: {
|
||||
|
@ -92,17 +85,6 @@ class AssetModulesPlugin {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param {Module} module the module to render
|
||||
* @param {ModuleTemplate} moduleTemplate the module template
|
||||
* @param {RenderContext} renderContext the render context
|
||||
* @returns {Source} the rendered source
|
||||
*/
|
||||
/* eslint-enable */
|
||||
renderAsset(module, moduleTemplate, renderContext) {
|
||||
return moduleTemplate.render(module, renderContext);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AssetModulesPlugin;
|
||||
|
|
|
@ -206,7 +206,7 @@ class ProfilingPlugin {
|
|||
"Context Module Factory"
|
||||
);
|
||||
interceptAllParserHooks(normalModuleFactory, tracer);
|
||||
interceptTemplateInstancesFrom(compilation, tracer);
|
||||
interceptAllJavascriptModulesPluginHooks(compilation, tracer);
|
||||
}
|
||||
);
|
||||
|
||||
|
@ -276,37 +276,6 @@ class ProfilingPlugin {
|
|||
}
|
||||
}
|
||||
|
||||
const interceptTemplateInstancesFrom = (compilation, tracer) => {
|
||||
const { mainTemplate, chunkTemplate, moduleTemplates } = compilation;
|
||||
|
||||
const { javascript, webassembly } = moduleTemplates;
|
||||
|
||||
[
|
||||
{
|
||||
instance: mainTemplate,
|
||||
name: "MainTemplate"
|
||||
},
|
||||
{
|
||||
instance: chunkTemplate,
|
||||
name: "ChunkTemplate"
|
||||
},
|
||||
{
|
||||
instance: javascript,
|
||||
name: "JavaScriptModuleTemplate"
|
||||
},
|
||||
{
|
||||
instance: webassembly,
|
||||
name: "WebAssemblyModuleTemplate"
|
||||
}
|
||||
].forEach(templateObject => {
|
||||
Object.keys(templateObject.instance.hooks).forEach(hookName => {
|
||||
templateObject.instance.hooks[hookName].intercept(
|
||||
makeInterceptorFor(templateObject.name, tracer)(hookName)
|
||||
);
|
||||
});
|
||||
});
|
||||
};
|
||||
|
||||
const interceptAllHooksFor = (instance, tracer, logLabel) => {
|
||||
if (Reflect.has(instance, "hooks")) {
|
||||
Object.keys(instance.hooks).forEach(hookName => {
|
||||
|
@ -336,6 +305,18 @@ const interceptAllParserHooks = (moduleFactory, tracer) => {
|
|||
});
|
||||
};
|
||||
|
||||
const interceptAllJavascriptModulesPluginHooks = (compilation, tracer) => {
|
||||
interceptAllHooksFor(
|
||||
{
|
||||
hooks: require("../JavascriptModulesPlugin").getCompilationHooks(
|
||||
compilation
|
||||
)
|
||||
},
|
||||
tracer,
|
||||
"JavascriptModulesPlugin"
|
||||
);
|
||||
};
|
||||
|
||||
const makeInterceptorFor = (instance, tracer) => hookName => ({
|
||||
register: ({ name, type, context, fn }) => {
|
||||
const newFn = makeNewProfiledTapFn(hookName, tracer, {
|
||||
|
|
|
@ -4,8 +4,16 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
/** @template T @typedef {function(): T} FunctionReturning */
|
||||
|
||||
/**
|
||||
* @template T
|
||||
* @param {FunctionReturning<T>} fn memorized function
|
||||
* @returns {FunctionReturning<T>} new function
|
||||
*/
|
||||
const memorize = fn => {
|
||||
let memorized = false;
|
||||
/** @type {T} */
|
||||
let result = undefined;
|
||||
return () => {
|
||||
if (memorized) {
|
||||
|
|
|
@ -5,18 +5,65 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { SyncWaterfallHook } = require("tapable");
|
||||
const Compilation = require("../Compilation");
|
||||
const Generator = require("../Generator");
|
||||
const { tryRunOrWebpackError } = require("../HookWebpackError");
|
||||
const WebAssemblyImportDependency = require("../dependencies/WebAssemblyImportDependency");
|
||||
const { compareModulesById } = require("../util/comparators");
|
||||
const AsyncWebAssemblyGenerator = require("./AsyncWebAssemblyGenerator");
|
||||
const AsyncWebAssemblyJavascriptGenerator = require("./AsyncWebAssemblyJavascriptGenerator");
|
||||
const AsyncWebAssemblyParser = require("./AsyncWebAssemblyParser");
|
||||
|
||||
/** @typedef {import("webpack-sources").Source} Source */
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
/** @typedef {import("../Module")} Module */
|
||||
/** @typedef {import("../Compilation")} Compilation */
|
||||
/** @typedef {import("../Template").RenderManifestOptions} RenderManifestOptions} */
|
||||
/** @typedef {import("../Template").RenderManifestEntry} RenderManifestEntry} */
|
||||
|
||||
/**
|
||||
* @typedef {Object} RenderContext
|
||||
* @property {Chunk} chunk the chunk
|
||||
* @property {DependencyTemplates} dependencyTemplates the dependency templates
|
||||
* @property {RuntimeTemplate} runtimeTemplate the runtime template
|
||||
* @property {ModuleGraph} moduleGraph the module graph
|
||||
* @property {ChunkGraph} chunkGraph the chunk graph
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} CompilationHooks
|
||||
* @property {SyncWaterfallHook<[Source, Module, RenderContext]>} renderModuleContent
|
||||
*/
|
||||
|
||||
/** @type {WeakMap<Compilation, CompilationHooks>} */
|
||||
const compilationHooksMap = new WeakMap();
|
||||
|
||||
class AsyncWebAssemblyModulesPlugin {
|
||||
/**
|
||||
* @param {Compilation} compilation the compilation
|
||||
* @returns {CompilationHooks} the attached hooks
|
||||
*/
|
||||
static getCompilationHooks(compilation) {
|
||||
if (!(compilation instanceof Compilation)) {
|
||||
throw new TypeError(
|
||||
"The 'compilation' argument must be an instance of JavascriptParser"
|
||||
);
|
||||
}
|
||||
let hooks = compilationHooksMap.get(compilation);
|
||||
if (hooks === undefined) {
|
||||
hooks = {
|
||||
renderModuleContent: new SyncWaterfallHook([
|
||||
"source",
|
||||
"module",
|
||||
"renderContext"
|
||||
])
|
||||
};
|
||||
compilationHooksMap.set(compilation, hooks);
|
||||
}
|
||||
return hooks;
|
||||
}
|
||||
|
||||
constructor(options) {
|
||||
this.options = options;
|
||||
}
|
||||
|
@ -29,6 +76,9 @@ class AsyncWebAssemblyModulesPlugin {
|
|||
compiler.hooks.compilation.tap(
|
||||
"AsyncWebAssemblyModulesPlugin",
|
||||
(compilation, { normalModuleFactory }) => {
|
||||
const hooks = AsyncWebAssemblyModulesPlugin.getCompilationHooks(
|
||||
compilation
|
||||
);
|
||||
compilation.dependencyFactories.set(
|
||||
WebAssemblyImportDependency,
|
||||
normalModuleFactory
|
||||
|
@ -50,62 +100,81 @@ class AsyncWebAssemblyModulesPlugin {
|
|||
});
|
||||
});
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {RenderManifestEntry[]} result render entries
|
||||
* @param {RenderManifestOptions} options context options
|
||||
* @returns {RenderManifestEntry[]} render entries
|
||||
*/
|
||||
const handler = (result, options) => {
|
||||
const { moduleGraph, chunkGraph, runtimeTemplate } = compilation;
|
||||
const chunk = options.chunk;
|
||||
const outputOptions = options.outputOptions;
|
||||
const moduleTemplates = options.moduleTemplates;
|
||||
const dependencyTemplates = options.dependencyTemplates;
|
||||
compilation.hooks.renderManifest.tap(
|
||||
"WebAssemblyModulesPlugin",
|
||||
(result, options) => {
|
||||
const { moduleGraph, chunkGraph, runtimeTemplate } = compilation;
|
||||
const chunk = options.chunk;
|
||||
const outputOptions = options.outputOptions;
|
||||
const dependencyTemplates = options.dependencyTemplates;
|
||||
|
||||
for (const module of chunkGraph.getOrderedChunkModulesIterable(
|
||||
chunk,
|
||||
compareModulesById(chunkGraph)
|
||||
)) {
|
||||
if (module.type === "webassembly/async") {
|
||||
const filenameTemplate = outputOptions.webassemblyModuleFilename;
|
||||
for (const module of chunkGraph.getOrderedChunkModulesIterable(
|
||||
chunk,
|
||||
compareModulesById(chunkGraph)
|
||||
)) {
|
||||
if (module.type === "webassembly/async") {
|
||||
const filenameTemplate =
|
||||
outputOptions.webassemblyModuleFilename;
|
||||
|
||||
result.push({
|
||||
render: () =>
|
||||
moduleTemplates.webassembly.render(module, {
|
||||
chunk,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
result.push({
|
||||
render: () =>
|
||||
this.renderModule(
|
||||
module,
|
||||
{
|
||||
chunk,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph
|
||||
},
|
||||
hooks
|
||||
),
|
||||
filenameTemplate,
|
||||
pathOptions: {
|
||||
module,
|
||||
chunkGraph
|
||||
}),
|
||||
filenameTemplate,
|
||||
pathOptions: {
|
||||
module,
|
||||
chunkGraph
|
||||
},
|
||||
auxiliary: true,
|
||||
identifier: `webassemblyAsyncModule${chunkGraph.getModuleId(
|
||||
module
|
||||
)}`,
|
||||
hash: chunkGraph.getModuleHash(module)
|
||||
});
|
||||
},
|
||||
auxiliary: true,
|
||||
identifier: `webassemblyAsyncModule${chunkGraph.getModuleId(
|
||||
module
|
||||
)}`,
|
||||
hash: chunkGraph.getModuleHash(module)
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
};
|
||||
compilation.chunkTemplate.hooks.renderManifest.tap(
|
||||
"WebAssemblyModulesPlugin",
|
||||
handler
|
||||
);
|
||||
compilation.mainTemplate.hooks.renderManifest.tap(
|
||||
"WebAssemblyModulesPlugin",
|
||||
handler
|
||||
return result;
|
||||
}
|
||||
);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
||||
renderModule(module, renderContext, hooks) {
|
||||
const {
|
||||
chunkGraph,
|
||||
moduleGraph,
|
||||
runtimeTemplate,
|
||||
dependencyTemplates
|
||||
} = renderContext;
|
||||
try {
|
||||
const moduleSource = module.source({
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph,
|
||||
type: "webassembly"
|
||||
});
|
||||
return tryRunOrWebpackError(
|
||||
() =>
|
||||
hooks.renderModuleContent.call(moduleSource, module, renderContext),
|
||||
"AsyncWebAssemblyModulesPlugin.getCompilationHooks().renderModuleContent"
|
||||
);
|
||||
} catch (e) {
|
||||
e.module = module;
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = AsyncWebAssemblyModulesPlugin;
|
||||
|
|
|
@ -64,7 +64,6 @@ class WebAssemblyModulesPlugin {
|
|||
const { moduleGraph, chunkGraph, runtimeTemplate } = compilation;
|
||||
const chunk = options.chunk;
|
||||
const outputOptions = options.outputOptions;
|
||||
const moduleTemplates = options.moduleTemplates;
|
||||
const dependencyTemplates = options.dependencyTemplates;
|
||||
|
||||
for (const module of chunkGraph.getOrderedChunkModulesIterable(
|
||||
|
@ -77,17 +76,12 @@ class WebAssemblyModulesPlugin {
|
|||
|
||||
result.push({
|
||||
render: () =>
|
||||
this.renderWebAssembly(
|
||||
module,
|
||||
moduleTemplates.webassembly,
|
||||
{
|
||||
chunk,
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph
|
||||
}
|
||||
),
|
||||
module.source({
|
||||
dependencyTemplates,
|
||||
runtimeTemplate,
|
||||
moduleGraph,
|
||||
chunkGraph
|
||||
}),
|
||||
filenameTemplate,
|
||||
pathOptions: {
|
||||
module,
|
||||
|
@ -132,17 +126,6 @@ class WebAssemblyModulesPlugin {
|
|||
}
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
*
|
||||
* @param {Module} module the wasm module
|
||||
* @param {ModuleTemplate} moduleTemplate the module tempalte
|
||||
* @param {RenderContext} renderContext render context
|
||||
* @returns {Source} rendered source
|
||||
*/
|
||||
renderWebAssembly(module, moduleTemplate, renderContext) {
|
||||
return moduleTemplate.render(module, renderContext);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = WebAssemblyModulesPlugin;
|
||||
|
|
|
@ -1294,7 +1294,7 @@
|
|||
},
|
||||
{
|
||||
"instanceof": "Function",
|
||||
"tsType": "Function"
|
||||
"tsType": "((pathData: import(\"../lib/Compilation\").PathData, assetInfo?: import(\"../lib/Compilation\").AssetInfo) => string)"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
|
|
@ -160,7 +160,10 @@ describe("StatsTestCases", () => {
|
|||
const testPath = path.join(base, testName);
|
||||
actual = actual
|
||||
.replace(/\r\n?/g, "\n")
|
||||
.replace(/\(.+\) DeprecationWarning.+(\n\s+at .*)*\n?/g, "")
|
||||
.replace(
|
||||
/\([^)]+\) (\[[^\]]+\]\s*)?DeprecationWarning.+(\n\s+at .*)*\n?/g,
|
||||
""
|
||||
)
|
||||
.replace(/[\t ]*Version:.+\n/g, "")
|
||||
.replace(new RegExp(quotemeta(testPath), "g"), "Xdir/" + testName)
|
||||
.replace(/(\w)\\(\w)/g, "$1/$2")
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -19,7 +19,7 @@ it("should include only one use strict per module", function() {
|
|||
|
||||
expect(matches).toEqual([
|
||||
'/* unused harmony default export */ var _unused_webpack_default_export = ("a");',
|
||||
"/******/",
|
||||
"/******/ // Check if module is in cache",
|
||||
"__webpack_require__.r(__webpack_exports__);",
|
||||
"__webpack_require__.r(__webpack_exports__);",
|
||||
"__webpack_require__.r(__webpack_exports__);",
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
const { CachedSource } = require("webpack-sources");
|
||||
const AsyncWebAssemblyModulesPlugin = require("../../../../lib/wasm-async/AsyncWebAssemblyModulesPlugin");
|
||||
|
||||
/** @typedef {import("../../../lib/Compilation")} Compilation */
|
||||
/** @typedef {import("../../../../lib/Compilation")} Compilation */
|
||||
|
||||
module.exports = {
|
||||
module: {
|
||||
|
@ -25,13 +26,12 @@ module.exports = {
|
|||
* @returns {void}
|
||||
*/
|
||||
compilation => {
|
||||
compilation.moduleTemplates.webassembly.hooks.package.tap(
|
||||
"Test",
|
||||
source => {
|
||||
// this is important to make each returned value a new instance
|
||||
return new CachedSource(source);
|
||||
}
|
||||
);
|
||||
AsyncWebAssemblyModulesPlugin.getCompilationHooks(
|
||||
compilation
|
||||
).renderModuleContent.tap("Test", source => {
|
||||
// this is important to make each returned value a new instance
|
||||
return new CachedSource(source);
|
||||
});
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -1,5 +1,4 @@
|
|||
const NodeTemplatePlugin = require("../../../../lib/node/NodeTemplatePlugin");
|
||||
const FunctionModulePlugin = require("../../../../lib/FunctionModulePlugin");
|
||||
const SingleEntryPlugin = require("../../../../lib/SingleEntryPlugin");
|
||||
|
||||
const compilerCache = new WeakMap();
|
||||
|
@ -14,7 +13,6 @@ module.exports = function(source) {
|
|||
},
|
||||
[
|
||||
new NodeTemplatePlugin(),
|
||||
new FunctionModulePlugin(),
|
||||
new SingleEntryPlugin(this.context, this.resource)
|
||||
]
|
||||
);
|
||||
|
|
Loading…
Reference in New Issue