webpack、rollup是否支持按window全局依赖存在性动态加载包?
Webpack、Rollup 等主流构建工具没有开箱即用的该动态依赖加载能力,但通过简单的配置配合自定义运行时代理逻辑,完全可以实现你描述的微应用场景下的灵活依赖加载效果,不需要修改构建工具底层源码。
核心实现思路
你需要的能力本质是运行时依赖降级策略,逻辑拆成三个环节即可落地:
- 构建阶段将每个第三方依赖单独打包为独立的bundle文件,和业务代码产物分离
- 依赖解析时优先检测window全局对象下是否存在对应依赖的全局变量
- 全局不存在对应依赖时,动态加载提前拆分好的对应依赖bundle,加载完成后再注入到业务代码的依赖引用链路中
Webpack 落地配置
首先通过splitChunks配置完成依赖单独拆包,匹配你举例的产物映射关系:
// webpack.config.js 核心配置片段 const path = require('path'); module.exports = { // 其余基础配置省略 optimization: { splitChunks: { chunks: 'all', cacheGroups: { react: { test: /[\\/]node_modules[\\/]react[\\/]/, name: 'a', filename: 'a.js', priority: 20 }, reactDom: { test: /[\\/]node_modules[\\/]react-dom[\\/]/, name: 'b', filename: 'b.js', priority: 20 }, uiLib: { test: /[\\/]node_modules[\\/]ui-lib[\\/]/, name: 'c', filename: 'c.js', priority: 20 } } } }, resolve: { alias: { // 将所有第三方依赖的引用指向自定义的依赖代理模块,通过query传递参数 react: path.resolve(__dirname, 'src/runtime/depProxy.js?globalKey=React&bundlePath=a.js'), 'react-dom': path.resolve(__dirname, 'src/runtime/depProxy.js?globalKey=ReactDOM&bundlePath=b.js'), 'ui-lib': path.resolve(__dirname, 'src/runtime/depProxy.js?globalKey=UiLib&bundlePath=c.js') } } }
然后编写依赖代理模块的运行时逻辑,实现「优先读全局,缺失则动态加载」的效果:
// src/runtime/depProxy.js const query = new URLSearchParams(__resourceQuery); const globalKey = query.get('globalKey'); const bundlePath = query.get('bundlePath'); // 优先命中全局依赖 if (window[globalKey]) { module.exports = window[globalKey]; } else { // 动态加载对应依赖bundle,微应用场景下依赖包体积普遍不大,同步请求不会造成明显阻塞 // 如果追求非阻塞体验,可以将应用入口改为异步启动模式,配合Promise完成依赖预加载 let depModule = null; const req = new XMLHttpRequest(); req.open('GET', bundlePath, false); req.onload = () => { depModule = eval(req.responseText); }; req.send(); module.exports = depModule; }
Rollup 落地配置
Rollup的实现逻辑和Webpack完全一致,仅配置API有区别:
- 通过
output.manualChunks配置指定每个第三方依赖单独输出为独立chunk,对应a.js/b.js/c.js的产物结构 - 通过alias插件将所有第三方依赖的引用指向和上文完全相同的运行时代理模块即可,不需要修改代理逻辑
- 如果需要更精细的拆包控制,可以搭配自定义rollup插件调整chunk生成规则
落地注意事项
- 建议在代理逻辑中增加版本校验逻辑:如果全局存在对应依赖,但版本和微应用预期版本不兼容,还是加载自有的依赖bundle,避免版本 mismatch 导致的运行时错误
- 动态加载依赖时建议使用绝对路径拼接bundle地址,避免受宿主应用的路由base路径影响导致资源加载404
- 如果团队内有多个微应用需要该能力,可以将依赖代理逻辑抽为公共运行时SDK,减少重复代码
内容的提问来源于stack exchange,提问作者duocai
相关产品推荐
相关产品推荐

