webpack/lib/web/JsonpTemplatePlugin.js

175 lines
5.7 KiB
JavaScript
Raw Normal View History

2013-01-31 01:49:25 +08:00
/*
MIT License http://www.opensource.org/licenses/mit-license.php
Author Tobias Koppers @sokra
*/
2018-07-30 23:08:51 +08:00
"use strict";
const { SyncWaterfallHook } = require("tapable");
const Compilation = require("../Compilation");
const RuntimeGlobals = require("../RuntimeGlobals");
const Template = require("../Template");
const ArrayPushCallbackChunkFormatPlugin = require("../javascript/ArrayPushCallbackChunkFormatPlugin");
const JsonpChunkLoadingRuntimeModule = require("./JsonpChunkLoadingRuntimeModule");
const { needEntryDeferringCode } = require("./JsonpHelpers");
/** @typedef {import("../Chunk")} Chunk */
/** @typedef {import("../Compilation")} Compilation */
2018-11-09 05:59:19 +08:00
/** @typedef {import("../Compiler")} Compiler */
/**
* @typedef {Object} JsonpCompilationPluginHooks
2018-12-09 19:54:17 +08:00
* @property {SyncWaterfallHook<[string, Chunk, string]>} linkPreload
* @property {SyncWaterfallHook<[string, Chunk, string]>} linkPrefetch
*/
/** @type {WeakMap<Compilation, JsonpCompilationPluginHooks>} */
const compilationHooksMap = new WeakMap();
class JsonpTemplatePlugin {
/**
* @param {Compilation} compilation the compilation
* @returns {JsonpCompilationPluginHooks} hooks
*/
static getCompilationHooks(compilation) {
if (!(compilation instanceof Compilation)) {
throw new TypeError(
"The 'compilation' argument must be an instance of Compilation"
);
}
let hooks = compilationHooksMap.get(compilation);
if (hooks === undefined) {
hooks = {
linkPreload: new SyncWaterfallHook(["source", "chunk", "hash"]),
linkPrefetch: new SyncWaterfallHook(["source", "chunk", "hash"])
};
compilationHooksMap.set(compilation, hooks);
}
return hooks;
}
2018-11-09 05:59:19 +08:00
/**
2020-04-23 16:48:36 +08:00
* Apply the plugin
2018-11-09 05:59:19 +08:00
* @param {Compiler} compiler the compiler instance
* @returns {void}
*/
apply(compiler) {
new ArrayPushCallbackChunkFormatPlugin().apply(compiler);
2018-02-25 09:00:20 +08:00
compiler.hooks.thisCompilation.tap("JsonpTemplatePlugin", compilation => {
const {
linkPreload,
linkPrefetch
} = JsonpTemplatePlugin.getCompilationHooks(compilation);
linkPreload.tap("JsonpTemplatePlugin", (_, chunk, hash) => {
2020-06-25 04:05:21 +08:00
const { crossOriginLoading, scriptType } = compilation.outputOptions;
return Template.asString([
"var link = document.createElement('link');",
2020-06-25 04:05:21 +08:00
scriptType ? `link.type = ${JSON.stringify(scriptType)};` : "",
"link.charset = 'utf-8';",
`if (${RuntimeGlobals.scriptNonce}) {`,
Template.indent(
`link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
),
"}",
'link.rel = "preload";',
'link.as = "script";',
2019-06-13 16:51:12 +08:00
`link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(chunkId);`,
crossOriginLoading
? Template.asString([
"if (link.href.indexOf(window.location.origin + '/') !== 0) {",
Template.indent(
`link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
),
"}"
])
: ""
]);
});
linkPrefetch.tap("JsonpTemplatePlugin", (_, chunk, hash) => {
const { crossOriginLoading } = compilation.outputOptions;
return Template.asString([
"var link = document.createElement('link');",
crossOriginLoading
? `link.crossOrigin = ${JSON.stringify(crossOriginLoading)};`
: "",
`if (${RuntimeGlobals.scriptNonce}) {`,
Template.indent(
`link.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});`
),
"}",
'link.rel = "prefetch";',
'link.as = "script";',
2019-06-13 16:51:12 +08:00
`link.href = ${RuntimeGlobals.publicPath} + ${RuntimeGlobals.getChunkScriptFilename}(chunkId);`
]);
});
const onceForChunkSet = new WeakSet();
const handler = (chunk, set) => {
if (onceForChunkSet.has(chunk)) return;
onceForChunkSet.add(chunk);
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
2019-12-03 21:27:39 +08:00
set.add(RuntimeGlobals.hasOwnProperty);
compilation.addRuntimeModule(
chunk,
2020-08-19 21:05:49 +08:00
new JsonpChunkLoadingRuntimeModule(set, linkPreload, linkPrefetch)
);
};
RuntimeGlobals.ensureChunkHandlers;
RuntimeGlobals.hmrDownloadUpdateHandlers;
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.ensureChunkHandlers)
.tap("JsonpTemplatePlugin", handler);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
.tap("JsonpTemplatePlugin", handler);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hmrDownloadManifest)
.tap("JsonpTemplatePlugin", handler);
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.ensureChunkHandlers)
.tap("JsonpTemplatePlugin", (chunk, set) => {
set.add(RuntimeGlobals.publicPath);
set.add(RuntimeGlobals.loadScript);
set.add(RuntimeGlobals.getChunkScriptFilename);
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hmrDownloadUpdateHandlers)
.tap("JsonpTemplatePlugin", (chunk, set) => {
set.add(RuntimeGlobals.publicPath);
set.add(RuntimeGlobals.loadScript);
set.add(RuntimeGlobals.getChunkUpdateScriptFilename);
set.add(RuntimeGlobals.moduleCache);
set.add(RuntimeGlobals.hmrModuleData);
set.add(RuntimeGlobals.moduleFactoriesAddOnly);
});
compilation.hooks.runtimeRequirementInTree
.for(RuntimeGlobals.hmrDownloadManifest)
.tap("JsonpTemplatePlugin", (chunk, set) => {
set.add(RuntimeGlobals.publicPath);
set.add(RuntimeGlobals.getUpdateManifestFilename);
});
compilation.hooks.additionalTreeRuntimeRequirements.tap(
"JsonpTemplatePlugin",
(chunk, set) => {
const withDefer = needEntryDeferringCode(compilation, chunk);
if (withDefer) {
set.add(RuntimeGlobals.startup);
set.add(RuntimeGlobals.startupNoDefault);
handler(chunk, set);
}
if (withDefer) {
set.add(RuntimeGlobals.require);
}
}
);
});
}
}
2013-01-31 01:49:25 +08:00
module.exports = JsonpTemplatePlugin;