Webpack分包时报TypeError: callbacks[i] is not a function错误求助
解决Webpack分包vendor后bundle-loader触发
TypeError: callbacks[i] is not a function的问题 问题根源分析
我帮你梳理了下,这个错误的核心原因是生产环境中你给所有业务JS都全局配置了bundle-loader,但你的模块导入逻辑是同步的,两者的使用方式完全不匹配,再加上分包(splitChunks)的打包逻辑,最终触发了回调相关的异常。
具体来说:
bundle-loader的作用是实现模块的异步加载,它会返回一个加载函数,而不是直接返回模块导出的内容。但你在main.js里是直接同步导入responsiveMenu,然后直接执行responsiveMenu()——这相当于你在调用bundle-loader返回的加载函数,而不是真正的responsiveMenu函数,自然会出现"callbacks[i] is not a function"的错误。- 禁用分包时,模块打包的顺序和加载逻辑刚好没触发这个矛盾,但这只是暂时规避了问题,
bundle-loader的错误使用才是根本原因。
分步解决方案
1. 移除全局的bundle-loader配置(最直接的修复)
你的业务代码都是同步导入使用的,完全不需要bundle-loader。把生产环境下的JS规则里的bundle-loader去掉:
// 修改Webpack配置中module.rules里的生产环境JS规则: { test: /\.js$/, exclude: /(node_modules|bower_components)/, include: path.resolve(__dirname, 'assets/js'), use: ['happypack/loader'] }
2. 若确实需要异步加载模块(按需调整)
如果某个模块需要按需异步加载,不要全局配置bundle-loader,而是在导入该模块时单独使用:
// 比如异步加载responsiveMenu的写法: import loadResponsiveMenu from 'bundle-loader!./responsiveMenu'; // 在需要使用的时候调用加载函数,传入回调 loadResponsiveMenu(function(responsiveMenu) { responsiveMenu(); });
3. 优化模块导出逻辑(可选)
你的responsiveMenu.js导出是正常的,不过可以稍微优化下写法,确保初始化逻辑能正确触发:
export default function responsiveMenu() { // Responsive Menu function init() { const toggleTrigger = $('.mobile-toggle'); const menuWrap = $('.menu-responsive'); menuPositionSetup(menuWrap); triggerMenu(toggleTrigger, menuWrap); childItemsHandler(); } function menuPositionSetup(menu) { let headerHeight = $('.header').outerHeight(true); $(menu).css('top', headerHeight); $(menu).css({ height: 'calc(100% - ' + headerHeight + 'px)' }); } function triggerMenu(toggle, menu) { $(toggle).on('click', function(e) { mobileToggle($(this), menu); }); } function mobileToggle(trigger, menu) { $(menu).toggleClass('is-active'); $(trigger).toggleClass('is-active'); $('body').toggleClass('is-overflow-h'); } function childItemsHandler() { $('.menu-item-has-children > a').on('click', function(e) { if ($(this).hasClass('is-active')) { // Go to the link } else { // Open the sub menu $(this).addClass('is-active'); $(this) .parent() .find('.sub-menu') .slideDown(); e.preventDefault(); } }); } // 调用初始化函数,确保导入后执行responsiveMenu()能触发逻辑 init(); }
额外提示
- Webpack的
splitChunks已经可以很好地处理vendor(node_modules)和业务代码的分包,bundle-loader是用于按需异步加载特定模块的场景,不要把两者的用途混淆。 - 检查
HappyPack里的babel-loader配置,确保和你的.babelrc.js预设一致,避免编译时出现差异。
内容的提问来源于stack exchange,提问作者Freddie
相关产品推荐
相关产品推荐

