带有webpack-encore的ekko-lightbox:无法读取属性'构造函数'未定义的

时间:2018-01-30 12:42:00

标签: symfony webpack-encore

我想使用Symfony的webpack-encore来包含ekko-lightbox

我在这里创建了一个有效的jsFiddle演示:https://jsfiddle.net/92vq1z2b/。它和我一样使用相同版本的bootstrap,jQuery和ekko-lightbox。

在我当地的Symfony项目中,它并不起作用。当我点击" lightboxed"我在浏览器控制台中收到以下错误:

Uncaught TypeError: Cannot read property 'Constructor' of undefined
at new Lightbox (ekko-lightbox.js:97)
at HTMLAnchorElement.<anonymous> (ekko-lightbox.js:649)
at Function.each (jquery.js:362)
at jQuery.fn.init.each (jquery.js:157)
at jQuery.fn.init._jQueryInterface [as ekkoLightbox] (ekko-lightbox.js:645)
at HTMLAnchorElement.<anonymous> (members.js:8)
at HTMLDocument.dispatch (jquery.js:5206)
at HTMLDocument.elemData.handle (jquery.js:5014)

ekko-lightbox.js的第97行内容如下:

this._isBootstrap3 = $.fn.modal.Constructor.VERSION[0] == 3;

不知何故,webpack-encore似乎弄乱了javascript文件。但我找不到问题。

我的webpack.config.js看起来像这样:

// webpack.config.js
// ...
.addEntry('global', './assets/js/global.js')
.addEntry('public', './assets/js/public.js')
.addEntry('members', './assets/js/members.js')
// ...

global.js文件包括bootstrap,jQuery等:

// global.js
require('../css/global.scss');

var $ = require('jquery');
require('popper.js');
require('bootstrap');

members.js文件包含ekko-lightbox:

// members.js
require('../css/members.scss');

require('ekko-lightbox');

$(document).ready(function () {
    $(document).on('click', '[data-toggle="lightbox"]', function (event) {
        event.preventDefault();
        $(this).ekkoLightbox();
    });
});

在我的HTML代码中,global.js在members.js:

之前加载
// HTML code that loads the javascript files
<script src="/build/global.js"></script>    
<script src="/build/members.js"></script>

顺便说一下:由于某种原因,webpack-encore使用缩小版的ekko-lightbox,即ekko-lightbox.min.js。即使在开发模式下。我的期望是webpack-encore总是在开发模式下使用非缩小版本。我不得不更改ekko-lightbox package.json文件以更改此行为(package.json中的&#39; main&#39;条目先前指向.min.js文件,现在指向非缩小文件版)。我认为&#39;主要&#39;条目应始终指向目标文件而没有任何文件扩展名(它是如何在bootstrap的package.json中定义的)。也就是说,它应该看起来像"main": "dist/ekko-lightbox"而不是"main": "dist/ekko-lightbox.js""main": "dist/ekko-lightbox.min.js"

版本信息:

Google Chrome 63
"@symfony/webpack-encore": "^0.17.1",
"bootstrap": "^4.0.0-beta.3",
"jquery": "^3.2.1",
"ekko-lightbox": "^5.3.0"

更新:我注意到bootstrap v4已不再处于测试阶段。但运行npm update后问题仍然存在。我的新npm软件包版本如下(仅限顶级):

+-- @symfony/webpack-encore@0.17.1
+-- bootstrap@4.0.0
+-- ekko-lightbox@5.3.0
+-- jquery@3.3.1
+-- node-sass@4.7.2
+-- popper.js@1.13.0
+-- sass-loader@6.0.6
`-- webpack-notifier@1.5.1

1 个答案:

答案 0 :(得分:0)

经过大量调试后我解决了。问题是我如何包含jQuery和bootstrap。在我的global.js中,我明确要求jQuery进行require()调用。但是,这是由我的.autoProvidejQuery()中的行webpack.config.js由webpack-encore自动执行的。此外,webpack.config.js引用的每个javascript文件似乎都会自动提供jQuery。那就是:我的global.js,public.js和members.js每个都有一个单独的jQuery实例(顺便说一下:这也会减慢页面加载时间!)。

显然,这些单独的jQuery实例搞砸了引导程序模块注册(它们在jQuery.fn[MODULE_NAME]$.fn[MODULE_NAME]下注册。)

解决方案是创建一个所谓的shared entry to your webpack.config.js

我的webpack.config.js现在看起来像这样:

// ...
.addEntry('global', './assets/js/global.js')
.addEntry('public', './assets/js/public.js')
.addEntry('members', './assets/js/members.js')

.createSharedEntry('vendor', [
    'jquery',
    'popper.js',
    'bootstrap'
])

// allow sass/scss files to be processed
.enableSassLoader()

// allow legacy applications to use $/jQuery as a global variable
.autoProvidejQuery()
// ...

我的global.js不再需要jQuery或bootstrap,因为它们已经包含在共享模块中。全局CSS定义只剩下一个require()。

// global.js
require('../css/global.scss');

我的members.js没有改变,只是我添加了行require('ekko-lightbox/dist/ekko-lightbox.css');来包含ekko-lightbox自己的CSS定义。

最后,我只需扩展我的基本HTML模板,在任何其他javascript文件之前包含新的vendor.js和manifest.js:

{% block javascripts %}
<script src="{{ asset('build/manifest.js') }}"></script>
<script src="{{ asset('build/vendor.js') }}"></script>
<script src="{{ asset('build/global.js') }}"></script>
{% endblock %}