前言
最近在产品的推波助澜下,部门增加了一条新的业务线“丁香实验”。这条业务线是“丁香通”业务线的补充业务。具体做的内容是:在丁香通平台进行实验器材、试剂的销售的同时,围绕实验的具体操作等等建立一个集“问、答、科普、百科”于一体化的科研平台。
既然是新的业务线,那从研发的角度出发,技术栈的选型有以下两点需要考虑:
- 项目需要 0 -> 1 进行搭建(周期不能太长,时间不等人)
- 要符合组内的未来技术路线
既然考虑的点列好了,那就来选择技术栈吧。
Module Federation
Module Federation(模块联邦)是 Webpack 5 新出的功能,作者是 Jack Herrington。
在 Webpack 的官方文档中,有这个功能的详细介绍。其中关于概念的介绍有很多,但是关于 API 的介绍却少的可怜。
1. 概念
- Container
- Remote Modules
- Local Modules
2. API
webpack.container.ModuleFederationPlugin
提供了 MF 的可配置 API:name
:输出的模块名称
filename
:构建输出的文件名称
library
:声明全局变量的方式library.name
:library.type
:
exposes
:暴露出的资源
shared
:其他项目可共享的资源shared.module.eager
shared.module.singleton
shared.module.requiredVersion
具体实现
A:主项目(提供 Remote Modules)
B:联邦项目(获取 Remote Modules 并与本地 Local Modules 相结合)
踩坑记录
B 项目引入 webpack.container.ModuleFederationPlugin
并配置后,MF
资源仍然从当前项目获取 。
问题定位:A 项目设置了
output.publicPath: '/'
,导致资源在加载时会从 B 项目进行加载。解决办法:将
output.publicPath
值设置为 auto
。// webpack.dev.js output: { publicPath: 'auto' }
B 项目引入 webpack.container.ModuleFederationPlugin
并配置后, MF
无效。
使用
MF
的项目,入口文件必须要使用动态加载的方式。// entry.js import('./bootstrap.js') // bootstrap.js import React from 'react' const render = () => { React.render( <App /> ), document.getElementById('root') }
A 项目在打包并部署后,B 项目模块资源加载失败,但 remoteEntry
能够正确加载。
问题定位:后发现是
optimization.runtimeChunk
将 runtime.js
从 remoteEntry.js
进行了拆分,而 B 项目在使用 remoteEntry.js
时, remoteEntry~runtime.js
并不会加载。解决方法:移除
optimization.runtimeChunk
选项。A 项目在本地开发时,重新刷新页面显示白屏,资源加载失败。
问题定位:URL 路径修改后,由于
output.publicPath
设置为了 auto
,刷新后的资源会从当前路由路径下进行请求,导致了 main.js
等文件路径错误。解决办法:将
publicPath
设置为 http://localhost:8080
。// webpack.dev.js output: { // ... publicPath: `http://${localConfig.clientHost}:${localConfig.clientPort}/` }
A 项目在本地开发时,HMR 失败。
看了下这个 issue,发现
webpack-dev-server
不支持 MF。解决办法:本地开发时,
remove
掉该 plugin
。相关资料
- 丁妈项目拆分中的选择
- 活动模块拆分过程与问题