Webpack 5模塊聯邦引發微前端的革命?

echa攻城獅 發佈 2020-06-15T21:40:04+00:00

作者:奶爸碼農轉發連結:https://mp.weixin.qq.com/s/quG-DC8QWm3me2PNGpFXTwWebpack 5的模塊聯邦提供加載部分編譯好的代碼能力,這個似乎會成為微前端架構的標準實現。❞引言在當前的微前端實現中,我們需要通過一系列的技巧去實現。



作者:奶爸碼農

轉發連結:https://mp.weixin.qq.com/s/quG-DC8QWm3me2PNGpFXTw

Webpack 5的模塊聯邦提供加載部分編譯好的代碼能力,這個似乎會成為微前端架構的標準實現。

引言

在當前的微前端實現中,我們需要通過一系列的技巧去實現。正如上圖所示,微前端的公共依賴加載目前並沒有非常好的實現方案。然後,Webpack 5中的模塊聯邦將會改變這一現狀。

模塊聯邦可以去依賴一個遠程模塊,這個依賴會在運行時生效,並不影響編譯時。因此,這個遠程依賴的模塊就可以是一個微前端獨立模塊。同時,每個獨立模塊都可以申明公共的依賴庫,這樣也可以避免獨立模塊間的依賴包的冗餘和衝突。

這篇文章將一步步告訴你如何通過Webpack 5的模塊聯邦特性來搭建一個微前端應用。這裡可以找到原始碼。

示例

這個例子首先包含一個空殼涵蓋兩個模塊(Home、Flights),這個空殼應用可以按需的加載各個微前端模塊。

下面是微前端模塊的部分-Flights,這部分其實也可以獨立運行。

通過這樣的架構可以實現各個模塊的獨立開發發布,同時又能夠按需的進行集成整合。

模塊聯邦

在過去要實現微前端的架構是非常困難的,尤其是像Webpack這類工具是需要在編譯階段保證全部代碼的完整性。懶加載是有可能的,但需要在編譯階段排除掉才行。

在微前端架構下,每個獨立模塊都需要獨立編譯打包,並且需要人工引入。大體的代碼如下:

import('http://other-microfrontend');

這樣的實現需要依賴external方式的JavaScript人工引入,在Webpack 5中這一實現方式將會得到改變。

模塊聯邦背後的原理非常簡單:宿主系統通過配置名稱來引用遠程模塊,同時在編譯階段宿主系統是不需要了解遠程模塊的,僅僅在運行時通過加載遠程模塊的入口文件來實現。

宿主系統實現

宿主系統用於引入遠程模塊。這個例子會加載一個遠程模塊「mfe1/component」,mfe1是配置的遠程模塊名,component是其中提供的一個文件。


const rxjs = await import('rxjs');

const container = document.getElementById('container');
const flightsLink = document.getElementById('flights');

rxjs.fromEvent(flightsLink, 'click').subscribe(async _ => {
    const module = await import('mfe1/component');
    const elm = document.createElement(module.elementName);
    […]    
    container.appendChild(elm);
});

在Webpack配置中,採用「ModuleFederationPlugin」可以來申明要使用的遠程模塊信息。

const ModuleFederationPlugin = require("webpack/lib/container/ModuleFederationPlugin");

[…]

plugins: [
  new ModuleFederationPlugin({
    name: "shell",
    library: { type: "var", name: "shell" },
    remotes: {
      mfe1: "mfe1"
    },
    shared: ["rxjs"]
  })
]

這樣遠程模塊「mfe1」就聲明完成了,Webpack在編譯階段就會把mfe1相關的引用都忽略,避免將其進行打包。

在shared中可以定義依賴的公共庫,這個例子就是rxjs。這樣就可以保證整個應用僅僅會加載rxjs庫一次,否則的話公共庫會被打包進入宿主應用,同時也會在各個子模塊中重複出現。

當然,shared的公共庫需要保證是一樣的版本。同時,宿主系統需要通過dynamic import的方式進行加載:

import * as rxjs from 'rxjs';

遠程模塊的實現

遠程模塊也是一個獨立系統,這裡採用web component方式實現:

class Microfrontend1 extends HTMLElement {

    constructor() {
        super();
        this.attachShadow({ mode: 'open' });
    }

    async connectedCallback() {
        this.shadowRoot.innerHTML = `[…]`;
    }
}

const elementName = 'microfrontend-one';
customElements.define(elementName, Microfrontend1);

export { elementName };

當然,你可以採用任何一種前端框架來實現,通用的框架庫可以用shared的方式在宿主和遠程模塊之間實現公用。

在遠程模塊的Webpack配置中,也需要使用「ModuleFederationPlugin」,將模塊暴露出去。

output: {
      publicPath: "http://localhost:3000/",
      […]
 },
 […]
 plugins: [
    new ModuleFederationPlugin({
      name: "mfe1",
      library: { type: "var", name: "mfe1" },
      filename: "remoteEntry.js",
      exposes: {
        component: "./mfe1/component"
      },
      shared: ["rxjs"]
    })
]

