乡下人产国偷v产偷v自拍,国产午夜片在线观看,婷婷成人亚洲综合国产麻豆,久久综合给合久久狠狠狠9

  • <output id="e9wm2"></output>
    <s id="e9wm2"><nobr id="e9wm2"><ins id="e9wm2"></ins></nobr></s>

    • 分享

      三大應(yīng)用場(chǎng)景調(diào)研,Webpack 新功能 Module Federation 深入解析

       西北望msm66g9f 2020-05-06

      導(dǎo)讀:Federated Modules 是一個(gè)令人激動(dòng)的功能,它可能會(huì)改變未來幾年的前端打包方式,作者深入分析了 Module Federation 的原理及其應(yīng)用場(chǎng)景,希望能對(duì)大家有所啟發(fā)。

      WHAT(Module Federation 是什么?)

      Module Federation  [?fed??re??n] 使 JavaScript 應(yīng)用得以在客戶端或服務(wù)器上動(dòng)態(tài)運(yùn)行另一個(gè) bundle 的代碼。

      這其中的關(guān)鍵點(diǎn)是:

      • 動(dòng)態(tài),包含兩個(gè)含義:

        • 按需,可以把一個(gè)包拆開來加載其中一部分;

        • 運(yùn)行時(shí),跑在瀏覽器而非 node 編譯時(shí);

      • 另一個(gè) bundle 的代碼,之前應(yīng)用之間做共享是在文件級(jí)或 npm 包級(jí) export 成員,現(xiàn)在可以在應(yīng)用級(jí) export 成員屬性。


      一些相關(guān)的概念:

      • Remote,被 Host 消費(fèi)的 Webpack 構(gòu)建;

      • Host,消費(fèi)其他 Remote 的 Webpack 構(gòu)建;


      一個(gè)應(yīng)用可以是 Host,也可以是 Remote,也可以同時(shí)是 Host 和 Remote。



      HOW(它的原理是什么?)

      通過回答 Module Federation 如何運(yùn)轉(zhuǎn)?Host 如何消費(fèi) Remote?以及 Remote 如何優(yōu)先使用 Host shared 的依賴?這三個(gè)問題,我們分析一下 Module Federation 的原理。

      ModuleFederationPlugin

      整體是通過 ModuleFederationPlugin(https://github.com/webpack/webpack/blob/dev-1/lib/container/ModuleFederationPlugin.js)這個(gè)插件串聯(lián)起來的。

      配置示例:

      1. new ModuleFederationPlugin({

      2. name: 'app-1',

      3. library: { type: 'var', name: 'app_1' },

      4. filename: 'remoteEntry.js',

      5. remotes: {

      6. app_02: 'app_02',

      7. app_03: 'app_03',

      8. },

      9. exposes: {

      10. antd: './src/antd',

      11. button: './src/button',

      12. },

      13. shared: ['react', 'react-dom'],

      14. }),


      配置屬性:

      • name,必須,唯一 ID,作為輸出的模塊名,使用的時(shí)通過 ${name}/${expose} 的方式使用;

      • library,必須,其中這里的 name 為作為 umd 的 name;

      • remotes,可選,表示作為 Host 時(shí),去消費(fèi)哪些 Remote;

      • exposes,可選,表示作為 Remote 時(shí),export 哪些屬性被消費(fèi);

      • shared,可選,優(yōu)先用 Host 的依賴,如果 Host 沒有,再用自己的;




      產(chǎn)物:




      • main.js,應(yīng)用主文件;

      • remoteEntry.js,作為 remote 時(shí)被引的文件;

      • 一堆異步加載的文件,main.js 或 remoteEntry.js 里可能加載的文件;


      所以比如下面如圖示例的應(yīng)用集群:



      加載方式應(yīng)該這樣:

      1. <script src='C/remoteEntry.js'></script>

      2. <script src='B/remoteEntry.js'></script>

      3. <script src='A/main.js'></script


      C/remoteEntry.js 和 B/remoteEntry 的順序沒有要求,只要在 A/main.js 之前就好了。

      A 如何消費(fèi) B ?

      可以通過代碼示例來進(jìn)行理解。

      B 源碼:

      1. // src/react.js

      2. export * from 'react';

      3. // webpack.config.js

      4. ...

      5. exposes: {

      6. react: './src/react',

      7. },


      A 源碼:

      1. // 異步加載 B 的 react 模塊

      2. const React = await import('B/react');


      B 構(gòu)建產(chǎn)物:

      1. // windows 變量

      2. let B;

      3. const moduleMap = {

      4. 'react': () => {

      5. return Promise.all([e('a'), e('b'), e('c')]),

      6. },

      7. };

      8. B = {

      9. get(moduleId) {

      10. return moduleMap(moduleId);

      11. }

      12. }

      A 構(gòu)建產(chǎn)物:

      1. const modules = {

      2. 'B': () => {

      3. return B;

      4. }

      5. };

      6. // 異步獲取模塊 export 內(nèi)容

      7. function e(moduleId) {

      8. // 1. 取 shared 的模塊

      9. // 2. 取 remote 的模塊

      10. const idToExternalAndNameMapping = {

      11. 'B/react': ['B', 'react'],

      12. };

      13. // 從 module B 里取 react

      14. const data = idToExternalAndNameMapping[moduleId];

      15. __webpack_require__(data[0]).get(data[1]);

      16. // 3. 取當(dāng)前項(xiàng)目的異步模塊

      17. }

      18. // 初始化

      19. e('B/react');


      這其中的原理:

      • 多個(gè) Bundler 之間通過全局變量串聯(lián);

      • Remote 會(huì) export get 方法獲取他的子模塊,子模塊的獲取通過 Promise 以按需的方式引入;

      A 如何讓 B 用 A shared 的庫?

      再看如下兩個(gè)代碼示例。

      B 構(gòu)建產(chǎn)物:

      1. let B;

      2. __webpack_require__.Overrides = {};

      3. function e(moduleId) {

      4. // 1. 取 shared 的模塊

      5. // 當(dāng)前項(xiàng)目的 shared 模塊列表

      6. const fallbackMapping = {};

      7. // 先從 Overrides 里取,再從當(dāng)前項(xiàng)目里取

      8. push_require_try(__webpack_require__.Overrides[moduleId] || fallbackMapping[moduleId]);

      9. // 2. 取 remote 的模塊

      10. // 3. 取當(dāng)前項(xiàng)目的異步模塊

      11. }

      12. B = {

      13. override(override) {

      14. Object.assign(__webpack_require__.Overrides, override);

      15. }

      16. }


      A 構(gòu)建產(chǎn)物:

      1. B.override(Object.assign({

      2. 'react': () => {

      3. // A 的 react 內(nèi)容

      4. },

      5. }, __webpack_require__.Overrides));


      原理分析:

      • Remote(B)export override 方法,Host(A) 會(huì)調(diào)用其關(guān)聯(lián) Remote 的 override 方法,把 shared 的依賴寫進(jìn)去;

      • Remote(B) 獲取模塊時(shí)會(huì)優(yōu)先從 override 里取,沒有再從當(dāng)前 Bundle 的模塊索引里取;


      這樣,B 里面在 require react 時(shí),就會(huì)用 A 的 react 模塊。

      WHY(它的應(yīng)用場(chǎng)景有哪些?)

      Module Federation 可以用在哪里?

      微前端



      如上圖,這是去年畫的一張微前端的圖,其中最下面的 “公共依賴加載” 一直是沒有非常優(yōu)雅的方案。



      方法一:讓每個(gè)子應(yīng)用都分開打包,主應(yīng)用不管,這樣不會(huì)有問題,但問題就是尺寸大,而且大了不是一點(diǎn)點(diǎn)。

      方法二:主應(yīng)用包含 antd 和 react,子應(yīng)用如果版本一致不打包 react 和 antd,版本不一致就自己打一份,但有幾個(gè)問題:

        1. antd 和 react 是通過 umd 的方式同步載入的,主應(yīng)用初始化會(huì)比較慢;

        2. 主應(yīng)用升級(jí)了 antd 的時(shí)候,所有子應(yīng)用可能需要一起升級(jí),這個(gè)成本就很大了。


      方法三:利用 Module Federation 的 shared 能力,子應(yīng)用的依賴如果和主應(yīng)用匹配,那么,能解決方法二里的第一個(gè)問題,但第二個(gè)問題依舊解不了。

      方法四:利用 Module Federation 的 remotes 能力,再提一個(gè)應(yīng)用專門提供庫被消費(fèi),看起來前面的問題都能解。



      有沒有感覺技術(shù)又輪回到了 seajs + spmjs 的時(shí)代。

      應(yīng)用集群

      微前端是應(yīng)用集群的解法之一,但不是唯一方案。


      現(xiàn)狀是,通過 npm 共享組件。



      基于 Module Federation,除通過 npm 共享依賴,還可以有運(yùn)行時(shí)的依賴、組件、頁面甚至應(yīng)用的直接共享。



      這樣一來,靈活性就非常大了,可以在應(yīng)用的各個(gè)層面做共享。A 應(yīng)用引用 B 整個(gè)應(yīng)用,也可以應(yīng)用 B 的的頁面和組件,還可以提一個(gè)庫應(yīng)用,做 npm 依賴的運(yùn)行時(shí)共享。

      編譯提速,應(yīng)用秒開

      我們大部分場(chǎng)景不是微前端或應(yīng)用集群,Module Federation 還可以幫助我們干什么?


      現(xiàn)在項(xiàng)目組織和文件依賴通常是這樣:



      現(xiàn)狀是:

      • 全部打成一個(gè)包;

      • 打包時(shí)間較慢,據(jù)統(tǒng)計(jì),內(nèi)部云編譯平臺(tái)的平均編譯時(shí)間在 100s 以上;


      期望的是:

      • node_modules 下的提前打包好,通過 runtime 的方式引;

      • 本地調(diào)試和編譯時(shí)只打項(xiàng)目文件;

      • 快,根據(jù)項(xiàng)目復(fù)雜度可提升到 1s - 7s 之內(nèi);


      為什么不是其他的編譯速度優(yōu)化方案?



      舉一個(gè)對(duì)比的例子,比如 external,我們之前還有做過自動(dòng)的 external 方案,雖然他也可能顯著提速,但有以下問題:

      • 以空間換時(shí)間,依賴包全量引用導(dǎo)致 npm,用在生產(chǎn)上會(huì)犧牲部分產(chǎn)品體驗(yàn),需權(quán)衡;

      • 不是所有的依賴都有 umd 包,覆蓋率不夠;

      • npm 可能有依賴,比如 antd 依賴 react 和 moment,那么 react 和 moment 也得 external 并且在html 里引用他們;

      • 需要手動(dòng)修改 html 里的引用,維護(hù)上有成本提升。

      更多參考:


      關(guān)注「Alibaba F2E」

      把握阿里巴巴前端新動(dòng)向

        本站是提供個(gè)人知識(shí)管理的網(wǎng)絡(luò)存儲(chǔ)空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點(diǎn)。請(qǐng)注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請(qǐng)點(diǎn)擊一鍵舉報(bào)。
        轉(zhuǎn)藏 分享 獻(xiàn)花(0

        0條評(píng)論

        發(fā)表

        請(qǐng)遵守用戶 評(píng)論公約

        類似文章 更多