add support for import chunk loading with runtime chunk
This commit is contained in:
parent
1bb0db3a86
commit
77ed50425d
|
@ -379,6 +379,7 @@ class Template {
|
|||
source.add(Template.toNormalComment(module.identifier()) + "\n");
|
||||
if (!module.shouldIsolate()) {
|
||||
source.add(runtimeSource);
|
||||
source.add("\n\n");
|
||||
} else if (renderContext.runtimeTemplate.supportsArrowFunction()) {
|
||||
source.add("(() => {\n");
|
||||
if (renderContext.useStrict) source.add('\t"use strict";\n');
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/*
|
||||
MIT License http://www.opensource.org/licenses/mit-license.php
|
||||
*/
|
||||
|
||||
"use strict";
|
||||
|
||||
const RuntimeModule = require("../RuntimeModule");
|
||||
|
||||
class ExportWebpackRequireRuntimeModule extends RuntimeModule {
|
||||
constructor() {
|
||||
super("export webpack runtime", RuntimeModule.STAGE_ATTACH);
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {boolean} true, if the runtime module should get it's own scope
|
||||
*/
|
||||
shouldIsolate() {
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* @returns {string} runtime code
|
||||
*/
|
||||
generate() {
|
||||
return "export default __webpack_require__;";
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = ExportWebpackRequireRuntimeModule;
|
|
@ -5,13 +5,18 @@
|
|||
|
||||
"use strict";
|
||||
|
||||
const { ConcatSource } = require("webpack-sources");
|
||||
const { ConcatSource, RawSource } = require("webpack-sources");
|
||||
const { RuntimeGlobals } = require("..");
|
||||
const HotUpdateChunk = require("../HotUpdateChunk");
|
||||
const Template = require("../Template");
|
||||
const {
|
||||
getCompilationHooks
|
||||
getCompilationHooks,
|
||||
getChunkFilenameTemplate
|
||||
} = require("../javascript/JavascriptModulesPlugin");
|
||||
const {
|
||||
generateEntryStartup,
|
||||
updateHashForEntryStartup
|
||||
} = require("../javascript/StartupHelpers");
|
||||
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
|
||||
|
@ -30,8 +35,9 @@ class ModuleChunkFormatPlugin {
|
|||
(chunk, set) => {
|
||||
if (chunk.hasRuntime()) return;
|
||||
if (compilation.chunkGraph.getNumberOfEntryModules(chunk) > 0) {
|
||||
set.add(RuntimeGlobals.onChunksLoaded);
|
||||
set.add(RuntimeGlobals.require);
|
||||
set.add(RuntimeGlobals.startupEntrypoint);
|
||||
set.add(RuntimeGlobals.externalInstallChunk);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -39,7 +45,7 @@ class ModuleChunkFormatPlugin {
|
|||
hooks.renderChunk.tap(
|
||||
"ModuleChunkFormatPlugin",
|
||||
(modules, renderContext) => {
|
||||
const { chunk, chunkGraph } = renderContext;
|
||||
const { chunk, chunkGraph, runtimeTemplate } = renderContext;
|
||||
const hotUpdateChunk =
|
||||
chunk instanceof HotUpdateChunk ? chunk : null;
|
||||
const source = new ConcatSource();
|
||||
|
@ -68,9 +74,84 @@ class ModuleChunkFormatPlugin {
|
|||
chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
|
||||
);
|
||||
if (entries.length > 0) {
|
||||
throw new Error(
|
||||
"Entry modules in chunk is not implemented for module chunk format yet"
|
||||
const runtimeChunk = entries[0][1].getRuntimeChunk();
|
||||
const currentOutputName = compilation
|
||||
.getPath(
|
||||
getChunkFilenameTemplate(chunk, compilation.outputOptions),
|
||||
{
|
||||
chunk,
|
||||
contentHashType: "javascript"
|
||||
}
|
||||
)
|
||||
.split("/");
|
||||
const runtimeOutputName = compilation
|
||||
.getPath(
|
||||
getChunkFilenameTemplate(
|
||||
runtimeChunk,
|
||||
compilation.outputOptions
|
||||
),
|
||||
{
|
||||
chunk: runtimeChunk,
|
||||
contentHashType: "javascript"
|
||||
}
|
||||
)
|
||||
.split("/");
|
||||
|
||||
// remove filename, we only need the directory
|
||||
const outputFilename = currentOutputName.pop();
|
||||
|
||||
// remove common parts
|
||||
while (
|
||||
currentOutputName.length > 0 &&
|
||||
runtimeOutputName.length > 0 &&
|
||||
currentOutputName[0] === runtimeOutputName[0]
|
||||
) {
|
||||
currentOutputName.shift();
|
||||
runtimeOutputName.shift();
|
||||
}
|
||||
|
||||
// create final path
|
||||
const runtimePath =
|
||||
(currentOutputName.length > 0
|
||||
? "../".repeat(currentOutputName.length)
|
||||
: "./") + runtimeOutputName.join("/");
|
||||
|
||||
const entrySource = new ConcatSource();
|
||||
entrySource.add(source);
|
||||
entrySource.add(";\n\n// load runtime\n");
|
||||
entrySource.add(
|
||||
`import __webpack_require__ from ${JSON.stringify(
|
||||
runtimePath
|
||||
)};\n`
|
||||
);
|
||||
entrySource.add(
|
||||
`import * as __webpack_self_exports__ from ${JSON.stringify(
|
||||
"./" + outputFilename
|
||||
)};\n`
|
||||
);
|
||||
entrySource.add(
|
||||
`${RuntimeGlobals.externalInstallChunk}(__webpack_self_exports__);\n`
|
||||
);
|
||||
const startupSource = new RawSource(
|
||||
generateEntryStartup(
|
||||
chunkGraph,
|
||||
runtimeTemplate,
|
||||
entries,
|
||||
chunk,
|
||||
false
|
||||
)
|
||||
);
|
||||
entrySource.add(
|
||||
hooks.renderStartup.call(
|
||||
startupSource,
|
||||
entries[entries.length - 1][0],
|
||||
{
|
||||
...renderContext,
|
||||
inlined: false
|
||||
}
|
||||
)
|
||||
);
|
||||
return entrySource;
|
||||
}
|
||||
}
|
||||
return source;
|
||||
|
@ -82,11 +163,10 @@ class ModuleChunkFormatPlugin {
|
|||
if (chunk.hasRuntime()) return;
|
||||
hash.update("ModuleChunkFormatPlugin");
|
||||
hash.update("1");
|
||||
// TODO
|
||||
// const entries = Array.from(
|
||||
// chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
|
||||
// );
|
||||
// updateHashForEntryStartup(hash, chunkGraph, entries, chunk);
|
||||
const entries = Array.from(
|
||||
chunkGraph.getChunkEntryModulesWithChunkGroupIterable(chunk)
|
||||
);
|
||||
updateHashForEntryStartup(hash, chunkGraph, entries, chunk);
|
||||
}
|
||||
);
|
||||
}
|
||||
|
|
|
@ -6,6 +6,7 @@
|
|||
"use strict";
|
||||
|
||||
const RuntimeGlobals = require("../RuntimeGlobals");
|
||||
const ExportWebpackRequireRuntimeModule = require("./ExportWebpackRequireRuntimeModule");
|
||||
const ModuleChunkLoadingRuntimeModule = require("./ModuleChunkLoadingRuntimeModule");
|
||||
|
||||
/** @typedef {import("../Compiler")} Compiler */
|
||||
|
@ -45,9 +46,21 @@ class ModuleChunkLoadingPlugin {
|
|||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.baseURI)
|
||||
.tap("ModuleChunkLoadingPlugin", handler);
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.externalInstallChunk)
|
||||
.tap("ModuleChunkLoadingPlugin", handler);
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.onChunksLoaded)
|
||||
.tap("ModuleChunkLoadingPlugin", handler);
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.externalInstallChunk)
|
||||
.tap("ModuleChunkLoadingPlugin", (chunk, set) => {
|
||||
if (!isEnabledForChunk(chunk)) return;
|
||||
compilation.addRuntimeModule(
|
||||
chunk,
|
||||
new ExportWebpackRequireRuntimeModule()
|
||||
);
|
||||
});
|
||||
|
||||
compilation.hooks.runtimeRequirementInTree
|
||||
.for(RuntimeGlobals.ensureChunkHandlers)
|
||||
|
|
|
@ -67,6 +67,9 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
|
|||
} = compilation;
|
||||
const fn = RuntimeGlobals.ensureChunkHandlers;
|
||||
const withBaseURI = this._runtimeRequirements.has(RuntimeGlobals.baseURI);
|
||||
const withExternalInstallChunk = this._runtimeRequirements.has(
|
||||
RuntimeGlobals.externalInstallChunk
|
||||
);
|
||||
const withLoading = this._runtimeRequirements.has(
|
||||
RuntimeGlobals.ensureChunkHandlers
|
||||
);
|
||||
|
@ -110,6 +113,38 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
|
|||
),
|
||||
"};",
|
||||
"",
|
||||
withLoading || withExternalInstallChunk
|
||||
? `var installChunk = ${runtimeTemplate.basicFunction("data", [
|
||||
runtimeTemplate.destructureObject(
|
||||
["ids", "modules", "runtime"],
|
||||
"data"
|
||||
),
|
||||
'// add "modules" to the modules object,',
|
||||
'// then flag all "ids" as loaded and fire callback',
|
||||
"var moduleId, chunkId, i = 0;",
|
||||
"for(moduleId in modules) {",
|
||||
Template.indent([
|
||||
`if(${RuntimeGlobals.hasOwnProperty}(modules, moduleId)) {`,
|
||||
Template.indent(
|
||||
`${RuntimeGlobals.moduleFactories}[moduleId] = modules[moduleId];`
|
||||
),
|
||||
"}"
|
||||
]),
|
||||
"}",
|
||||
"if(runtime) runtime(__webpack_require__);",
|
||||
"for(;i < ids.length; i++) {",
|
||||
Template.indent([
|
||||
"chunkId = ids[i];",
|
||||
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
|
||||
Template.indent("installedChunks[chunkId][0]();"),
|
||||
"}",
|
||||
"installedChunks[ids[i]] = 0;"
|
||||
]),
|
||||
"}",
|
||||
withOnChunkLoad ? `${RuntimeGlobals.onChunksLoaded}();` : ""
|
||||
])}`
|
||||
: "// no install chunk",
|
||||
"",
|
||||
withLoading
|
||||
? Template.asString([
|
||||
`${fn}.j = ${runtimeTemplate.basicFunction(
|
||||
|
@ -137,45 +172,13 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
|
|||
rootOutputDir
|
||||
)} + ${
|
||||
RuntimeGlobals.getChunkScriptFilename
|
||||
}(chunkId)).then(${runtimeTemplate.basicFunction(
|
||||
"data",
|
||||
}(chunkId)).then(installChunk, ${runtimeTemplate.basicFunction(
|
||||
"e",
|
||||
[
|
||||
runtimeTemplate.destructureObject(
|
||||
["ids", "modules", "runtime"],
|
||||
"data"
|
||||
),
|
||||
'// add "modules" to the modules object,',
|
||||
'// then flag all "ids" as loaded and fire callback',
|
||||
"var moduleId, chunkId, i = 0;",
|
||||
"for(moduleId in modules) {",
|
||||
Template.indent([
|
||||
`if(${RuntimeGlobals.hasOwnProperty}(modules, moduleId)) {`,
|
||||
Template.indent(
|
||||
`${RuntimeGlobals.moduleFactories}[moduleId] = modules[moduleId];`
|
||||
),
|
||||
"}"
|
||||
]),
|
||||
"}",
|
||||
"if(runtime) runtime(__webpack_require__);",
|
||||
"for(;i < ids.length; i++) {",
|
||||
Template.indent([
|
||||
"chunkId = ids[i];",
|
||||
`if(${RuntimeGlobals.hasOwnProperty}(installedChunks, chunkId) && installedChunks[chunkId]) {`,
|
||||
Template.indent(
|
||||
"installedChunks[chunkId][0]();"
|
||||
),
|
||||
"}",
|
||||
"installedChunks[ids[i]] = 0;"
|
||||
]),
|
||||
"}",
|
||||
withOnChunkLoad
|
||||
? `${RuntimeGlobals.onChunksLoaded}();`
|
||||
: ""
|
||||
"if(installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;",
|
||||
"throw e;"
|
||||
]
|
||||
)}, ${runtimeTemplate.basicFunction("e", [
|
||||
"if(installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;",
|
||||
"throw e;"
|
||||
])});`,
|
||||
)});`,
|
||||
`var promise = Promise.race([promise, new Promise(${runtimeTemplate.expressionFunction(
|
||||
`installedChunkData = installedChunks[chunkId] = [resolve]`,
|
||||
"resolve"
|
||||
|
@ -193,6 +196,12 @@ class ModuleChunkLoadingRuntimeModule extends RuntimeModule {
|
|||
])
|
||||
: "// no chunk on demand loading",
|
||||
"",
|
||||
withExternalInstallChunk
|
||||
? Template.asString([
|
||||
`${RuntimeGlobals.externalInstallChunk} = installChunk;`
|
||||
])
|
||||
: "// no external install chunk",
|
||||
"",
|
||||
withOnChunkLoad
|
||||
? `${
|
||||
RuntimeGlobals.onChunksLoaded
|
||||
|
|
|
@ -17,6 +17,24 @@ module.exports = (env, { testPath }) => [
|
|||
outputModule: true
|
||||
}
|
||||
},
|
||||
{
|
||||
output: {
|
||||
filename: "esm-runtimeChunk/[name].js",
|
||||
libraryTarget: "module"
|
||||
},
|
||||
target: "node14",
|
||||
resolve: {
|
||||
alias: {
|
||||
external: "./non-external"
|
||||
}
|
||||
},
|
||||
optimization: {
|
||||
runtimeChunk: "single"
|
||||
},
|
||||
experiments: {
|
||||
outputModule: true
|
||||
}
|
||||
},
|
||||
{
|
||||
output: {
|
||||
filename: "commonjs.js",
|
||||
|
|
|
@ -14,6 +14,21 @@ module.exports = (env, { testPath }) => [
|
|||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
resolve: {
|
||||
alias: {
|
||||
library: path.resolve(
|
||||
testPath,
|
||||
"../0-create-library/esm-runtimeChunk/main.js"
|
||||
)
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
NAME: JSON.stringify("esm-runtimeChunk")
|
||||
})
|
||||
]
|
||||
},
|
||||
{
|
||||
resolve: {
|
||||
alias: {
|
||||
|
|
Loading…
Reference in New Issue