Webpack и External Libs: ProvidePlugin vs entry vs global import?
1. ProvidePlugin()
Похож на широко используемый подход. Об этом gist, демонстрируя, как включить whatwg-fetch polyfill в сборку Webpack. Многие ответы на StackOverflow используют здесь и здесь.
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery',
'fetch': 'imports?this=>global!exports?global.fetch!whatwg-fetch'
})
👍 Плюсы
- Это работает. (пожалуйста, обновите этот список, если мне что-то не хватает)
👎 Минусы
- Необходимо отслеживать глобальные библиотеки в конфигурации Webpack.
2. entry: [...]
Я был немного удивлен этим подходом, когда обнаружил его в этот смысл, но он работает так же хорошо.
entry: [
'babel-polyfill',
'whatwg-fetch',
'jquery',
'webpack-hot-middleware/client',
path.join(process.cwd(), 'app/app.js')
],
👍 Плюсы
- Он работает.
- Я могу полностью удалить
ProvidePlugin()
.
👎 Минусы
- Необходимо отслеживать глобальные библиотеки в конфигурации Webpack.
3. Верхний уровень import
Это очень просто, см. пример app.js. Этот файл является точкой входа в приложение React.
/**
* app.js
*/
import 'whatwg-fetch';
import 'babel-polyfill';
import 'jquery';
👍 Плюсы
- Он работает так же хорошо.
- Простое добавление/удаление. Не нужно касаться конфигурации Webpack.
👎 Минусы
- Не похоже, что этот подход будет работать с плагинами jQuery, например. bootstrap.js.
Наблюдение. Между всеми тремя подходами я не заметил никаких изменений в размере пакета.
Есть ли один рекомендованный способ обработки глобальных библиотек с помощью Webpack (и React)? Может ли какое-либо из этих решений вызвать проблему с помощью рендеринга на стороне сервера?
Спасибо!
Ответы
Ответ 1
Я бы не рекомендовал публиковать библиотеки как глобальные, если вам это действительно не нужно, т.е. точка системы модуля должна явно объявлять зависимости, например.
// app.js
import $ from 'jquery';
$.ajax(...);
Если вам абсолютно необходимо jQuery на глобальном уровне, потому что третья сторона script требует его на вашей странице или, возможно, для отладки в консоли, а затем немного информации о подходе, которые вы указали:
ProvidePlugin
ProvidePlugin не будет раскрывать jQuery в глобальной сети и действительно предназначен для исправления сторонних модулей, которые неправильно полагаются на наличие глобального модуля, поэтому я бы не рекомендовал это, например.
// app.js
$.ajax(...);
Эффективно передается в:
// app.js
require('jquery').ajax(...);
Ввод и импорт верхнего уровня
Эти подходы не будут работать для обычного модуля UMD, такого как jQuery, поскольку jQuery достаточно умен, чтобы не подвергать себя глобальному при загрузке загрузчиком commonjs/amd/es6.
Однако эти два подхода идеально подходят для модулей с побочными эффектами, таких как babel-polyfill
/whatwg-fetch
, потому что они ничего не экспортируют, они по сути мутируют глобальную среду.
Моя рекомендация для jQuery заключается в том, чтобы использовать expose-loader
, который предназначен для экспорта экспорта модулей во всем мире, например.
// webpack.config.js
{
module: {
loaders: [
test: require.resolve('jquery'),
loader: 'expose-loader?jQuery!expose-loader?$'
]
}
}
Затем вам нужно будет импортировать его в код приложения:
// app.js
import $ from 'jquery';
$.ajax(...)
Но он доступен в глобальном режиме для других скриптов на странице для доступа, если это абсолютно необходимо:
// console
window.$
window.jQuery
ПРИМЕЧАНИЕ. Технически вы могли бы просто import 'jquery'
раз в вашей точке входа при использовании выгружающего загрузчика, а затем полагаться на глобальный в других модулях.
Как я уже сказал, на самом деле не рекомендуется размещать модуль, если вам это не нужно, даже если вы в настоящее время используете его в каждом другом модуле.
Ответ 2
Просто узнайте, что предоставляемая библиотека будет перезаписана, если вы используете несколько пакетов (точек входа) на одной странице при использовании ProvidePlugin. Примеры для RoR и Webpacker, но я предполагаю, что это не имеет значения.
Например, у вас есть в вашем макете:
javascript_pack_tag 'application',
'metronic'
А в конфигах у вас есть:
environment.plugins.append('Provide', new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
"window.jQuery": "jquery",
"window.$": "jquery",
_: 'underscore',
Handlebars: 'handlebars'
}));
Если в application.js
вам требуются библиотеки, которые мутируют JQuery, вы потеряете всю эту мутацию в metronic.js
и в браузере, даже если вы предоставите JQuery с помощью expose-loader.
Поправьте меня, если я ошибаюсь, вероятно, ProvidePlugin просто импортирует библиотеки в каждую точку входа.