本文是《彻底搞懂 Module Federation》系列的第2篇,深入分析 Webpack 异步加载的底层原理。
📚 系列文章
- 📖 第1篇:概述与实战示例
- ✅ 第2篇(本文):原理分析 - Webpack 异步加载流程
- 📖 第3篇:原理分析 - MF 模块加载(上)
- 📖 第4篇:原理分析 - MF 模块加载(下)
- 📖 第5篇:原理分析 - Runtime API + 项目实操
3. 原理分析
not magic, just async chunk
大白话解释一下,共享组件单独打包成一个异步chunk里面,共享的依赖会在加载组件之前进行前置加载,中间有一些复杂的依赖版本号比较,依赖库加载的逻辑通过shared字段进行配置。
这里的加载模块流程分析准备分三部分,首先介绍最基础的webpack异步模块加载流程,后面分别介绍module federation两个引入方式对应不同的加载流程
3.1 webpack异步模块加载流程
3.1.1 按需加载
按需加载,也叫异步加载、动态导入,即只在有需要的时候才去下载相应的资源文件。
在 webpack 中可以使用 import 和 require.ensure 来引入需要动态导入的代码,还是用前面的vue3-demo示例,现在只关注home目录,并且把webpack配置中的ModuleFederationPlugin插件去掉。
home文件夹目录结构
vue3-demo/
├── home(remote)
│ ├── src
│ │ ├── App.vue -- 入口组件 components: { Content: defineAsyncComponent(() => import('./components/Content')),
│ │ ├── components
│ │ │ ├── Button.js -- 业务组件Button
│ │ │ └── Content.vue -- 业务组件Content
│ │ ├── index.js. -- import('./main.js');
│ │ └── main.js -- const app = createApp(App);app.mount('#app');
│ └── webpack.config.js
App.vue组件里面进行组件注册时,使用import方法引入
components: {
Content: defineAsyncComponent(() => import('./components/Content')),
Button: defineAsyncComponent(() => import('./components/Button')),
},
本地开发环境配置修改后,重新进行构建,可以看到从请求html到后续的js、css文件加载顺序。
3.1.2 初始化请求链路
-
Request initiator chain
-
-
- http://localhost:3002/vendors-node_modules_pnpm_mini-css-extract-plugin_2_9_2_webpack_5_96_1__swc_core_1_9_2_webpac-fe6f3f.js
- http://localhost:3002/src_main_js.css
- http://localhost:3002/src_main_js.js
- http://localhost:3002/src_components_Content_vue.js
- http://localhost:3002/src_components_Button_js.js
-
-
3.1.3 源码与构建后代码对照
3.1.3.1 入口html文件
3.1.3.1.1 源码
<div id="app"></div>
3.1.3.1.2 构建后代码
<head>
<script defer src="main.js"></script>
</head>
<div id="app"></div>
3.1.3.2 入口index.js文件
3.1.3.2.1 源码
// https://webpack.js.org/concepts/module-federation/#uncaught-error-shared-module-is-not-available-for-eager-consumption
import('./main.js');
3.1.3.2.2 构建后代码
构建后的startUp 入口函数
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
**********************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
// https://webpack.js.org/concepts/module-federation/#uncaught-error-shared-module-is-not-available-for-eager-consumption
Promise.all(/*! import() */[__webpack_require__.e("vendors-node_modules_pnpm_mini-css-extract-plugin_2_9_2_webpack_5_96_1__swc_core_1_9_2_webpac-fe6f3f"), __webpack_require__.e("src_main_js")]).then(__webpack_require__.bind(__webpack_require__, /*! ./main.js */ "./src/main.js"));
/***/ })
})
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };
/******/ __webpack_require__.i.forEach(function(handler) { handler(execOptions); });
/******/ module = execOptions.module;
/******/ execOptions.factory.call(module.exports, module, module.exports, execOptions.require);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = __webpack_module_cache__;
/******/
/******/ // expose the module execution interceptor
/******/ __webpack_require__.i = [];
/******/
/************************************************************************/
/******/
/******/ /* webpack/runtime/ensure chunk */
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
/******/ }, []));
/******/ };
/******/ })();
/******/
/******/ /* webpack/runtime/get javascript chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.u = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".js";
/******/ };
/******/ })();
/******/
/******/
/******/ /* webpack/runtime/get mini-css chunk filename */
/******/ (() => {
/******/ // This function allow to reference async chunks
/******/ __webpack_require__.miniCssF = (chunkId) => {
/******/ // return url for filenames based on template
/******/ return "" + chunkId + ".css";
/******/ };
/******/ })();
/******/
/******/
/******/
/******/ /* webpack/runtime/load script */
/******/ (() => {
/******/ var inProgress = {};
/******/ var dataWebpackPrefix = "vue3-demo_home:";
/******/ // loadScript function to load a script via script tag
/******/ __webpack_require__.l = (url, done, key, chunkId) => {
/******/ if(inProgress[url]) { inProgress[url].push(done); return; }
/******/ var script, needAttach;
/******/ if(key !== undefined) {
/******/ var scripts = document.getElementsByTagName("script");
/******/ for(var i = 0; i < scripts.length; i++) {
/******/ var s = scripts[i];
/******/ if(s.getAttribute("src") == url || s.getAttribute("data-webpack") == dataWebpackPrefix + key) { script = s; break; }
/******/ }
/******/ }
/******/ if(!script) {
/******/ needAttach = true;
/******/ script = document.createElement('script');
/******/
/******/ script.charset = 'utf-8';
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
/******/
/******/ script.src = url;
/******/ }
/******/ inProgress[url] = [done];
/******/ var onScriptComplete = (prev, event) => {
/******/ // avoid mem leaks in IE.
/******/ script.onerror = script.onload = null;
/******/ clearTimeout(timeout);
/******/ var doneFns = inProgress[url];
/******/ delete inProgress[url];
/******/ script.parentNode && script.parentNode.removeChild(script);
/******/ doneFns && doneFns.forEach((fn) => (fn(event)));
/******/ if(prev) return prev(event);
/******/ }
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
/******/ script.onload = onScriptComplete.bind(null, script.onload);
/******/ needAttach && document.head.appendChild(script);
/******/ };
/******/ })();
/******/
/******/
/******/
/******/ /* webpack/runtime/css loading */
/******/ (() => {
/******/ if (typeof document === "undefined") return;
/******/ var createStylesheet = (chunkId, fullhref, oldTag, resolve, reject) => {
/******/ var linkTag = document.createElement("link");
/******/
/******/ linkTag.rel = "stylesheet";
/******/ linkTag.type = "text/css";
/******/ if (__webpack_require__.nc) {
/******/ linkTag.nonce = __webpack_require__.nc;
/******/ }
/******/ var onLinkComplete = (event) => {
/******/ // avoid mem leaks.
/******/ linkTag.onerror = linkTag.onload = null;
/******/ if (event.type === 'load') {
/******/ resolve();
/******/ } else {
/******/ var errorType = event && event.type;
/******/ var realHref = event && event.target && event.target.href || fullhref;
/******/ var err = new Error("Loading CSS chunk " + chunkId + " failed.\n(" + errorType + ": " + realHref + ")");
/******/ err.name = "ChunkLoadError";
/******/ err.code = "CSS_CHUNK_LOAD_FAILED";
/******/ err.type = errorType;
/******/ err.request = realHref;
/******/ if (linkTag.parentNode) linkTag.parentNode.removeChild(linkTag)
/******/ reject(err);
/******/ }
/******/ }
/******/ linkTag.onerror = linkTag.onload = onLinkComplete;
/******/ linkTag.href = fullhref;
/******/
/******/
/******/ if (oldTag) {
/******/ oldTag.parentNode.insertBefore(linkTag, oldTag.nextSibling);
/******/ } else {
/******/ document.head.appendChild(linkTag);
/******/ }
/******/ return linkTag;
/******/ };
/******/ var findStylesheet = (href, fullhref) => {
/******/ var existingLinkTags = document.getElementsByTagName("link");
/******/ for(var i = 0; i < existingLinkTags.length; i++) {
/******/ var tag = existingLinkTags[i];
/******/ var dataHref = tag.getAttribute("data-href") || tag.getAttribute("href");
/******/ if(tag.rel === "stylesheet" && (dataHref === href || dataHref === fullhref)) return tag;
/******/ }
/******/ var existingStyleTags = document.getElementsByTagName("style");
/******/ for(var i = 0; i < existingStyleTags.length; i++) {
/******/ var tag = existingStyleTags[i];
/******/ var dataHref = tag.getAttribute("data-href");
/******/ if(dataHref === href || dataHref === fullhref) return tag;
/******/ }
/******/ };
/******/ var loadStylesheet = (chunkId) => {
/******/ return new Promise((resolve, reject) => {
/******/ var href = __webpack_require__.miniCssF(chunkId);
/******/ var fullhref = __webpack_require__.p + href;
/******/ if(findStylesheet(href, fullhref)) return resolve();
/******/ createStylesheet(chunkId, fullhref, null, resolve, reject);
/******/ });
/******/ }
/******/ // object to store loaded CSS chunks
/******/ var installedCssChunks = {
/******/ "main": 0
/******/ };
/******/
/******/ __webpack_require__.f.miniCss = (chunkId, promises) => {
/******/ var cssChunks = {"src_main_js":1};
/******/ if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);
/******/ else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {
/******/ promises.push(installedCssChunks[chunkId] = loadStylesheet(chunkId).then(() => {
/******/ installedCssChunks[chunkId] = 0;
/******/ }, (e) => {
/******/ delete installedCssChunks[chunkId];
/******/ throw e;
/******/ }));
/******/ }
/******/ };
/******/
/******/ var oldTags = [];
/******/ var newTags = [];
/******/ var applyHandler = (options) => {
/******/ return { dispose: () => {
/******/ for(var i = 0; i < oldTags.length; i++) {
/******/ var oldTag = oldTags[i];
/******/ if(oldTag.parentNode) oldTag.parentNode.removeChild(oldTag);
/******/ }
/******/ oldTags.length = 0;
/******/ }, apply: () => {
/******/ for(var i = 0; i < newTags.length; i++) newTags[i].rel = "stylesheet";
/******/ newTags.length = 0;
/******/ } };
/******/ }
/******/ __webpack_require__.hmrC.miniCss = (chunkIds, removedChunks, removedModules, promises, applyHandlers, updatedModulesList) => {
/******/ applyHandlers.push(applyHandler);
/******/ chunkIds.forEach((chunkId) => {
/******/ var href = __webpack_require__.miniCssF(chunkId);
/******/ var fullhref = __webpack_require__.p + href;
/******/ var oldTag = findStylesheet(href, fullhref);
/******/ if(!oldTag) return;
/******/ promises.push(new Promise((resolve, reject) => {
/******/ var tag = createStylesheet(chunkId, fullhref, oldTag, () => {
/******/ tag.as = "style";
/******/ tag.rel = "preload";
/******/ resolve();
/******/ }, reject);
/******/ oldTags.push(oldTag);
/******/ newTags.push(tag);
/******/ }));
/******/ });
/******/ }
/******/
/******/ // no prefetching
/******/
/******/ // no preloaded
/******/ })();
/******/
/******/ /* webpack/runtime/jsonp chunk loading */
/******/ (() => {
/******/ // no baseURI
/******/
/******/ // object to store loaded and loading chunks
/******/ // undefined = chunk not loaded, null = chunk preloaded/prefetched
/******/ // [resolve, reject, Promise] = chunk loading, 0 = chunk loaded
/******/ var installedChunks = __webpack_require__.hmrS_jsonp = __webpack_require__.hmrS_jsonp || {
/******/ "main": 0
/******/ };
/******/
/******/ __webpack_require__.f.j = (chunkId, promises) => {
/******/ // JSONP chunk loading for javascript
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ promises.push(installedChunkData[2]);
/******/ } else {
/******/ if(true) { // all chunks have JS
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
/******/ promises.push(installedChunkData[2] = promise);
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
/******/ if(installedChunkData) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src;
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ installedChunkData[1](error);
/******/ }
/******/ }
/******/ };
/******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);
/******/ }
/******/ }
/******/ }
/******/ };
/******/
/******/ // no prefetching
/******/
/******/
/******/
/******/
/******/ // install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) var result = runtime(__webpack_require__);
/******/ }
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/
/******/ }
/******/
/******/ var chunkLoadingGlobal = self["webpackChunkvue3_demo_home"] = self["webpackChunkvue3_demo_home"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ })();
/******/
/************************************************************************/
/******/
/******/ // module cache are used so entry inlining is disabled
/******/ // startup
/******/ // Load entry module and return exports
/******/ __webpack_require__("../../node_modules/.pnpm/webpack-dev-server@5.0.4_webpack-cli@5.1.4_webpack@5.96.1/node_modules/webpack-dev-server/client/index.js?protocol=ws%3A&hostname=0.0.0.0&port=3002&pathname=%2Fws&logging=info&overlay=true&reconnect=10&hot=true&live-reload=true");
/******/ __webpack_require__("../../node_modules/.pnpm/webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4/node_modules/webpack/hot/dev-server.js");
/******/ var __webpack_exports__ = __webpack_require__("./src/index.js");
/******/
/******/ })()
;
//# sourceMappingURL=main.js.map
3.1.3.3 main.js文件
3.1.3.3.1 源码
import { createApp } from 'vue';
import App from './App.vue';
const app = createApp(App);
app.mount('#app');
3.1.3.3.2 构建后代码
"use strict";
(self["webpackChunkvue3_demo_home"] = self["webpackChunkvue3_demo_home"] || []).push([["src_main_js"], {
/***/
"../../node_modules/.pnpm/mini-css-extract-plugin@2.9.2_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-2.use[0]!../../node_modules/.pnpm/css-loader@7.1.2_@rspack+core@1.1.1_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/css-loader/dist/cjs.js!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/stylePostLoader.js!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css": /*!*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ../../node_modules/.pnpm/mini-css-extract-plugin@2.9.2_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-2.use[0]!../../node_modules/.pnpm/css-loader@7.1.2_@rspack+core@1.1.1_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/css-loader/dist/cjs.js!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/stylePostLoader.js!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css ***!
*******************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/***/
( (module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
// extracted by mini-css-extract-plugin
if (true) {
(function() {
var localsJsonString = undefined;
// 1758629789554
var cssReload = __webpack_require__(/*! ../../../node_modules/.pnpm/mini-css-extract-plugin@2.9.2_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js */
"../../node_modules/.pnpm/mini-css-extract-plugin@2.9.2_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/mini-css-extract-plugin/dist/hmr/hotModuleReplacement.js")(module.id, {});
// only invalidate when locals change
if (module.hot.data && module.hot.data.value && module.hot.data.value !== localsJsonString) {
module.hot.invalidate();
} else {
module.hot.accept();
}
module.hot.dispose(function(data) {
data.value = localsJsonString;
cssReload();
});
}
)();
}
/***/
}
),
/***/
"./src/App.vue": /*!*********************!*\
!*** ./src/App.vue ***!
*********************/
/***/
( (module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
"default": () => (__WEBPACK_DEFAULT_EXPORT__)/* harmony export */
});
/* harmony import */
var _App_vue_vue_type_template_id_7ba5bd90_scoped_true__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./App.vue?vue&type=template&id=7ba5bd90&scoped=true */
"./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true");
/* harmony import */
var _App_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./App.vue?vue&type=script&lang=js */
"./src/App.vue?vue&type=script&lang=js");
/* harmony import */
var _App_vue_vue_type_style_index_0_id_7ba5bd90_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css */
"./src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css");
/* harmony import */
var _Users_liqi_fe_module_federation_examples_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/exportHelper.js */
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/exportHelper.js");
;
const __exports__ = /*#__PURE__*/
(0,
_Users_liqi_fe_module_federation_examples_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_3__["default"])(_App_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__["default"], [['render', _App_vue_vue_type_template_id_7ba5bd90_scoped_true__WEBPACK_IMPORTED_MODULE_0__.render], ['__scopeId', "data-v-7ba5bd90"], ['__file', "src/App.vue"]])
/* hot reload */
if (true) {
__exports__.__hmrId = "7ba5bd90"
const api = __VUE_HMR_RUNTIME__
module.hot.accept()
if (!api.createRecord('7ba5bd90', __exports__)) {
console.log('reload')
api.reload('7ba5bd90', __exports__)
}
module.hot.accept(/*! ./App.vue?vue&type=template&id=7ba5bd90&scoped=true */
"./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true", __WEBPACK_OUTDATED_DEPENDENCIES__ => {
/* harmony import */
_App_vue_vue_type_template_id_7ba5bd90_scoped_true__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./App.vue?vue&type=template&id=7ba5bd90&scoped=true */
"./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true");
( () => {
console.log('re-render')
api.rerender('7ba5bd90', _App_vue_vue_type_template_id_7ba5bd90_scoped_true__WEBPACK_IMPORTED_MODULE_0__.render)
}
)(__WEBPACK_OUTDATED_DEPENDENCIES__);
}
)
}
/* harmony default export */
const __WEBPACK_DEFAULT_EXPORT__ = (__exports__);
/***/
}
),
/***/
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=script&lang=js": /*!*****************************************************************************************************************************************************************************************************************************************************************!*\
!*** ../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=script&lang=js ***!
*****************************************************************************************************************************************************************************************************************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
"default": () => (__WEBPACK_DEFAULT_EXPORT__)/* harmony export */
});
/* harmony import */
var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */
"../../node_modules/.pnpm/vue@3.3.7_typescript@5.6.3/node_modules/vue/dist/vue.runtime.esm-bundler.js");
// import Content from "./components/Content";
// import Button from "./components/Button";
/* harmony default export */
const __WEBPACK_DEFAULT_EXPORT__ = ({
components: {
Content: (0,
vue__WEBPACK_IMPORTED_MODULE_0__.defineAsyncComponent)( () => __webpack_require__.e(/*! import() */
"src_components_Content_vue").then(__webpack_require__.bind(__webpack_require__, /*! ./components/Content */
"./src/components/Content.vue"))),
Button: (0,
vue__WEBPACK_IMPORTED_MODULE_0__.defineAsyncComponent)( () => __webpack_require__.e(/*! import() */
"src_components_Button_js").then(__webpack_require__.bind(__webpack_require__, /*! ./components/Button */
"./src/components/Button.js"))),
},
// components: {
// Content,
// Button,
// },
setup() {
const count = (0,
vue__WEBPACK_IMPORTED_MODULE_0__.ref)(0);
const inc = () => {
count.value++;
}
;
return {
count,
inc,
};
},
});
/***/
}
),
/***/
"./src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css": /*!*****************************************************************************!*\
!*** ./src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css ***!
*****************************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */
var _node_modules_pnpm_mini_css_extract_plugin_2_9_2_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_mini_css_extract_plugin_dist_loader_js_clonedRuleSet_2_use_0_node_modules_pnpm_css_loader_7_1_2_rspack_core_1_1_1_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_css_loader_dist_cjs_js_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_stylePostLoader_js_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_App_vue_vue_type_style_index_0_id_7ba5bd90_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/.pnpm/mini-css-extract-plugin@2.9.2_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-2.use[0]!../../../node_modules/.pnpm/css-loader@7.1.2_@rspack+core@1.1.1_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/css-loader/dist/cjs.js!../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/stylePostLoader.js!../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css */
"../../node_modules/.pnpm/mini-css-extract-plugin@2.9.2_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/mini-css-extract-plugin/dist/loader.js??clonedRuleSet-2.use[0]!../../node_modules/.pnpm/css-loader@7.1.2_@rspack+core@1.1.1_webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/css-loader/dist/cjs.js!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/stylePostLoader.js!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css");
/***/
}
),
/***/
"./src/App.vue?vue&type=script&lang=js": /*!*********************************************!*\
!*** ./src/App.vue?vue&type=script&lang=js ***!
*********************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
"default": () => (/* reexport safe */
_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_App_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__["default"])/* harmony export */
});
/* harmony import */
var _node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_App_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./App.vue?vue&type=script&lang=js */
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=script&lang=js");
/***/
}
),
/***/
"./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true": /*!***************************************************************!*\
!*** ./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true ***!
***************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
render: () => (/* reexport safe */
_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_1_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_App_vue_vue_type_template_id_7ba5bd90_scoped_true__WEBPACK_IMPORTED_MODULE_0__.render)/* harmony export */
});
/* harmony import */
var _node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_1_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_App_vue_vue_type_template_id_7ba5bd90_scoped_true__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./App.vue?vue&type=template&id=7ba5bd90&scoped=true */
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true");
/***/
}
),
/***/
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true": /*!*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true ***!
*********************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
render: () => (/* binding */
render)/* harmony export */
});
/* harmony import */
var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */
"../../node_modules/.pnpm/vue@3.3.7_typescript@5.6.3/node_modules/vue/dist/vue.runtime.esm-bundler.js");
const _withScopeId = n => ((0,
vue__WEBPACK_IMPORTED_MODULE_0__.pushScopeId)("data-v-7ba5bd90"),
n = n(),
(0,
vue__WEBPACK_IMPORTED_MODULE_0__.popScopeId)(),
n)
const _hoisted_1 = /*#__PURE__*/
_withScopeId( () => /*#__PURE__*/
(0,
vue__WEBPACK_IMPORTED_MODULE_0__.createElementVNode)("h3", null, "Main App", -1 /* HOISTED */
))
function render(_ctx, _cache, $props, $setup, $data, $options) {
const _component_Content = (0,
vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Content")
const _component_Button = (0,
vue__WEBPACK_IMPORTED_MODULE_0__.resolveComponent)("Button")
return ((0,
vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(),
(0,
vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", null, [_hoisted_1, (0,
vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Content), (0,
vue__WEBPACK_IMPORTED_MODULE_0__.createVNode)(_component_Button)]))
}
/***/
}
),
/***/
"./src/main.js": /*!*********************!*\
!*** ./src/main.js ***!
*********************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */
var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */
"../../node_modules/.pnpm/vue@3.3.7_typescript@5.6.3/node_modules/vue/dist/vue.runtime.esm-bundler.js");
/* harmony import */
var _App_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./App.vue */
"./src/App.vue");
const app = (0,
vue__WEBPACK_IMPORTED_MODULE_0__.createApp)(_App_vue__WEBPACK_IMPORTED_MODULE_1__["default"]);
app.mount('#app');
/***/
}
)
}]);
//# sourceMappingURL=src_main_js.js.map
3.1.3.4 button.js组件文件
3.1.3.4.1 源码
import { render, h } from 'vue';
const button = {
name: 'btn-component',
render() {
return h(
'button',
{
id: 'btn-primary',
},
'Hello World',
);
},
};
export default button;
3.1.3.4.2 构建后代码
"use strict";
(self["webpackChunkvue3_demo_home"] = self["webpackChunkvue3_demo_home"] || []).push([["src_components_Button_js"],{
/***/ "./src/components/Button.js":
/*!**********************************!*\
!*** ./src/components/Button.js ***!
**********************************/
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ "default": () => (__WEBPACK_DEFAULT_EXPORT__)
/* harmony export */ });
/* harmony import */ var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */ "../../node_modules/.pnpm/vue@3.3.7_typescript@5.6.3/node_modules/vue/dist/vue.runtime.esm-bundler.js");
const button = {
name: 'btn-component',
render() {
return (0,vue__WEBPACK_IMPORTED_MODULE_0__.h)(
'button',
{
id: 'btn-primary',
},
'Hello World',
);
},
};
/* harmony default export */ const __WEBPACK_DEFAULT_EXPORT__ = (button);
/***/ })
}]);
//# sourceMappingURL=src_components_Button_js.js.map
3.1.3.5 Content.vue组件文件
3.1.3.5.1 源码
<template>
<div style="color: red">{{ title }}</div>
</template>
<script>
export default {
data() {
return {
title: 'Remote Component in Action..',
};
},
};
</script>
3.1.3.5.2 构建后代码
"use strict";
(self["webpackChunkvue3_demo_home"] = self["webpackChunkvue3_demo_home"] || []).push([["src_components_Content_vue"], {
/***/
"./src/components/Content.vue": /*!************************************!*\
!*** ./src/components/Content.vue ***!
************************************/
/***/
( (module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
"default": () => (__WEBPACK_DEFAULT_EXPORT__)/* harmony export */
});
/* harmony import */
var _Content_vue_vue_type_template_id_7eab81f9__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Content.vue?vue&type=template&id=7eab81f9 */
"./src/components/Content.vue?vue&type=template&id=7eab81f9");
/* harmony import */
var _Content_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./Content.vue?vue&type=script&lang=js */
"./src/components/Content.vue?vue&type=script&lang=js");
/* harmony import */
var _Users_liqi_fe_module_federation_examples_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/exportHelper.js */
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/exportHelper.js");
;const __exports__ = /*#__PURE__*/
(0,
_Users_liqi_fe_module_federation_examples_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_2__["default"])(_Content_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__["default"], [['render', _Content_vue_vue_type_template_id_7eab81f9__WEBPACK_IMPORTED_MODULE_0__.render], ['__file', "src/components/Content.vue"]])
/* hot reload */
if (true) {
__exports__.__hmrId = "7eab81f9"
const api = __VUE_HMR_RUNTIME__
module.hot.accept()
if (!api.createRecord('7eab81f9', __exports__)) {
console.log('reload')
api.reload('7eab81f9', __exports__)
}
module.hot.accept(/*! ./Content.vue?vue&type=template&id=7eab81f9 */
"./src/components/Content.vue?vue&type=template&id=7eab81f9", __WEBPACK_OUTDATED_DEPENDENCIES__ => {
/* harmony import */
_Content_vue_vue_type_template_id_7eab81f9__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./Content.vue?vue&type=template&id=7eab81f9 */
"./src/components/Content.vue?vue&type=template&id=7eab81f9");
( () => {
console.log('re-render')
api.rerender('7eab81f9', _Content_vue_vue_type_template_id_7eab81f9__WEBPACK_IMPORTED_MODULE_0__.render)
}
)(__WEBPACK_OUTDATED_DEPENDENCIES__);
}
)
}
/* harmony default export */
const __WEBPACK_DEFAULT_EXPORT__ = (__exports__);
/***/
}
),
/***/
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/components/Content.vue?vue&type=script&lang=js": /*!********************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/components/Content.vue?vue&type=script&lang=js ***!
********************************************************************************************************************************************************************************************************************************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
"default": () => (__WEBPACK_DEFAULT_EXPORT__)/* harmony export */
});
/* harmony default export */
const __WEBPACK_DEFAULT_EXPORT__ = ({
data() {
return {
title: 'Remote Component in Action..',
};
},
});
/***/
}
),
/***/
"./src/components/Content.vue?vue&type=script&lang=js": /*!************************************************************!*\
!*** ./src/components/Content.vue?vue&type=script&lang=js ***!
************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
"default": () => (/* reexport safe */
_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_Content_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__["default"])/* harmony export */
});
/* harmony import */
var _node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_Content_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./Content.vue?vue&type=script&lang=js */
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/components/Content.vue?vue&type=script&lang=js");
/***/
}
),
/***/
"./src/components/Content.vue?vue&type=template&id=7eab81f9": /*!******************************************************************!*\
!*** ./src/components/Content.vue?vue&type=template&id=7eab81f9 ***!
******************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
render: () => (/* reexport safe */
_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_1_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_Content_vue_vue_type_template_id_7eab81f9__WEBPACK_IMPORTED_MODULE_0__.render)/* harmony export */
});
/* harmony import */
var _node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_templateLoader_js_ruleSet_1_rules_1_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_index_js_ruleSet_1_rules_4_use_0_Content_vue_vue_type_template_id_7eab81f9__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! -!../../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./Content.vue?vue&type=template&id=7eab81f9 */
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/components/Content.vue?vue&type=template&id=7eab81f9");
/***/
}
),
/***/
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/components/Content.vue?vue&type=template&id=7eab81f9": /*!************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************!*\
!*** ../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/templateLoader.js??ruleSet[1].rules[1]!../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/index.js??ruleSet[1].rules[4].use[0]!./src/components/Content.vue?vue&type=template&id=7eab81f9 ***!
************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
render: () => (/* binding */
render)/* harmony export */
});
/* harmony import */
var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */
"../../node_modules/.pnpm/vue@3.3.7_typescript@5.6.3/node_modules/vue/dist/vue.runtime.esm-bundler.js");
const _hoisted_1 = {
style: {
"color": "red"
}
}
function render(_ctx, _cache, $props, $setup, $data, $options) {
return ((0,
vue__WEBPACK_IMPORTED_MODULE_0__.openBlock)(),
(0,
vue__WEBPACK_IMPORTED_MODULE_0__.createElementBlock)("div", _hoisted_1, (0,
vue__WEBPACK_IMPORTED_MODULE_0__.toDisplayString)($data.title), 1 /* TEXT */
))
}
/***/
}
)
}]);
//# sourceMappingURL=src_components_Content_vue.js.map
3.1.4 过程解析
3.1.4.1 webpack_require("./src/index.js")
先从入口index.js文件开始看,里面只有一行代码,异步引入main.js模块,
import('./main.js');
但是构建后的startUp入口文件,里面包含了很多基础依赖库,只有在代码最后出现了index.js引入相关代码,
再把里面的代码简化一下,只保留关键的引入部分。
/******/ (() => { // webpackBootstrap
/******/ var __webpack_modules__ = ({
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
**********************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
// https://webpack.js.org/concepts/module-federation/#uncaught-error-shared-module-is-not-available-for-eager-consumption
Promise.all(/*! import() */[__webpack_require__.e("vendors-node_modules_pnpm_mini-css-extract-plugin_2_9_2_webpack_5_96_1__swc_core_1_9_2_webpac-fe6f3f"), __webpack_require__.e("src_main_js")]).then(__webpack_require__.bind(__webpack_require__, /*! ./main.js */ "./src/main.js"));
/***/ })
})
/************************************************************************/
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // Check if module is in cache
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // Create a new module (and put it into the cache)
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };
/******/ __webpack_require__.i.forEach(function(handler) { handler(execOptions); });
/******/ module = execOptions.module;
/******/ execOptions.factory.call(module.exports, module, module.exports, execOptions.require);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
/******/
/******/ // expose the modules object (__webpack_modules__)
/******/ __webpack_require__.m = __webpack_modules__;
/******/
/******/ // expose the module cache
/******/ __webpack_require__.c = __webpack_module_cache__;
/******/
/******/ // expose the module execution interceptor
/******/ __webpack_require__.i = [];
/******/
/************************************************************************/
/******/ // module cache are used so entry inlining is disabled
/******/ // startup
/******/ // Load entry module and return exports
/******/ __webpack_require__("../../node_modules/.pnpm/webpack-dev-server@5.0.4_webpack-cli@5.1.4_webpack@5.96.1/node_modules/webpack-dev-server/client/index.js?protocol=ws%3A&hostname=0.0.0.0&port=3002&pathname=%2Fws&logging=info&overlay=true&reconnect=10&hot=true&live-reload=true");
/******/ __webpack_require__("../../node_modules/.pnpm/webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4/node_modules/webpack/hot/dev-server.js");
/******/ var __webpack_exports__ = __webpack_require__("./src/index.js");
/******/
/******/ })()
;
直接看到最后一行代码,通过__webpack_require__方法引入index.js文件,这里也可以认为是一般的同步加载模块部分
*/ var __webpack_exports__ = __webpack_require__("./src/index.js");
继续看__webpack_require__函数实现,先从__webpack_module_cache__缓存变量中获取moduleId为./src/index.js的模块,没有缓存,则创建一个新的模块数据结构,并放到__webpack_module_cache__变量里面,
/******/ // The module cache
/******/ var __webpack_module_cache__ = {};
/******/
/******/ // The require function
/******/ function __webpack_require__(moduleId) {
/******/ // 先从__webpack_module_cache__缓存变量中获取moduleId为./src/index.js的模块
/******/ var cachedModule = __webpack_module_cache__[moduleId];
/******/ if (cachedModule !== undefined) {
/******/ return cachedModule.exports;
/******/ }
/******/ // 没有缓存,则创建一个新的模块数据结构,并放到__webpack_module_cache__变量里面
/******/ var module = __webpack_module_cache__[moduleId] = {
/******/ id: moduleId,
/******/ // no module.loaded needed
/******/ exports: {}
/******/ };
/******/
/******/ // Execute the module function
/******/ var execOptions = { id: moduleId, module: module, factory: __webpack_modules__[moduleId], require: __webpack_require__ };
/******/ __webpack_require__.i.forEach(function(handler) { handler(execOptions); });
/******/ module = execOptions.module;
/******/ execOptions.factory.call(module.exports, module, module.exports, execOptions.require);
/******/
/******/ // Return the exports of the module
/******/ return module.exports;
/******/ }
缓存数据结构中factory字段存放模块里面的具体代码实现,通过__webpack_modules__[moduleId]获取代码实现部分,最后执行。
3.1.4.2 webpack_modules
接着看__webpack_modules__变量,其实在文件最开头已经定义好了,这里才是真正存放原始的'src/index.js'文件,经过构建后的代码,可以具体看一下
/******/ var __webpack_modules__ = ({
/***/ "./src/index.js":
/*!**********************!*\
!*** ./src/index.js ***!
**********************/
/***/ ((__unused_webpack_module, __unused_webpack_exports, __webpack_require__) => {
// https://webpack.js.org/concepts/module-federation/#uncaught-error-shared-module-is-not-available-for-eager-consumption
Promise.all(/*! import() */
[
__webpack_require__.e("vendors-node_modules_pnpm_mini-css-extract-plugin_2_9_2_webpack_5_96_1__swc_core_1_9_2_webpac-fe6f3f"),
__webpack_require__.e("src_main_js")]
).then(
__webpack_require__.bind(__webpack_require__, /*! ./main.js */ "./src/main.js")
);
/***/ })
})
简单看原始的 import('./main.js'); 异步加载main.js模块,转化成了 __webpack_require__.e("src_main_js") 。
这里可以暂时理解成去异步请求main.js文件,等main.js文件请求完成后,进入then里面,执行
__webpack_require__.bind(__webpack_require__, /*! ./main.js */ "./src/main.js")
也就是进行一般的同步加载模块,类似前面加载"./src/index.js",都是用__webpack_require__函数。
3.1.4.3 webpack_require.e
接着关键看__webpack_require__.e是如何实现,其实从前面的index.js加载过程,大致可以推测一下,它主要任务有两个
- 通过创建一个script标签,并设置到html里面,发起请求main.js文件,并自动执行main.js
- ...
__webpack_modules__变量中找到./src/main.js的具体实现。
如何把main.js执行完成后,把自身代码实现设置到__webpack_modules__变量上面。就是最大的疑问。
/******/ /* webpack/runtime/ensure chunk */
/******/ (() => {
/******/ __webpack_require__.f = {};
/******/ // This file contains only the entry chunk.
/******/ // The chunk loading function for additional chunks
/******/ __webpack_require__.e = (chunkId) => {
/******/ return Promise.all(Object.keys(__webpack_require__.f).reduce((promises, key) => {
/******/ __webpack_require__.f[key](chunkId, promises);
/******/ return promises;
/******/ }, []));
/******/ };
/******/ })();
遍历_webpack_require__.f对象上挂载的所有方法,并执行。
__webpack_require__.f = {
miniCss: (chunkId, promises) => {
/******/ var cssChunks = {"90":1};
/******/ if(installedCssChunks[chunkId]) promises.push(installedCssChunks[chunkId]);
/******/ else if(installedCssChunks[chunkId] !== 0 && cssChunks[chunkId]) {
/******/ promises.push(installedCssChunks[chunkId] = loadStylesheet(chunkId).then(() => {
/******/ installedCssChunks[chunkId] = 0;
/******/ }, (e) => {
/******/ delete installedCssChunks[chunkId];
/******/ throw e;
/******/ }));
/******/ }
/******/ };
/******/ j: (chunkId, promises) => {
/******/ // JSONP chunk loading for javascript
/******/ var installedChunkData = __webpack_require__.o(installedChunks, chunkId) ? installedChunks[chunkId] : undefined;
/******/ if(installedChunkData !== 0) { // 0 means "already installed".
/******/
/******/ // a Promise means "currently loading".
/******/ if(installedChunkData) {
/******/ promises.push(installedChunkData[2]);
/******/ } else {
/******/ if(true) { // all chunks have JS
/******/ // setup Promise in chunk cache
/******/ var promise = new Promise((resolve, reject) => (installedChunkData = installedChunks[chunkId] = [resolve, reject]));
/******/ promises.push(installedChunkData[2] = promise);
/******/
/******/ // start chunk loading
/******/ var url = __webpack_require__.p + __webpack_require__.u(chunkId);
/******/ // create error before stack unwound to get useful stacktrace later
/******/ var error = new Error();
/******/ var loadingEnded = (event) => {
/******/ if(__webpack_require__.o(installedChunks, chunkId)) {
/******/ installedChunkData = installedChunks[chunkId];
/******/ if(installedChunkData !== 0) installedChunks[chunkId] = undefined;
/******/ if(installedChunkData) {
/******/ var errorType = event && (event.type === 'load' ? 'missing' : event.type);
/******/ var realSrc = event && event.target && event.target.src;
/******/ error.message = 'Loading chunk ' + chunkId + ' failed.\n(' + errorType + ': ' + realSrc + ')';
/******/ error.name = 'ChunkLoadError';
/******/ error.type = errorType;
/******/ error.request = realSrc;
/******/ installedChunkData[1](error);
/******/ }
/******/ }
/******/ };
/******/ __webpack_require__.l(url, loadingEnded, "chunk-" + chunkId, chunkId);
/******/ }
/******/ }
/******/ }
/******/ };
}
两个方法
- miniCss: 通过createStylesheet方法,动态创建link标签,异步加载样式文件
- j: 应该就是jsonp缩写,具体实现是
__webpack_require__.l,里面主要功能也是通过动态创建script标签,异步加载./src/main.js文件
/******/ /* webpack/runtime/load script */
/******/ (() => {
/******/ var inProgress = {};
/******/ var dataWebpackPrefix = "vue3-demo_home:";
/******/ // loadScript function to load a script via script tag
/******/ __webpack_require__.l = (url, done, key, chunkId) => {
...
/******/ needAttach = true;
/******/ script = document.createElement('script');
/******/
/******/ script.charset = 'utf-8';
/******/ script.timeout = 120;
/******/ if (__webpack_require__.nc) {
/******/ script.setAttribute("nonce", __webpack_require__.nc);
/******/ }
/******/ script.setAttribute("data-webpack", dataWebpackPrefix + key);
/******/
/******/ script.src = url;
/******/
/******/ inProgress[url] = [done];
/******/ var onScriptComplete = (prev, event) => {
....
/******/ }
/******/ var timeout = setTimeout(onScriptComplete.bind(null, undefined, { type: 'timeout', target: script }), 120000);
/******/ script.onerror = onScriptComplete.bind(null, script.onerror);
/******/ script.onload = onScriptComplete.bind(null, script.onload);
/******/ };
/******/ })();
3.1.4.4 ./src/main.js
接着看./src/main.js 文件加载并执行完成有什么效果。
"use strict";
(self["webpackChunkvue3_demo_home"] = self["webpackChunkvue3_demo_home"] || []).push([["src_main_js"], {
/***/
"./src/App.vue": /*!*********************!*\
!*** ./src/App.vue ***!
*********************/
/***/
( (module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony export */
__webpack_require__.d(__webpack_exports__, {
/* harmony export */
"default": () => (__WEBPACK_DEFAULT_EXPORT__)/* harmony export */
});
/* harmony import */
var _App_vue_vue_type_template_id_7ba5bd90_scoped_true__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! ./App.vue?vue&type=template&id=7ba5bd90&scoped=true */
"./src/App.vue?vue&type=template&id=7ba5bd90&scoped=true");
/* harmony import */
var _App_vue_vue_type_script_lang_js__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./App.vue?vue&type=script&lang=js */
"./src/App.vue?vue&type=script&lang=js");
/* harmony import */
var _App_vue_vue_type_style_index_0_id_7ba5bd90_scoped_true_lang_css__WEBPACK_IMPORTED_MODULE_2__ = __webpack_require__(/*! ./App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css */
"./src/App.vue?vue&type=style&index=0&id=7ba5bd90&scoped=true&lang=css");
/* harmony import */
var _Users_liqi_fe_module_federation_examples_node_modules_pnpm_vue_loader_16_8_3_vue_compiler_sfc_3_4_31_vue_3_3_7_typescript_5_6_3_webpack_5_96_1_swc_core_1_9_2_webpack_cli_5_1_4_node_modules_vue_loader_dist_exportHelper_js__WEBPACK_IMPORTED_MODULE_3__ = __webpack_require__(/*! ../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/exportHelper.js */
"../../node_modules/.pnpm/vue-loader@16.8.3_@vue+compiler-sfc@3.4.31_vue@3.3.7_typescript@5.6.3__webpack@5.96.1_@swc+core@1.9.2_webpack-cli@5.1.4_/node_modules/vue-loader/dist/exportHelper.js");
;
/* harmony default export */
const __WEBPACK_DEFAULT_EXPORT__ = (__exports__);
/***/
}
),
/***/
"./src/main.js": /*!*********************!*\
!*** ./src/main.js ***!
*********************/
/***/
( (__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
__webpack_require__.r(__webpack_exports__);
/* harmony import */
var vue__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! vue */
"../../node_modules/.pnpm/vue@3.3.7_typescript@5.6.3/node_modules/vue/dist/vue.runtime.esm-bundler.js");
/* harmony import */
var _App_vue__WEBPACK_IMPORTED_MODULE_1__ = __webpack_require__(/*! ./App.vue */
"./src/App.vue");
const app = (0,
vue__WEBPACK_IMPORTED_MODULE_0__.createApp)(_App_vue__WEBPACK_IMPORTED_MODULE_1__["default"]);
app.mount('#app');
/***/
}
)
}]);
push里面的内容跟. __webpack_modules__变量结构很类似,key对应moduleid, value对应具体代码实现。
self["webpackChunkvue3_demo_home"] = self["webpackChunkvue3_demo_home"] || []).push([["src_main_js"], {
{key}: {value}
}])
self是指向当前 window 对象的引用,在Service Workers和Web Workers非window场景下也适用
3.1.4.5 self["webpackChunkvue3_demo_home"].push = webpackJsonpCallback
从[入口的js文件中]寻找 self["webpackChunkvue3_demo_home"]的实现。
// install a JSONP callback for chunk loading
/******/ var webpackJsonpCallback = (parentChunkLoadingFunction, data) => {
/******/ var [chunkIds, moreModules, runtime] = data;
/******/ // add "moreModules" to the modules object,
/******/ // then flag all "chunkIds" as loaded and fire callback
/******/ var moduleId, chunkId, i = 0;
/******/ if(chunkIds.some((id) => (installedChunks[id] !== 0))) {
/******/ for(moduleId in moreModules) {
/******/ if(__webpack_require__.o(moreModules, moduleId)) {
/******/ __webpack_require__.m[moduleId] = moreModules[moduleId];
/******/ }
/******/ }
/******/ if(runtime) var result = runtime(__webpack_require__);
/******/ }
/******/ if(parentChunkLoadingFunction) parentChunkLoadingFunction(data);
/******/ for(;i < chunkIds.length; i++) {
/******/ chunkId = chunkIds[i];
/******/ if(__webpack_require__.o(installedChunks, chunkId) && installedChunks[chunkId]) {
/******/ installedChunks[chunkId][0]();
/******/ }
/******/ installedChunks[chunkId] = 0;
/******/ }
/******/
/******/ }
/******/
/******/ var chunkLoadingGlobal = self["webpackChunkvue3_demo_home"] = self["webpackChunkvue3_demo_home"] || [];
/******/ chunkLoadingGlobal.forEach(webpackJsonpCallback.bind(null, 0));
/******/ chunkLoadingGlobal.push = webpackJsonpCallback.bind(null, chunkLoadingGlobal.push.bind(chunkLoadingGlobal));
/******/ })();
上面代码有两个关键点:
-
chunkLoadingGlobal.push,也就是self["webpackChunkvue3_demo_home"].push方法被改写成了webpackJsonpCallback
-
webpackJsonpCallback里面__webpack_require__.m 也就是指向了 webpack_modules, 把push方法传入的参数解析到__webpack_modules__对象上,完成了模块赋值闭环。