/
githubmirror
/
webpack
Обзор
Документация
Войти
/
githubmirror
/
webpack
Код
Запросы
0
Пакеты
0
Релизы
0
Аналитика
Безопасность
v5.108.2
lib/runtime/LoadScriptRuntimeModule.js
165 строк
5 KB
Xiao
refactor: extract createHooksRegistry to deduplicate getCompilationHooks pattern (#21224)
26 июн 2026, 16:27
Не верифицирован
26 июн 2026, 16:27
5e7db5d
Код
Авторство
О чём код?
/* MIT License http://www.opensource.org/licenses/mit-license.php */ "use strict"; const { SyncWaterfallHook } = require("tapable"); /** @typedef {import("../Compilation")} Compilation */ const RuntimeGlobals = require("../RuntimeGlobals"); const Template = require("../Template"); const createHooksRegistry = require("../util/createHooksRegistry"); const HelperRuntimeModule = require("./HelperRuntimeModule"); /** @typedef {import("../Chunk")} Chunk */ /** * @typedef {object} LoadScriptCompilationHooks * @property {SyncWaterfallHook<[string, Chunk]>} createScript */ class LoadScriptRuntimeModule extends HelperRuntimeModule { /** * @param {boolean=} withCreateScriptUrl use create script url for trusted types * @param {boolean=} withFetchPriority use `fetchPriority` attribute */ constructor(withCreateScriptUrl, withFetchPriority) { super("load script"); /** @type {boolean | undefined} */ this._withCreateScriptUrl = withCreateScriptUrl; /** @type {boolean | undefined} */ this._withFetchPriority = withFetchPriority; } /** * Generates runtime code for this runtime module. * @returns {string | null} runtime code */ generate() { const compilation = /** @type {Compilation} */ (this.compilation); const { runtimeTemplate, outputOptions } = compilation; const { scriptType, chunkLoadTimeout: loadTimeout, crossOriginLoading, uniqueName, charset } = outputOptions; const fn = RuntimeGlobals.loadScript; const { createScript } = LoadScriptRuntimeModule.getCompilationHooks(compilation); const code = Template.asString([ "script = document.createElement('script');", scriptType ? `script.type = ${JSON.stringify(scriptType)};` : "", charset ? "script.charset = 'utf-8';" : "", `if (${RuntimeGlobals.scriptNonce}) {`, Template.indent( `script.setAttribute("nonce", ${RuntimeGlobals.scriptNonce});` ), "}", uniqueName ? 'script.setAttribute("data-webpack", dataWebpackPrefix + key);' : "", this._withFetchPriority ? Template.asString([ "if(fetchPriority) {", Template.indent( 'script.setAttribute("fetchpriority", fetchPriority);' ), "}" ]) : "", `script.src = ${ this._withCreateScriptUrl ? `${RuntimeGlobals.createScriptUrl}(url)` : "url" };`, crossOriginLoading ? crossOriginLoading === "use-credentials" ? 'script.crossOrigin = "use-credentials";' : Template.asString([ "if (script.src.indexOf(window.location.origin + '/') !== 0) {", Template.indent( `script.crossOrigin = ${JSON.stringify(crossOriginLoading)};` ), "}" ]) : "" ]); const cst = runtimeTemplate.renderConst(); const lt = runtimeTemplate.renderLet(); return Template.asString([ `${cst} inProgress = {};`, uniqueName ? `${cst} dataWebpackPrefix = ${JSON.stringify(`${uniqueName}:`)};` : "// data-webpack is not used as build has no uniqueName", "// loadScript function to load a script via script tag", `${fn} = ${runtimeTemplate.basicFunction( `url, done, key, chunkId${ this._withFetchPriority ? ", fetchPriority" : "" }`, [ "if(inProgress[url]) { inProgress[url].push(done); return; }", `${lt} script, needAttach;`, "if(key !== undefined) {", Template.indent([ `${cst} scripts = document.getElementsByTagName("script");`, "for(var i = 0; i < scripts.length; i++) {", Template.indent([ `${cst} s = scripts[i];`, `if(s.getAttribute("src") == url${ uniqueName ? ' || s.getAttribute("data-webpack") == dataWebpackPrefix + key' : "" }) { script = s; break; }` ]), "}" ]), "}", "if(!script) {", Template.indent([ "needAttach = true;", createScript.call(code, /** @type {Chunk} */ (this.chunk)) ]), "}", "inProgress[url] = [done];", `${cst} onScriptComplete = ${runtimeTemplate.basicFunction( "prev, event", Template.asString([ "// avoid mem leaks in IE.", "script.onerror = script.onload = null;", "clearTimeout(timeout);", `${cst} doneFns = inProgress[url];`, "delete inProgress[url];", `${runtimeTemplate.optionalChaining( "script.parentNode", "removeChild(script)" )};`, `${runtimeTemplate.optionalChaining( "doneFns", `forEach(${runtimeTemplate.returningFunction("fn(event)", "fn")})` )};`, "if(prev) return prev(event);" ]) )}`, `${cst} timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), ${loadTimeout});`, "script.onerror = onScriptComplete.bind(null, script.onerror);", "script.onload = onScriptComplete.bind(null, script.onload);", "needAttach && document.head.appendChild(script);" ] )};` ]); } } LoadScriptRuntimeModule.getCompilationHooks = createHooksRegistry( () => /** @type {LoadScriptCompilationHooks} */ ({ createScript: new SyncWaterfallHook(["source", "chunk"]) }) ); module.exports = LoadScriptRuntimeModule;