Старая страница видит `$`, а новый модуль получает пустое значение. Цена ошибки — либо дублированная библиотека в каждом бандле, либо плагины, которые работают только из-за случайного порядка подключения.
Оригинальный материал правильно начинает с установки пакета и `ProvidePlugin`. В редактуре важно разделить две задачи: дать старому коду совместимое глобальное имя и оставить импорт явным в новых модулях. Если смешать их в одном правиле сборки, после смены entry-файла ошибка проявится только на части страниц.
Что сохраняем из исходной заметки
Webpack является одним из самых мощных и гибких инструментов для сборки фронтенд-проектов. Иногда необходимо включить в проект Webpack одну из самых популярных JavaScript библиотек jQuery.
Для начала необходимо установить jQuery из репозитория npm командой:
npm i jquery
либо (если используем менеджер пакетов Yarn):
yarn add jquery
Чтобы jQuery стал доступным в глобальной области видимости в «бандле» (собираемом пакете, от bundle) можно использовать ProvidePlugin (см. официальную документацию https://webpack.js.org/plugins/provide-plugin/):
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
}),
]
};
import $ from 'jquery';
global.jQuery = $;
global.$ = $;
Также jQuery можно подключить в проект Webpack через CDN с помощью плагина html-webpack-externals-plugin (https://www.npmjs.com/package/html-webpack-externals-plugin):
module.exports = {
plugins: [
new HtmlWebpackExternalsPlugin({ // optional plugin: inject cdn
externals: [
{
module: 'jquery',
entry: 'https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js'
}
],
}),
]
};
После чего можно использовать jQuery библиотеки, подключая их следующим образом:
require("inputmask/dist/inputmask/jquery.inputmask.js");
Итоговая схема подключения
Для старого проекта jQuery в Webpack лучше подключать явно: установить пакет, импортировать его в точке входа и отдельно решить вопрос с глобальными переменными. ProvidePlugin удобен, когда в модулях встречаются свободные идентификаторы $ или jQuery. Но если старый плагин лезет именно в window.jQuery, одного ProvidePlugin может быть мало — нужно положить jQuery в window самостоятельно.
import $ from 'jquery';
window.$ = $;
window.jQuery = $;
После этого можно добавить ProvidePlugin, чтобы не писать импорт в каждом файле:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
}),
],
};
Порядок подключения имеет значение. Сначала в entry-файле импортируем jQuery и кладём его в window, потом импортируем старые плагины, которым нужен глобальный объект. Если плагин подключается через require, делаем это после установки window.jQuery.
import './jquery-global';
import 'inputmask/dist/jquery.inputmask';
import './app';
Проверка простая: в браузерной консоли должны существовать window.$ и window.jQuery, а в собранном bundle не должно быть двух разных копий jQuery. Если проект новый, лучше не тащить jQuery без необходимости. Если проект старый и плагины уже написаны под jQuery, такая схема делает зависимость явной и предсказуемой.
Механизм без лишних обещаний
Webpack строит граф модулей из import и require. Глобальная переменная не входит в этот граф как обычная зависимость, поэтому старый плагин может работать только при дополнительном правиле ProvidePlugin или явной записи в window.
ProvidePlugin подставляет импорт в местах, где встречается идентификатор. Это не делает jQuery глобальной для любого скрипта, загруженного отдельно через HTML. Для такого скрипта нужен один согласованный entry и одна точка экспорта.
Если библиотека уже приходит с CDN, её следует объявить external и проверить, что глобальное имя появляется раньше потребителя. Две независимые копии jQuery дают разные объекты и ломают плагины, которые сравнивают `$.fn` или регистрируют обработчики.
Минимальный воспроизводимый пример
Ниже — маленькая проверка, которую можно запустить или адаптировать в отдельном тестовом окружении. Значения демонстрационные; проектные идентификаторы, пути и версии нужно заменить своими и сохранить рядом с результатом.
const webpack = require('webpack');
module.exports = {
entry: {
legacy: './src/legacy-entry.js',
modern: './src/modern-entry.js'
},
plugins: [
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
};
// В новом модуле зависимость остаётся видимой.
import $ from 'jquery';
export function mount() {
return $.fn && $.fn.jquery;
}
Матрица диагностики
| Слой | Что проверяем | Типичная ошибка |
|---|---|---|
| Новый модуль | Есть `import $ from 'jquery'` | Зависимость спрятана в window |
| Старый плагин | Потребитель получает тот же объект | Созданы две копии jQuery |
| Entry | Библиотека загружена до потребителя | Порядок зависит от HTML |
| CDN | external и глобальное имя согласованы | Бандл ожидает модуль, а получает URL |
Порядок действий
- Определить, какие файлы используют import, а какие обращаются к `$` или `window.jQuery`.
- Оставить один способ доставки jQuery для каждого entry: пакет или external, но не случайную смесь.
- Добавить ProvidePlugin только для legacy-кода и проверить итоговый граф сборки.
- Запустить страницу с реальным старым плагином и убедиться, что объект jQuery один.
- После миграции каждого потребителя удалить лишнее глобальное правило и зафиксировать это в тесте сборки.
Ограничения и безопасный следующий шаг
ProvidePlugin не исправляет порядок независимых `