Я использую Webpack в своем приложении, в котором я создаю две точки входа - bundle.js для всех моих файлов/кодов JavaScript и vendors.js для всех библиотек, таких как jQuery и React. Что мне делать, чтобы использовать плагины с jQuery в качестве их зависимостей, и я хочу их также в vendors.js? Что делать, если эти плагины имеют несколько зависимостей?
В настоящее время я пытаюсь использовать этот плагин jQuery здесь - https://github.com/mbklein/jquery-elastic. В документации Webpack упоминается обеспечениеPlugin и import-loader. Я использовал offerPlugin, но все же объект jQuery недоступен. Вот как выглядит мой webpack.config.js -
var webpack = require('webpack');
var bower_dir = __dirname + '/bower_components';
var node_dir = __dirname + '/node_modules';
var lib_dir = __dirname + '/public/js/libs';
var config = {
addVendor: function (name, path) {
this.resolve.alias[name] = path;
this.module.noParse.push(new RegExp(path));
},
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jquery: "jQuery",
"windows.jQuery": "jquery"
}),
new webpack.optimize.CommonsChunkPlugin('vendors', 'vendors.js', Infinity)
],
entry: {
app: ['./public/js/main.js'],
vendors: ['react','jquery']
},
resolve: {
alias: {
'jquery': node_dir + '/jquery/dist/jquery.js',
'jquery.elastic': lib_dir + '/jquery.elastic.source.js'
}
},
output: {
path: './public/js',
filename: 'bundle.js'
},
module: {
loaders: [
{ test: /\.js$/, loader: 'jsx-loader' },
{ test: /\.jquery.elastic.js$/, loader: 'imports-loader' }
]
}
};
config.addVendor('react', bower_dir + '/react/react.min.js');
config.addVendor('jquery', node_dir + '/jquery/dist/jquery.js');
config.addVendor('jquery.elastic', lib_dir +'/jquery.elastic.source.js');
module.exports = config;
Но, несмотря на это, он по-прежнему вызывает ошибку в консоли браузера:
Неподготовлено ReferenceError: jQuery не определен
Аналогично, когда я использую import-loader, он выдает ошибку,
require не определен '
в этой строке:
var jQuery = require("jquery")
Однако я мог бы использовать тот же плагин, когда не добавляю его в файл vendors.js, а вместо этого требую его в обычном режиме AMD, так как я включаю в себя мои другие файлы кодов JavaScript, например -
define(
[
'jquery',
'react',
'../../common-functions',
'../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
$("#myInput").elastic() //It works
});
Но это не то, что я хочу сделать, поскольку это означало бы, что jquery.elastic.source.js поставляется вместе с моим кодом JavaScript в bundle.js, и я хочу, чтобы все мои jQuery-плагины были в поставщиках. js bundle. Итак, как мне добиться этого?
Вы использовали разные подходы, как включить устаревшие модули поставщиков. Вот как я справился бы с этим:
dist
Большинство модулей связывают версию dist
в поле main
своих package.json
. Хотя это полезно для большинства разработчиков, для webpack лучше использовать псевдоним версии src
, потому что таким образом webpack лучше оптимизирует зависимости (например, при использовании DedupePlugin
).
// webpack.config.js
module.exports = {
...
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}
};
Однако, в большинстве случаев версия dist
работает очень хорошо.
ProvidePlugin
для ввода неявных глобальных переменныхБольшинство устаревших модулей полагаются на присутствие определенных глобальных переменных, например плагины jQuery на $
или jQuery
. В этом случае вы можете настроить webpack, чтобы добавить var $ = require("jquery")
каждый раз, когда он встречает глобальный идентификатор $
.
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
this
Некоторые устаревшие модули полагаются на this
как объект window
. Это становится проблемой, когда модуль выполняется в контексте CommonJS, где this
равно module.exports
. В этом случае вы можете переопределить this
с помощью imports-loader.
Запустите npm i imports-loader --save-dev
, а затем
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?this=>window"
}
]
}
Импорт-загрузчик также может использоваться для ручного ввода переменных всех видов. Но большую часть времени ProvidePlugin
более полезен, когда дело доходит до неявных глобалов.
Существуют модули, поддерживающие разные стили модулей, такие как AMD, CommonJS и legacy. Однако большую часть времени они сначала проверяют на define
, а затем используют некоторый причудливый код для экспорта свойств. В этих случаях это может помочь принудительно установить путь CommonJS, установив define = false
.
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?define=>false"
}
]
}
Если вам не нужны глобальные переменные и вы хотите, чтобы устаревшие скрипты работали, вы также можете использовать script -loader. Он выполняет модуль в глобальном контексте, как если бы вы включили их через тег <script>
.
noParse
, чтобы включить большие кубикиЕсли версия модуля AMD/CommonJS отсутствует и вы хотите включить dist
, вы можете пометить этот модуль как noParse
. Тогда webpack будет включать в себя модуль без его разбора, который может быть использован для улучшения времени сборки. Это означает, что любая функция, требующая AST, как и ProvidePlugin
, не будет работать.
module: {
noParse: [
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
]
}
ProvidePlugin
применяется ко всем вхождениям указанных идентификаторов во всех файлах. imports-loader
может быть применен только к определенным файлам, но вы не должны использовать оба для тех же переменных / зависимостей.
Для глобального доступа к jquery существует несколько вариантов. В моем последнем проекте webpack мне нужен глобальный доступ к jquery, поэтому я добавил следующее в мои объявления плагинов:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
Это значит, что jquery доступен из исходного кода JavaScript через глобальные ссылки $и jQuery.
Конечно, вам нужно также установить jquery через npm:
$ npm i jquery --save
Для рабочего примера этого подхода, пожалуйста, не стесняйтесь разворачивать мое приложение на github
ProvidePlugin
решение ProvidePlugin
уже было предложено?
Я не знаю, хорошо ли я понимаю, что вы пытаетесь сделать, но мне пришлось использовать плагины jQuery, которые требовали, чтобы jQuery находился в глобальном контексте (окне), и я ввел следующее в entry.js
:
var $ = require('jquery');
window.jQuery = $;
window.$ = $;
Мне просто нужно требовать, где бы я хотел, чтобы jqueryplugin.min.js
и window.$
были расширены с плагином, как ожидалось.
Добавьте это в свой массив плагинов в webpack.config.js
new webpack.ProvidePlugin({
'window.jQuery': 'jquery',
'window.$': 'jquery',
})
тогда требуется обычно jquery
require('jquery');
Если боль не позволяет получить другие скрипты, попробуйте явно разместить ее в глобальном контексте через (в записи js)
window.$ = jQuery;
Я попробовал некоторые из предоставленных ответов, но никто из них, похоже, не работал. Затем я попробовал это:
new webpack.ProvidePlugin({
'window.jQuery' : 'jquery',
'window.$' : 'jquery',
'jQuery' : 'jquery',
'$' : 'jquery'
});
Кажется, работает независимо от того, какую версию я использую
$
за пределами необходимого файла веб-пакета, он будет неопределенным.
Это работает в webpack 3:
в файле webpack.config.babel.js:
resolve: {
alias: {
jquery: "jquery/src/jquery"
},
....
}
И используйте ProvidePlugin
new webpack.ProvidePlugin({
'$': 'jquery',
'jQuery': 'jquery',
})
У меня получилось хорошо работать при экспонировании $
и jQuery
в качестве глобальных переменных с помощью Webpack 3.8.1 и следующих.
Установите jQuery в качестве зависимости от проекта. Вы можете опустить @3.2.1
, чтобы установить последнюю версию или указать другую версию.
npm install --save [email protected]
Установите expose-loader
в качестве зависимостей разработки, если они уже не установлены.
npm install expose-loader --save-dev
Настройте Webpack для загрузки и отображения jQuery для нас.
// webpack.config.js
const webpack = require('webpack')
module.exports = {
entry: [
// entry bits
],
output: {
// output bits
},
module: {
rules: [
// any other rules
{
// Exposes jQuery for use outside Webpack build
test: require.resolve('jquery'),
use: [{
loader: 'expose-loader',
options: 'jQuery'
},{
loader: 'expose-loader',
options: '$'
}]
}
]
},
plugins: [
// Provides jQuery for other JS bundled with Webpack
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery'
})
]
}
expose-loader
, чтобы его правильно npm install expose-loader --save-dev
Это работает для меня на webpack.config.js
new webpack.ProvidePlugin({
$: 'jquery',
jQuery: 'jquery',
'window.jQuery': 'jquery'
}),
в другом javascript или в HTML add:
global.jQuery = require('jquery');
Лучшее решение, которое я нашел, это:
https://github.com/angular/angular-cli/issues/5139#issuecomment-283634059
В принципе, вам нужно включить фиктивную переменную в typings.d.ts, удалить из своего кода "import * as" из "jquery", а затем вручную добавить тег в jQuery script в ваш SPA html. Таким образом, веб-пакет не будет на вашем пути, и вы должны иметь доступ к одной и той же глобальной переменной jQuery во всех своих сценариях.
Изменить: иногда вы хотите использовать webpack просто как модуль для простого веб-проекта, чтобы сохранить свой собственный код. Следующее решение для тех, кто просто хочет, чтобы внешняя библиотека работала так, как ожидалось, в своих модулях - без использования большого количества времени для погружения в настройки веб-пакета. (Отредактировано после -1)
Быстрое и простое решение (es6), если вы все еще боретесь или хотите избежать внешней конфигурации config/дополнительного плагина webpack:
<script src="cdn/jquery.js"></script>
<script src="cdn/underscore.js"></script>
<script src="etc.js"></script>
<script src="bundle.js"></script>
внутри модуля:
const { jQuery: $, Underscore: _, etc } = window;