使用Webpack Encore集成ekko-lightbox时出现Constructor未定义错误
我来帮你排查这个问题,你遇到的Uncaught TypeError: Cannot read property 'Constructor' of undefined本质是ekko-lightbox无法找到Bootstrap modal的构造函数,这和Webpack Encore的模块隔离机制以及jQuery的作用域有关,下面分步骤解决:
核心原因分析
Webpack默认会将每个entry文件作为独立的模块,你在global.js里引入的jQuery和Bootstrap只在global模块的作用域内有效,而members.js作为另一个模块,默认会重新引入一个独立的jQuery实例——这个实例上并没有Bootstrap的modal组件,所以ekko-lightbox访问$.fn.modal.Constructor时就会报错。
另外你提到的Encore默认加载ekko-lightbox压缩版的问题,是因为它的package.json里main字段指向了压缩文件,不过这只是调试不便,不是报错的核心原因。
解决方案
1. 让jQuery全局共享(关键步骤)
在webpack.config.js中启用Encore的自动提供jQuery功能,这样所有模块都会使用同一个全局的jQuery实例,Bootstrap的组件也会正确挂载到这个实例上:
// webpack.config.js Encore // ... 你的其他配置 .autoProvidejQuery() // 添加这一行 ;
2. 调整JS文件的引入逻辑
- 在
global.js中保持现有配置即可,不需要额外修改:
// global.js require('../css/global.scss'); require('jquery'); require('popper.js'); require('bootstrap');
(因为autoProvidejQuery会自动把jQuery暴露为全局的$和jQuery,所以不需要手动赋值var $ = require('jquery'))
- 修改
members.js,去掉重复的jQuery引入,直接使用全局的jQuery实例:
// members.js require('../css/members.scss'); require('ekko-lightbox'); // 现在它会使用全局的jQuery和Bootstrap $(document).ready(function () { $(document).on('click', '[data-toggle="lightbox"]', function (event) { event.preventDefault(); $(this).ekkoLightbox(); }); });
3. (可选)指定加载ekko-lightbox未压缩版
如果你不想修改package.json,可以在members.js里直接引入未压缩的源码文件,方便调试:
require('ekko-lightbox/dist/ekko-lightbox.js');
或者在webpack.config.js里配置别名,统一指定加载未压缩版:
// webpack.config.js Encore // ... 其他配置 .addAliases({ 'ekko-lightbox': 'ekko-lightbox/dist/ekko-lightbox.js' }) ;
4. 验证版本兼容性
虽然你更新了Bootstrap和jQuery版本,但还是要确认ekko-lightbox v5.3.0对Bootstrap 4的兼容性——你的JSFiddle能正常运行说明版本是兼容的,所以主要还是Webpack的模块作用域问题。
按照上述步骤调整后,ekko-lightbox就能正确访问到Bootstrap的modal构造函数,点击图片应该就能正常触发lightbox效果了。
内容的提问来源于stack exchange,提问作者robert

