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" 属性。