Skip to content

fix: port public path of module chunk loading from webpack #10425

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion crates/rspack_plugin_runtime/src/module_chunk_loading.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
use rspack_core::{
ChunkLoading, ChunkLoadingType, ChunkUkey, Compilation, CompilationRuntimeRequirementInTree,
Plugin, PluginContext, RuntimeGlobals, RuntimeModuleExt,
Plugin, PluginContext, PublicPath, RuntimeGlobals, RuntimeModuleExt,
};
use rspack_error::Result;
use rspack_hook::{plugin, plugin_hook};
Expand Down Expand Up @@ -30,6 +30,11 @@ async fn runtime_requirements_in_tree(
match runtime_requirement {
RuntimeGlobals::ENSURE_CHUNK_HANDLERS if is_enabled_for_chunk => {
has_chunk_loading = true;

if !matches!(compilation.options.output.public_path, PublicPath::Auto) {
runtime_requirements_mut.insert(RuntimeGlobals::PUBLIC_PATH);
}

runtime_requirements_mut.insert(RuntimeGlobals::GET_CHUNK_SCRIPT_FILENAME);
}
RuntimeGlobals::EXTERNAL_INSTALL_CHUNK if is_enabled_for_chunk => {
Expand All @@ -40,6 +45,11 @@ async fn runtime_requirements_in_tree(
RuntimeGlobals::ON_CHUNKS_LOADED | RuntimeGlobals::BASE_URI if is_enabled_for_chunk => {
has_chunk_loading = true;
}
RuntimeGlobals::PREFETCH_CHUNK_HANDLERS | RuntimeGlobals::PRELOAD_CHUNK_HANDLERS => {
if is_enabled_for_chunk {
runtime_requirements_mut.insert(RuntimeGlobals::PUBLIC_PATH);
}
}
_ => {}
}
}
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use rspack_collections::{DatabaseItem, Identifier};
use rspack_core::{
compile_boolean_matcher, impl_runtime_module, BooleanMatcher, Chunk, ChunkUkey, Compilation,
RuntimeGlobals, RuntimeModule, RuntimeModuleStage,
PublicPath, RuntimeGlobals, RuntimeModule, RuntimeModuleStage,
};

use super::utils::{chunk_has_js, get_output_dir};
Expand Down Expand Up @@ -142,12 +142,17 @@ impl RuntimeModule for ModuleChunkLoadingRuntimeModule {
let body = if matches!(has_js_matcher, BooleanMatcher::Condition(false)) {
"installedChunks[chunkId] = 0;".to_string()
} else {
let output_dir = if matches!(compilation.options.output.public_path, PublicPath::Auto) {
serde_json::to_string(&root_output_dir).expect("should able to serde_json::to_string")
} else {
RuntimeGlobals::PUBLIC_PATH.to_string()
};
compilation.runtime_template.render(
&self.template(TemplateId::WithLoading),
Some(serde_json::json!({
"_js_matcher": &has_js_matcher.render("chunkId"),
"_import_function_name":&compilation.options.output.import_function_name,
"_output_dir": &root_output_dir,
"_output_dir": &output_dir,
"_match_fallback": if matches!(has_js_matcher, BooleanMatcher::Condition(true)) {
""
} else {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ if (installedChunkData !== 0) { // 0 means "already installed".'
} else {
if (<%- _js_matcher %>) {
// setup Promise in chunk cache
var promise = <%- _import_function_name %>("<%- _output_dir %>" + <%- GET_CHUNK_SCRIPT_FILENAME %>(chunkId)).then(installChunk, <%- basicFunction("e") %> {
var promise = <%- _import_function_name %>(<%- _output_dir %> + <%- GET_CHUNK_SCRIPT_FILENAME %>(chunkId)).then(installChunk, <%- basicFunction("e") %> {
if (installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;
throw e;
});
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@
"webpack/runtime/hasOwnProperty shorthand": "!function () {\n __webpack_require__.o = function (obj, prop) {\n return Object.prototype.hasOwnProperty.call(obj, prop);\n };\n}();",
"webpack/runtime/make namespace object": "!function () {\n __webpack_require__.r = function (exports) {\n if (typeof Symbol !== \"undefined\" && Symbol.toStringTag) Object.defineProperty(exports, Symbol.toStringTag, {\n \"value\": \"Module\"\n });\n Object.defineProperty(exports, \"__esModule\", {\n \"value\": true\n });\n };\n}();",
"webpack/runtime/hot module replacement": "!function () {\n var currentModuleData = {};\n var installedModules = __webpack_require__.c;\n var currentChildModule;\n var currentParents = [];\n var registeredStatusHandlers = [];\n var currentStatus = \"idle\";\n var blockingPromises = 0;\n var blockingPromisesWaiting = [];\n var currentUpdateApplyHandlers;\n var queuedInvalidatedModules;\n __webpack_require__.hmrD = currentModuleData;\n __webpack_require__.i.push(function (options) {\n var module = options.module;\n var require = createRequire(options.require, options.id);\n module.hot = createModuleHotObject(options.id, module);\n module.parents = currentParents;\n module.children = [];\n currentParents = [];\n options.require = require;\n });\n __webpack_require__.hmrC = {};\n __webpack_require__.hmrI = {};\n function createRequire(require, moduleId) {\n var me = installedModules[moduleId];\n if (!me) return require;\n var fn = function (request) {\n if (me.hot.active) {\n if (installedModules[request]) {\n var parents = installedModules[request].parents;\n if (parents.indexOf(moduleId) === -1) parents.push(moduleId);\n } else {\n currentParents = [moduleId];\n currentChildModule = request;\n }\n if (me.children.indexOf(request) === -1) me.children.push(request);\n } else {\n console.warn(\"[HMR] unexpected require(\" + request + \") from disposed module \" + moduleId);\n currentParents = [];\n }\n return require(request);\n };\n var createPropertyDescriptor = function (name) {\n return {\n \"configurable\": true,\n \"enumerable\": true,\n \"get\": function () {\n return require[name];\n },\n \"set\": function (value) {\n require[name] = value;\n }\n };\n };\n for (var name in require) if (Object.prototype.hasOwnProperty.call(require, name) && name !== \"e\") Object.defineProperty(fn, name, createPropertyDescriptor(name));\n fn.e = function (chunkId, fetchPriority) {\n return trackBlockingPromise(require.e(chunkId, fetchPriority));\n };\n return fn;\n }\n function createModuleHotObject(moduleId, me) {\n var _main = currentChildModule !== moduleId;\n var hot = {\n \"_acceptedDependencies\": {},\n \"_acceptedErrorHandlers\": {},\n \"_declinedDependencies\": {},\n \"_disposeHandlers\": [],\n \"_main\": _main,\n \"_requireSelf\": function () {\n currentParents = me.parents.slice();\n currentChildModule = _main ? undefined : moduleId;\n __webpack_require__(moduleId);\n },\n \"_selfAccepted\": false,\n \"_selfDeclined\": false,\n \"_selfInvalidated\": false,\n \"accept\": function (dep, callback, errorHandler) {\n if (dep === undefined) hot._selfAccepted = true;else if (typeof dep === \"function\") hot._selfAccepted = dep;else if (typeof dep === \"object\" && dep !== null) for (var i = 0; i < dep.length; i++) {\n hot._acceptedDependencies[dep[i]] = callback || function () {};\n hot._acceptedErrorHandlers[dep[i]] = errorHandler;\n } else {\n hot._acceptedDependencies[dep] = callback || function () {};\n hot._acceptedErrorHandlers[dep] = errorHandler;\n }\n },\n \"active\": true,\n \"addDisposeHandler\": function (callback) {\n hot._disposeHandlers.push(callback);\n },\n \"addStatusHandler\": function (l) {\n registeredStatusHandlers.push(l);\n },\n \"apply\": hotApply,\n \"check\": hotCheck,\n \"data\": currentModuleData[moduleId],\n \"decline\": function (dep) {\n if (dep === undefined) hot._selfDeclined = true;else if (typeof dep === \"object\" && dep !== null) for (var i = 0; i < dep.length; i++) hot._declinedDependencies[dep[i]] = true;else hot._declinedDependencies[dep] = true;\n },\n \"dispose\": function (callback) {\n hot._disposeHandlers.push(callback);\n },\n \"invalidate\": function () {\n this._selfInvalidated = true;\n switch (currentStatus) {\n case \"idle\":\n currentUpdateApplyHandlers = [];\n Object.keys(__webpack_require__.hmrI).forEach(function (key) {\n __webpack_require__.hmrI[key](moduleId, currentUpdateApplyHandlers);\n });\n setStatus(\"ready\");\n break;\n case \"ready\":\n Object.keys(__webpack_require__.hmrI).forEach(function (key) {\n __webpack_require__.hmrI[key](moduleId, currentUpdateApplyHandlers);\n });\n break;\n case \"prepare\":\n case \"check\":\n case \"dispose\":\n case \"apply\":\n (queuedInvalidatedModules = queuedInvalidatedModules || []).push(moduleId);\n break;\n default:\n break;\n }\n },\n \"removeDisposeHandler\": function (callback) {\n var idx = hot._disposeHandlers.indexOf(callback);\n if (idx >= 0) hot._disposeHandlers.splice(idx, 1);\n },\n \"removeStatusHandler\": function (l) {\n var idx = registeredStatusHandlers.indexOf(l);\n if (idx >= 0) registeredStatusHandlers.splice(idx, 1);\n },\n \"status\": function (l) {\n if (!l) return currentStatus;\n registeredStatusHandlers.push(l);\n }\n };\n currentChildModule = undefined;\n return hot;\n }\n function setStatus(newStatus) {\n currentStatus = newStatus;\n var results = [];\n for (var i = 0; i < registeredStatusHandlers.length; i++) results[i] = registeredStatusHandlers[i].call(null, newStatus);\n return Promise.all(results).then(function () {});\n }\n function unblock() {\n if (--blockingPromises === 0) setStatus(\"ready\").then(function () {\n if (blockingPromises === 0) {\n var list = blockingPromisesWaiting;\n blockingPromisesWaiting = [];\n for (var i = 0; i < list.length; i++) list[i]();\n }\n });\n }\n function trackBlockingPromise(promise) {\n switch (currentStatus) {\n case \"ready\":\n setStatus(\"prepare\");\n case \"prepare\":\n blockingPromises++;\n promise.then(unblock, unblock);\n return promise;\n default:\n return promise;\n }\n }\n function waitForBlockingPromises(fn) {\n if (blockingPromises === 0) return fn();\n return new Promise(function (resolve) {\n blockingPromisesWaiting.push(function () {\n resolve(fn());\n });\n });\n }\n function hotCheck(applyOnUpdate) {\n if (currentStatus !== \"idle\") throw new Error(\"check() is only allowed in idle status\");\n return setStatus(\"check\").then(__webpack_require__.hmrM).then(function (update) {\n if (!update) return setStatus(applyInvalidatedModules() ? \"ready\" : \"idle\").then(function () {\n return null;\n });\n return setStatus(\"prepare\").then(function () {\n var updatedModules = [];\n currentUpdateApplyHandlers = [];\n return Promise.all(Object.keys(__webpack_require__.hmrC).reduce(function (promises, key) {\n __webpack_require__.hmrC[key](update.c, update.r, update.m, promises, currentUpdateApplyHandlers, updatedModules);\n return promises;\n }, [])).then(function () {\n return waitForBlockingPromises(function () {\n if (applyOnUpdate) return internalApply(applyOnUpdate);\n return setStatus(\"ready\").then(function () {\n return updatedModules;\n });\n });\n });\n });\n });\n }\n function hotApply(options) {\n if (currentStatus !== \"ready\") return Promise.resolve().then(function () {\n throw new Error(\"apply() is only allowed in ready status (state: \" + currentStatus + \")\");\n });\n return internalApply(options);\n }\n function internalApply(options) {\n options = options || {};\n applyInvalidatedModules();\n var results = currentUpdateApplyHandlers.map(function (handler) {\n return handler(options);\n });\n currentUpdateApplyHandlers = undefined;\n var errors = results.map(function (r) {\n return r.error;\n }).filter(Boolean);\n if (errors.length > 0) return setStatus(\"abort\").then(function () {\n throw errors[0];\n });\n var disposePromise = setStatus(\"dispose\");\n results.forEach(function (result) {\n if (result.dispose) result.dispose();\n });\n var applyPromise = setStatus(\"apply\");\n var error;\n var reportError = function (err) {\n if (!error) error = err;\n };\n var outdatedModules = [];\n results.forEach(function (result) {\n if (result.apply) {\n var modules = result.apply(reportError);\n if (modules) for (var i = 0; i < modules.length; i++) outdatedModules.push(modules[i]);\n }\n });\n return Promise.all([disposePromise, applyPromise]).then(function () {\n if (error) return setStatus(\"fail\").then(function () {\n throw error;\n });\n if (queuedInvalidatedModules) return internalApply(options).then(function (list) {\n outdatedModules.forEach(function (moduleId) {\n if (list.indexOf(moduleId) < 0) list.push(moduleId);\n });\n return list;\n });\n return setStatus(\"idle\").then(function () {\n return outdatedModules;\n });\n });\n }\n function applyInvalidatedModules() {\n if (queuedInvalidatedModules) {\n if (!currentUpdateApplyHandlers) currentUpdateApplyHandlers = [];\n Object.keys(__webpack_require__.hmrI).forEach(function (key) {\n queuedInvalidatedModules.forEach(function (moduleId) {\n __webpack_require__.hmrI[key](moduleId, currentUpdateApplyHandlers);\n });\n });\n queuedInvalidatedModules = undefined;\n return true;\n }\n }\n}();",
"webpack/runtime/publicPath": "!function () {\n __webpack_require__.p = \"\";\n}();",
"webpack/runtime/export webpack runtime": "export default __webpack_require__;",
"webpack/runtime/import chunk loading": "!function () {\n var installedChunks = __webpack_require__.hmrS_module = __webpack_require__.hmrS_module || {\n \"bundle\": 0\n };\n var installChunk = function (data) {\n var __webpack_ids__ = data.__webpack_ids__;\n var __webpack_modules__ = data.__webpack_modules__;\n var __webpack_runtime__ = data.__webpack_runtime__;\n var moduleId,\n chunkId,\n i = 0;\n for (moduleId in __webpack_modules__) if (__webpack_require__.o(__webpack_modules__, moduleId)) __webpack_require__.m[moduleId] = __webpack_modules__[moduleId];\n if (__webpack_runtime__) __webpack_runtime__(__webpack_require__);\n for (; i < __webpack_ids__.length; i++) {\n chunkId = __webpack_ids__[i];\n if (__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) installedChunks[chunkId][0]();\n installedChunks[__webpack_ids__[i]] = 0;\n }\n };\n __webpack_require__.f.j = function (chunkId, promises) {\n var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n if (installedChunkData !== 0) if (installedChunkData) promises.push(installedChunkData[1]);else if (\"bundle\" != chunkId) {\n var promise = import(\"./\" + __webpack_require__.u(chunkId)).then(installChunk, function (e) {\n if (installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;\n throw e;\n });\n var promise = Promise.race([promise, new Promise(function (resolve) {\n installedChunkData = installedChunks[chunkId] = [resolve];\n })]);\n promises.push(installedChunkData[1] = promise);\n } else installedChunks[chunkId] = 0;\n };\n __webpack_require__.C = installChunk;\n}();"
"webpack/runtime/import chunk loading": "!function () {\n var installedChunks = __webpack_require__.hmrS_module = __webpack_require__.hmrS_module || {\n \"bundle\": 0\n };\n var installChunk = function (data) {\n var __webpack_ids__ = data.__webpack_ids__;\n var __webpack_modules__ = data.__webpack_modules__;\n var __webpack_runtime__ = data.__webpack_runtime__;\n var moduleId,\n chunkId,\n i = 0;\n for (moduleId in __webpack_modules__) if (__webpack_require__.o(__webpack_modules__, moduleId)) __webpack_require__.m[moduleId] = __webpack_modules__[moduleId];\n if (__webpack_runtime__) __webpack_runtime__(__webpack_require__);\n for (; i < __webpack_ids__.length; i++) {\n chunkId = __webpack_ids__[i];\n if (__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) installedChunks[chunkId][0]();\n installedChunks[__webpack_ids__[i]] = 0;\n }\n };\n __webpack_require__.f.j = function (chunkId, promises) {\n var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;\n if (installedChunkData !== 0) if (installedChunkData) promises.push(installedChunkData[1]);else if (\"bundle\" != chunkId) {\n var promise = import(__webpack_require__.p + \"./\" + __webpack_require__.u(chunkId)).then(installChunk, function (e) {\n if (installedChunks[chunkId] !== 0) installedChunks[chunkId] = undefined;\n throw e;\n });\n var promise = Promise.race([promise, new Promise(function (resolve) {\n installedChunkData = installedChunks[chunkId] = [resolve];\n })]);\n promises.push(installedChunkData[1] = promise);\n } else installedChunks[chunkId] = 0;\n };\n __webpack_require__.C = installChunk;\n}();"
}
}
Loading
Loading