Webpack编译的JavaScript项目中common.js代码重复执行问题求解
解决Webpack项目中common.js代码重复执行的问题
嘿,我来帮你搞定这个问题!你遇到的情况是典型的模块顶级代码重复执行的问题,咱们一步步来分析和解决。
问题根源
你的common.js里,$(document).ready(...)是写在模块顶级作用域里的代码——也就是说,只要这个模块被加载(不管是直接通过<script>标签引入,还是被其他模块import),这段代码就会执行一次。
结合你的场景来看:
notcool.cshtml应该是直接引入了common.js的打包文件,所以只输出一次Loaded,符合预期;cool.cshtml引入了cool.js,而cool.js里import了common.js,Webpack打包时会把common.js的代码合并到cool.js里。如果这时候你的页面同时还引入了独立的common.js打包文件(可能你没在示例里写明,但实际是这样的),就会导致common.js的顶级代码执行两次:一次来自独立的common.js脚本,一次来自cool.js里打包进去的common.js代码。
解决方案
方案1:拆分初始化代码与导出函数(最推荐)
从根源上分离全局初始化逻辑和可复用函数,避免重复执行:
- 新建
common-init.js,专门存放全局初始化代码:
$(document).ready(function() { console.log("Loaded"); });
- 修改原
common.js,只保留需要导出的可复用函数:
export function doSomethingCool() { console.log("I just did something cool"); }
- 页面配置:
notcool.cshtml只引入common-init.js的打包文件;cool.cshtml同时引入common-init.js和cool.js的打包文件(或者通过Webpack配置让cool.js依赖common-init,但确保common-init只被加载一次)。
这样不管cool.js怎么导入common.js,初始化代码只会在common-init.js加载时执行一次。
方案2:给初始化代码加执行标志位(快速临时解决)
如果不想拆分文件,可以给全局初始化逻辑加一个全局标志,确保它只执行一次:
修改common.js:
// 用全局变量标记是否已经执行过初始化 if (!window.commonHasLoaded) { $(document).ready(function() { console.log("Loaded"); window.commonHasLoaded = true; }); } export function doSomethingCool() { console.log("I just did something cool"); }
这样不管这个模块被加载多少次,初始化代码只会在第一次加载时执行。
方案3:优化Webpack配置,提取公共模块
通过Webpack的代码分割功能,把common.js提取为单独的公共chunk,确保它只被加载一次:
在webpack.config.js里配置splitChunks:
module.exports = { // ...其他配置(入口、输出等) optimization: { splitChunks: { chunks: 'all', // 提取所有类型chunk中的公共代码 name: 'common', // 公共chunk的名称 }, }, };
然后页面里先引入common.js这个公共chunk,再引入cool.js:
<!-- cool.cshtml --> <script type="text/javascript" src="~/dist/common.js"></script> <script type="text/javascript" src="~/dist/cool.js"></script>
Webpack会自动处理模块依赖,确保common.js的代码只被执行一次,cool.js会复用已经加载的common模块,不会重复执行顶级代码。
内容的提问来源于stack exchange,提问作者Lee
相关产品推荐
相关产品推荐