name定義了遠程模塊的配置名稱。通過遠程模塊名稱和暴露出來的組件名,宿主就可以遠程進行依賴引用:

import('mfe1/component')

最後,宿主還需要知道遠程模塊的url來真正引入。

宿主連接遠程模塊

宿主系統需要加載遠程的入口文件,這個文件是遠程模塊通過ModuleFederationPlugin打包產生的。

入口文件名定義在filename的配置中,這個例子定義為"remoteEntry.js"。微前端模塊的url定義在publicPath屬性上。

在宿主系統中引入遠程模塊入口文件:

const rxjs = await import('rxjs');const container = document.getElementById('container');const flightsLink = document.getElementById('flights');rxjs.fromEvent(flightsLink, 'click').subscribe(async _ => {    const module = await import('mfe1/component');    const elm = document.createElement(module.elementName);    […]        container.appendChild(elm);});

在這個例子中,我們提供了兩個系統

  • 宿主系統:地址是localhost:5000,會加載遠程模塊入口文件
  • 遠程模塊:地址是localhost:3000,提供了遠程模塊組件

結論

Webpack 5的模塊聯邦機制給微前端勢必會帶來革命性的變化。遠程的模塊可以獨立編譯,然後在運行時進行加載,同時還能夠定義公共庫來避免重複加載。

現在Webpack 5依舊還是beta版本,但我們已經可以預見在不久的將來,模塊聯邦將成為微前端架構中標準解決方案之一。

推薦JavaScript經典實例學習資料文章

《基於 Web 端的人臉識別身份驗證「實踐」》

《「前端進階」高性能渲染十萬條數據(時間分片)》

《「前端進階」高性能渲染十萬條數據(虛擬列表)》

《圖解 Promise 實現原理(一):基礎實現》

《圖解 Promise 實現原理(二):Promise 鏈式調用》

《圖解 Promise 實現原理(三):Promise 原型方法實現》

《圖解 Promise 實現原理(四):Promise 靜態方法實現》

《實踐教你從零構建前端 Lint 工作流「乾貨」》

《高性能多級多選級聯組件開發「JS篇」》

《深入淺出講解Node.js CLI 工具最佳實戰》

《延遲加載圖像以提高Web網站性能的五種方法「實踐」》

《比較 JavaScript 對象的四種方式「實踐」》

《使用Service Worker讓你的 Web 應用如虎添翼(上)「乾貨」》

《使用Service Worker讓你的 Web 應用如虎添翼(中)「乾貨」》

《使用Service Worker讓你的 Web 應用如虎添翼(下)「乾貨」》

《前端如何一次性處理10萬條數據「進階篇」》

《推薦三款正則可視化工具「JS篇」》

《如何讓用戶選擇是否離開當前頁面?「JS篇」》

《JavaScript開發人員更喜歡Deno的五大原因》

《僅用18行JavaScript實現一個倒數計時器》

《圖文細說JavaScript 的運行機制》

《一個輕量級 JavaScript 全文搜索庫,輕鬆實現站內離線搜索》

《推薦Web程式設計師常用的15個原始碼編輯器》

《10個實用的JS技巧「值得收藏」》

《細品269個JavaScript小函數,讓你少加班熬夜(一)「值得收藏」》

《細品269個JavaScript小函數,讓你少加班熬夜(二)「值得收藏」》

《細品269個JavaScript小函數,讓你少加班熬夜(三)「值得收藏」》

《細品269個JavaScript小函數,讓你少加班熬夜(四)「值得收藏」》

《細品269個JavaScript小函數,讓你少加班熬夜(五)「值得收藏」》

《細品269個JavaScript小函數,讓你少加班熬夜(六)「值得收藏」》

《深入JavaScript教你內存泄漏如何防範》

《手把手教你7個有趣的JavaScript 項目-上「附源碼」》

《手把手教你7個有趣的JavaScript 項目-下「附源碼」》

《JavaScript 使用 mediaDevices API 訪問攝像頭自拍》

《手把手教你前端代碼如何做錯誤上報「JS篇」》

《一文讓你徹底搞懂移動前端和Web 前端區別在哪裡》

《63個JavaScript 正則大禮包「值得收藏」》

《提高你的 JavaScript 技能10 個問答題》

《JavaScript圖表庫的5個首選》

《一文徹底搞懂JavaScript 中Object.freeze與Object.seal的用法》

《可視化的 JS:動態圖演示 - 事件循環 Event Loop的過程》

《教你如何用動態規劃和貪心算法實現前端瀑布流布局「實踐」》

《可視化的 js:動態圖演示 Promises & Async/Await 的過程》

《原生JS封裝拖動驗證滑塊你會嗎?「實踐」》

《如何實現高性能的在線 PDF 預覽》

《細說使用字體庫加密數據-仿58同城》

《Node.js要完了嗎?》

《Pug 3.0.0正式發布,不再支持 Node.js 6/8》

《純JS手寫輪播圖(代碼邏輯清晰,通俗易懂)》

《JavaScript 20 年 中文版之創立標準》

