想象一下,在webpack5還沒(méi)出來(lái)前,前端使用第三方組件庫(kù),例如使用 dayjs
日期處理庫(kù),都是通過(guò) npm i dayjs -s
安裝 dayjs
模塊到項(xiàng)目里,然后就可以通過(guò) require
或者 import
來(lái)使用。整個(gè)過(guò)程也不是很麻煩,但是如果某一天 dayjs
這個(gè)庫(kù)修復(fù)了一個(gè)重大bug,我們得重新通過(guò) npm 來(lái)安裝最新版本,然后重啟項(xiàng)目,那么有沒(méi)有一個(gè)更簡(jiǎn)單的方案呢?
成都創(chuàng)新互聯(lián)長(zhǎng)期為1000多家客戶提供的網(wǎng)站建設(shè)服務(wù),團(tuán)隊(duì)從業(yè)經(jīng)驗(yàn)10年,關(guān)注不同地域、不同群體,并針對(duì)不同對(duì)象提供差異化的產(chǎn)品和服務(wù);打造開放共贏平臺(tái),與合作伙伴共同營(yíng)造健康的互聯(lián)網(wǎng)生態(tài)環(huán)境。為南寧企業(yè)提供專業(yè)的網(wǎng)站設(shè)計(jì)制作、成都網(wǎng)站設(shè)計(jì),南寧網(wǎng)站改版等技術(shù)服務(wù)。擁有10年豐富建站經(jīng)驗(yàn)和眾多成功案例,為您定制開發(fā)。
本文首發(fā)于:https://www.1024nav.com/blog/webpck5-module-federation
為了減少對(duì) npm 包的安裝頻率,還有避免本地安裝 node_modules 包,webpack開發(fā)團(tuán)隊(duì)想出了一個(gè)解決方案,能否將第三方庫(kù)放到網(wǎng)絡(luò)上單獨(dú)部署,如果項(xiàng)目需要使用再?gòu)脑搸?kù)的地址上直接拉取下來(lái)使用,這樣就不需要通過(guò) npm 來(lái)安裝,更新指定依賴包,也方便實(shí)時(shí)保持庫(kù)的新版本。感覺(jué)有點(diǎn)類似以前通過(guò) cdn 引入第三方j(luò)s庫(kù)的感覺(jué)
模塊聯(lián)邦還可以實(shí)現(xiàn)微前端服務(wù)
微前端是一個(gè)技術(shù)棧無(wú)關(guān)的多應(yīng)用集成思想,將一個(gè)大應(yīng)用拆分成多個(gè)子應(yīng)用來(lái)開發(fā),每個(gè)子應(yīng)用可以使用自己的技術(shù)棧(vue,angularjs,reactjs,jquery)進(jìn)行獨(dú)立開發(fā),部署。最后通過(guò)主應(yīng)用基座來(lái)集成各個(gè)子應(yīng)用。具體細(xì)節(jié)這里不展開講
webpack提供了一個(gè) ModuleFederationPlugin
插件,能夠?qū)崿F(xiàn)模塊的發(fā)布和引入, ModuleFederationPlugin
插件常用的配置有以下幾個(gè)
shared: ['react', 'react-dom']
意思是宿主和引用依賴的模塊共享配置的庫(kù),如果host有該庫(kù)則不需要再次下載,直接使用host已有的庫(kù)接下來(lái)一步一步實(shí)現(xiàn)一個(gè)模塊聯(lián)邦功能
通過(guò)CRA(create react app)來(lái)創(chuàng)建一個(gè)應(yīng)用。我們創(chuàng)建一個(gè) common-component 項(xiàng)目
然后配置 ModuleFederationPlugin ,在 config-overrides.js 文件里面新增以下配置。關(guān)于 cra 如何自定義 webpack 配置可以查看這篇文章
module.exports = override(
config => {
config.output.publicPath = 'http://localhost:3000/';
return config;
},
addWebpackPlugin(new ModuleFederationPlugin({
name: 'ccomponent',
filename: "remoteEntry.js",
exposes: {
'./button': './src/button/index.jsx',
}
})),
);
注意這里的 publicPath 是必須的,獲取組件的時(shí)候會(huì)從當(dāng)前 host 下獲取 button 這個(gè)組件,通過(guò) ModuleFederationPlugin 的 exposes 選項(xiàng)暴露 button 組件。
我們?cè)?src 新建一個(gè) button 組件
// src/button/index.jsx
import React from 'react'
import PropTypes from 'prop-types'
const Button = props => {
const {
children
} = props;
return (
)
}
Button.propTypes = {
children: PropTypes.node.isRequired
}
export default Button
通過(guò) npm run start 啟動(dòng),這時(shí)候可以訪問(wèn)到 http://localhost:3000/remoteEntry.js
我們?cè)偻ㄟ^(guò) CRA 創(chuàng)建一個(gè)名稱 app 的項(xiàng)目,同樣的在 config-overrides.js 里面引入 ModuleFederationPlugin
module.exports = override(
addWebpackPlugin(new ModuleFederationPlugin({
name: 'app',
remotes: {
'ccomponent': 'ccomponent@http://localhost:3000/remoteEntry.js',
}
})),
);
cccomponent 是上面 common-component 項(xiàng)目里面配置的 name
然后在 app 里面使用 common-component 的 button 組件,這里使用 React.lazy 來(lái)異步加載該組件
const Button = React.lazy(() => import("ccomponent/button"));
function App() {
return (
);
}
到此為止,就可以在 app 項(xiàng)目里面看到 button 了,666~
webpack提供對(duì)模塊聯(lián)邦會(huì)使以后模塊使用更加方便,快捷,一切工具都是為了方便開發(fā),給 webpack 的貢獻(xiàn)者點(diǎn)個(gè)贊!