迁移Legacy JS项目到Webpack时如何导入导出全局App对象的属性
无需大规模重构的兼容方案
这个方案几乎不用修改原有业务逻辑,只需要调整入口和webpack配置即可对齐原有脚本拼接的运行行为:
- 第一步:改造入口
app.js,暴露全局App实例同时支持模块化导出
const App = (() => { const obj = { Lib: {}, Util: {}, // 原有其他属性 } return obj; })(); // 新增以下2行 window.App = App; export default App;
- 第二步:配置webpack全局注入App,消除每个文件手动导入的成本
// webpack.config.js const webpack = require('webpack'); const path = require('path'); module.exports = { // 其他原有配置不变 plugins: [ new webpack.ProvidePlugin({ App: [path.resolve(__dirname, '你项目中app.js的实际路径'), 'default'], }), ] }
- 第三步:调整依赖引入顺序
你之前拿不到导出值的核心原因是模块执行顺序问题,只要在用到App.Lib.Lazyload的文件中,先引入对应扩展模块触发挂载逻辑即可:
// 用到Lazyload的业务文件 import './lazyload.js'; // 先执行挂载,把Lazyload挂到App.Lib上 // 之后直接用App.Lib.Lazyload即可,已经被ProvidePlugin自动注入不需要额外导入 console.log(App.Lib.Lazyload);
如果需要导出扩展模块给其他地方用,直接在扩展文件末尾导出也能正常拿到:
// lazyload.js末尾 export default App.Lib.Lazyload;
// 其他导入的文件 import Lazyload from './lazyload.js'; // 此时lazyload.js先执行挂载,导出的就是正确的值
渐进式重构的最优建议
如果后续计划逐步消解全局依赖,可按以下低侵入步骤迭代:
- 先把各个独立扩展模块改为自包含导出,不需要依赖全局App挂载,比如lazyload.js直接导出实例:
export default (() => { // 原有lazyload逻辑不变 })();
- 在app.js中统一导入所有扩展模块,集中挂载到App对象上,统一管理所有依赖:
import Lazyload from './lazyload.js'; // 其他扩展模块的导入 const App = (() => { const obj = { Lib: { Lazyload, // 其他扩展属性 }, Util: {}, // 原有其他属性 } return obj; })(); export default App;
- 后续迭代过程中逐步把代码中直接访问
App.Lib.xxx的写法替换为直接import对应模块,逐步完成模块化改造,不会影响业务正常运行。
内容的提问来源于stack exchange,提问作者Ats
相关产品推荐
相关产品推荐

