jQuery и приложения наследования

Дата обновления перевода 2021-08-12

jQuery и приложения наследования

Внутри Webpack, когда вам нужен модуль, он (обычно) не устанавливает глобальную переменную. Вместо этого, оно просто возвращает значение:

1
2
// загружает jquery, но *не* устанавливает глобальную переменную $ или jQuery
const $ = require('jquery');

На практике, это вызовет проблемы с некоторыми внешними библиотеками, которые полагаются на то, чтобы jQuery был глобальным. Это будет проблемой, если часть вашего JavaScript не обрабатывается через Webpack (например, у вас есть некоторый JavaScript в ваших шаблонах).

1
2
Uncaught ReferenceError: $ is not defined at [...]
Uncaught ReferenceError: jQuery is not defined at [...]

Решение проблемы зависит от того, какой код ее вызывает.

Исправление плагинов jQuery, которые ожидают, чтобы jQuery был глобальным

Плагины jQuery часто ожидают, что jQuery уже будет доступен через глобальные переменные $ или jQuery. Чтобы исправить это, вызовите autoProvidejQuery() из вашего файла webpack.config.js:

1
2
3
4
5
// webpack.config.js
  Encore
      // ...
+     .autoProvidejQuery()
  ;

После перезапуска Encore, Webpack будет искать все неинициализированные переменные $ и jQuery, и автоматически требовать jquery, а также устанавливать эти переменные для вас. Он "перезаписывает" "плохой" код, чтобы он был правильным.

Внутренне, этот метод autoProvidejQuery() вызывает метод autoProvideVariables() из Encore. На практике, это эквивалентно следующему:

1
2
3
4
5
6
7
8
9
10
Encore
    // вы можете использовать этот метод, чтобы предоставить другие общие глобальные переменные
    // такие, как '_' для библиотеки 'underscore'
    .autoProvideVariables({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery',
    })
    // ...
;

Получение доступа к jQuery извне файлов Webpack JavaScript

Если вашему коду также нужен доступ к $ и jQuery, и вы находитесь в файле, который обрабатывается Webpack/Encore, вы должны убрать все ошибки "$ is not defined", затребовав у jQuery следующее: var $ = require('jquery').

Но если вам также нужно предоставить доступ к переменным $ и jQuery вне файлов JavaScript, обрабатываемых Webpack (к примеру, JavaScript, который все еще живет в ваших шаблонах), вам нужно вручную установить их как глобальные переменные в каком-то файле JavaScript, который загружается до вашего унаследованного кода.

Например, в вашем файле app.js, который обрабатывается Webpack, и загружается на каждой странице, добавьте:

1
2
3
4
5
6
7
// app.js

  // затребуйте jQuery нормально
  const $ = require('jquery');

+ // создайте глобальные переменные $ м jQuery
+ global.$ = global.jQuery = $;

Переменная global - это особый способ установки вещей в переменной window. В веб-контексте, использование global и window равнозначны, кроме того, что window.jQuery не будет работать при использовании autoProvidejQuery(). Другими словами, используйте global.

Кроме того, не забудьте установить опцию script_attributes.defer как false в вашем файле webpack_encore.yaml:

1
2
3
4
5
# config/packages/webpack_encore.yaml
webpack_encore:
    # ...
    script_attributes:
        defer: false

Это гарантирует то, что атрибута defer в вашем теге script не будет. Чтобы узнать больше, см, Перемещение <script> внутри <head> и атрибута "defer"