jQuery 插件和使用 Webpack Encore 的遗留应用
在 Webpack 内部,当你 require 一个模块时,它(通常)不会设置全局变量。相反,它只是返回一个值。
1 2
// this loads jquery, but does *not* set a global $ or jQuery variable
const $ = require('jquery');
在实践中,这将导致一些外部库出现问题,这些库依赖 jQuery 作为全局变量,或者如果你的 JavaScript 没有通过 Webpack 处理(例如,你的模板中有些 JavaScript),并且你需要 jQuery。两者都会导致类似的错误。
1 2
Uncaught ReferenceError: $ is not defined at [...]
Uncaught ReferenceError: jQuery is not defined at [...]
修复方法取决于哪个代码引起了问题。
修复期望 jQuery 为全局变量的 jQuery 插件
jQuery 插件通常期望 jQuery 已经通过 $
或 jQuery
全局变量可用。要修复此问题,请从你的 webpack.config.js
文件中调用 autoProvidejQuery()
。
1 2 3 4 5
// webpack.config.js
Encore
// ...
+ .autoProvidejQuery()
;
重启 Encore 后,Webpack 将查找所有未初始化的 $
和 jQuery
变量,并自动 require jquery
并为你设置这些变量。它“重写”了“错误”的代码,使其正确。
在内部,autoProvidejQuery()
方法调用 Encore 的 autoProvideVariables()
方法。在实践中,它等同于执行以下操作:
1 2 3 4 5 6 7 8 9 10
Encore
// you can use this method to provide other common global variables,
// such as '_' for the 'underscore' library
.autoProvideVariables({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery',
})
// ...
;
从 Webpack JavaScript 文件外部访问 jQuery
如果你的代码需要访问 $
或 jQuery
,并且你位于 Webpack/Encore 处理的文件中,你应该通过 require jQuery 来删除任何“$ is not defined”错误:var $ = require('jquery')
。
但是,如果你还需要在 Webpack 处理的 JavaScript 文件之外(例如,仍然存在于你的模板中的 JavaScript)提供对 $
和 jQuery
变量的访问,则需要在某些 JavaScript 文件中手动将这些变量设置为全局变量,该文件在你的遗留代码之前加载。
例如,在你的 app.js
文件中(该文件由 Webpack 处理并在每个页面上加载),添加:
1 2 3 4 5 6 7
// app.js
// require jQuery normally
const $ = require('jquery');
+ // create global $ and jQuery variables
+ global.$ = global.jQuery = $;
global
变量是在 window
变量中设置内容的特殊方式。在 Web 上下文中,使用 global
和 window
是等效的,除了在使用 autoProvidejQuery()
时 window.jQuery
将不起作用。换句话说,使用 global
。
此外,请务必在你的 webpack_encore.yaml
文件中将 script_attributes.defer
选项设置为 false
:
1 2 3 4 5
# config/packages/webpack_encore.yaml
webpack_encore:
# ...
script_attributes:
defer: false
这将确保你的 script
标签上没有 defer
属性。有关更多信息,请参阅 将 <script> 移动到 <head> 内和 "defer" 属性。