《值得收藏的前端常用60餘種工具方法「JS篇」》

《箭頭函數和常規函數之間的 5 個區別》

《通過發布/訂閱的設計模式搞懂 Node.js 核心模塊 Events》

《「前端篇」不再為正則煩惱》

《「速圍」Node.js V14.3.0 發布支持頂級 Await 和 REPL 增強功能》

《深入細品瀏覽器原理「流程圖」》

《JavaScript 已進入第三個時代,未來將何去何從?》

《前端上傳前預覽文件 image、text、json、video、audio「實踐」》

《深入細品 EventLoop 和瀏覽器渲染、幀動畫、空閒回調的關係》

《推薦13個有用的JavaScript數組技巧「值得收藏」》

《前端必備基礎知識:window.location 詳解》

《不要再依賴CommonJS了》

《犀牛書作者:最該忘記的JavaScript特性》

《36個工作中常用的JavaScript函數片段「值得收藏」》

《Node + H5 實現大文件分片上傳、斷點續傳》

《一文了解文件上傳全過程(1.8w字深度解析)「前端進階必備」》

《【實踐總結】關於小程序掙脫枷鎖實現批量上傳》

《手把手教你前端的各種文件上傳攻略和大文件斷點續傳》

《字節跳動面試官:請你實現一個大文件上傳和斷點續傳》

《談談前端關於文件上傳下載那些事【實踐】》

《手把手教你如何編寫一個前端圖片壓縮、方向糾正、預覽、上傳插件》

《最全的 JavaScript 模塊化方案和工具》

《「前端進階」JS中的內存管理》

《JavaScript正則深入以及10個非常有意思的正則實戰》

《前端面試者經常忽視的一道JavaScript 面試題》

《一行JS代碼實現一個簡單的模板字符串替換「實踐」》

《JS代碼是如何被壓縮的「前端高級進階」》

《前端開發規範:命名規範、html規範、css規範、js規範》

《【規範篇】前端團隊代碼規範最佳實踐》

《100個原生JavaScript代碼片段知識點詳細匯總【實踐】》

《關於前端174道 JavaScript知識點匯總(一)》

《關於前端174道 JavaScript知識點匯總(二)》

《關於前端174道 JavaScript知識點匯總(三)》

《幾個非常有意思的javascript知識點總結【實踐】》

《都2020年了,你還不會JavaScript 裝飾器?》

《JavaScript實現圖片合成下載》

《70個JavaScript知識點詳細總結(上)【實踐】》

《70個JavaScript知識點詳細總結(下)【實踐】》

《開源了一個 JavaScript 版敏感詞過濾庫》

《送你 43 道 JavaScript 面試題》

《3個很棒的小眾JavaScript庫,你值得擁有》

《手把手教你深入鞏固JavaScript知識體系【思維導圖】》

《推薦7個很棒的JavaScript產品步驟引導庫》

《Echa哥教你徹底弄懂 JavaScript 執行機制》

《一個合格的中級前端工程師需要掌握的 28 個 JavaScript 技巧》

《深入解析高頻項目中運用到的知識點匯總【JS篇】》

《JavaScript 工具函數大全【新】》

《從JavaScript中看設計模式(總結)》

《身份證號碼的正則表達式及驗證詳解(JavaScript,Regex)》

《瀏覽器中實現JavaScript計時器的4種創新方式》

《Three.js 動效方案》

《手把手教你常用的59個JS類方法》

《127個常用的JS代碼片段,每段代碼花30秒就能看懂-【上】》

《深入淺出講解 js 深拷貝 vs 淺拷貝》

《手把手教你JS開發H5遊戲【消滅星星】》

《深入淺出講解JS中this/apply/call/bind巧妙用法【實踐】》

《手把手教你全方位解讀JS中this真正含義【實踐】》

《書到用時方恨少,一大波JS開發工具函數來了》

《乾貨滿滿!如何優雅簡潔地實現時鐘翻牌器(支持JS/Vue/React)》

《手把手教你JS 異步編程六種方案【實踐】》

《讓你減少加班的15條高效JS技巧知識點匯總【實踐】》

《手把手教你JS開發H5遊戲【黃金礦工】》

《手把手教你JS實現監控瀏覽器上下左右滾動》

《JS 經典實例知識點整理匯總【實踐】》

《2.6萬字JS乾貨分享,帶你領略前端魅力【基礎篇】》

《2.6萬字JS乾貨分享,帶你領略前端魅力【實踐篇】》

《簡單幾步讓你的 JS 寫得更漂亮》

《恭喜你獲得治療JS this的詳細藥方》

《談談前端關於文件上傳下載那些事【實踐】》

《面試中教你繞過關於 JavaScript 作用域的 5 個坑》

《Jquery插件(常用的插件庫)》

《【JS】如何防止重複發送ajax請求》

《JavaScript+Canvas實現自定義畫板》

《Continuation 在 JS 中的應用「前端篇」》

作者:奶爸碼農

轉發連結:https://mp.weixin.qq.com/s/quG-DC8QWm3me2PNGpFXTw

關鍵字: