淺析關於webpack5模塊聯邦構建過程理解:3個重要概念理解(webpack構建產生資源包、remote暴露模塊、host消費)、host與remote兩個角色的依賴關系、案例解析(暴露模塊生成的各文件意思、對應項目加載對應組件、所需資源分離)、基本原理(先加載遠程依賴再加載本地依賴)


  關於其構建過程理解,主要學習這篇文章:https://blog.csdn.net/qq_40882724/article/details/116860994

一、三個概念

  首先,要理解三個重要的概念:

(1)webpack構建:一個獨立項目通過 webpack 打包編譯而產生資源包。

(2)remote:一個暴露模塊供其他 webpack 構建消費的webpack構建。

(3)host:一個消費其他 remote 模塊的 webpack 構建。

  簡言之:一個webpack構建可以是 remote(即服務的提供方),也可以是 host(即服務的消費方),也可以同時扮演服務提供者和服務消費者,完全看項目的架構。

二、host 與 remote 兩個角色的依賴關系

  可用下圖表示:

  需要指出的是,任何一個webpack構建既可以作為host消費方,也可以作為remote提供方,區別在於職責和webpack配置的不同。

三、案例實操解析

  項目依賴關系介紹,一共有三個微應用:lib-app、component-app、main-app,角色分別是:

(1)lib-app 作為 remote, 暴露了兩個模塊 react 和 react-dom

(2)component-app 作為 remote 和 host, 依賴 lib-app,暴露了一些組件供 main-app 消費

(3)main-app 作為 host,依賴lib-app和component-app

1、lib-app 暴露模塊

//webpack.config.js module.exports = { //...省略  plugins: [ new ModuleFederationPlugin({ name: "lib_app", filename: "remoteEntry.js", exposes: { "./react":"react", "./react-dom":"react-dom" } }) ], //...省略 }

  編譯后的結果如下:

  除去生成的 map文件,有四個文件:main.js、remoteEntry.js、...react_index.js、...react-dom_index.js;這里我們需要關注下:編譯生成的各文件的意思。

(1)第一個是本項目的入口文件(該項目只是暴露接口,所以該文件為空)

(2)第二個是遠程入口文件,其他webpack構建使用、訪問本項目暴露的模塊時,須通過它來加載

(3)第三個和第四個是暴露的模塊,供其他項目消費

2、component-app的配置

  依賴 lib-app 暴露三個模塊組件 ButtonDialogLogo

//webpack.config.js
module.exports = { //...省略
 plugins:[ new ModuleFederationPlugin({ name: "component_app", filename: "remoteEntry.js", exposes: { "./Button":"./src/Button.jsx", "./Dialog":"./src/Dialog.jsx", "./Logo":"./src/Logo.jsx" }, remotes:{ "lib-app":"lib_app@http://localhost:3000/remoteEntry.js" } }), ] }

  三個暴露的組件看原文章咯,這里只摘錄我覺得有用的了解學習。

3、main-app的配置

  main-app 依賴兩個項目 lin-appcomponent-app。這里的 remotes 就加載了 2 個。

///webpack.config.js
module.exports = { //省略...
 plugins: [ new ModuleFederationPlugin({ name: "main_app", remotes:{ "lib-app":"lib_app@http://localhost:3000/remoteEntry.js", "component-app":"component_app@http://localhost:3001/remoteEntry.js" }, }), new HtmlWebpackPlugin({ template: "./public/index.html", }) ] //省略...
};

  由於需要等待基礎模塊加載完畢,所以需要配置懶加載入口 bootstrap.js。

// 1、webpack打包入口文件
import("./bootstrap.js") // 2、bootstrap.js
import App from './App.jsx' import ReactDOM from 'lib-app/react-dom'; import React from 'lib-app/react' ReactDOM.render(<App />, document.getElementById("app"));
// 3、根組件App.jsx
import React from 'lib-app/react'; import Button from 'component-app/Button' import Dialog from 'component-app/Dialog' import Logo from 'component-app/Logo' export default class App extends React.Component{ constructor(props) { super(props) //省略...
 } //省略...
 render(){ return (<div>
      //省略...
    </div>) } }

  然后就會看到結論:

1、從對應項目加載到了需要的組件;

2、從查看控制台可以看到所需資源進行了很好的分離:

四、基本原理

  從 host 的代碼着手,簡單分析這一切是如何交互、工作的。程序從 main.js 里的一段代碼開始:

__webpack_require__.e("bootstrap_js").then(__webpack_require__.bind(__webpack_require__,"./bootstrap.js"))

  __webpack_require__.e("bootstrap_js")是加載 id 為bootstrap_js的chunk的所有依賴,返回一個promise。等一切依賴就緒,再獲取 ./bootstrap.js 模塊並執行。這里是__webpack_require__.e的代碼:

__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 對象並依次執行對象里的成員函數,此時該對象有兩個成員:

{ remotes:(chunkId, promises) => { //查找chunkId bootstrap_js對應的所有遠程模塊並加載
        var chunkMapping = { "bootstrap_js": [ "webpack/container/remote/lib-app/react", "webpack/container/remote/component-app/Button", //省略...
 ] }; var idToExternalAndNameMapping = { "webpack/container/remote/lib-app/react": [ "default", "./react", "webpack/container/reference/lib-app" ], "webpack/container/remote/component-app/Button": [ "default", "./Button", "webpack/container/reference/component-app" ], //...省略
 }; }, j:(chunkId,promises)=>{ //負責加載chunkId對應的本地模塊
 } }

  綜上,bootstrap_js 對應了兩個promises:

1、一個負責遠程依賴加載

2、另一個負責本地加載

  等到所有依賴模塊加載完准備就緒,才會 require 模塊並執行

  當然,細節遠不止此。現在這里先簡單了解下,以后真要技術選型,或項目中使用的話,再按需學習、深入研究吧。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM