Използвам Webpack в моето приложение, в което създавам две входни точки - bundle.js за всички мои JavaScript файлове/кодове и vendors.js за всички библиотеки като jQuery и React. Какво трябва да направя, за да използвам плъгини, които имат jQuery като своя зависимост и искам да ги имам и във vendors.js? Какво да правя, ако тези плъгини имат множество зависимости?
В момента се опитвам да използвам този плъгин на jQuery тук - https://github.com/mbklein/jquery-elastic. В документацията на Webpack се споменават providePlugin и imports-loader. Използвах providePlugin, но все още обектът 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",
"window.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;
Но въпреки това в конзолата на браузъра все още се изписва грешка:
Uncaught ReferenceError: jQuery не е дефиниран
По подобен начин, когато използвам импортирането на товарача, то хвърля грешка,
require is not defined'
в този ред:
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 да бъдат в пакета vendors.js. И така, как да постигна това?
Смесвате различни подходи за включване на наследени модули на доставчика. Аз бих се справил по този начин:
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"
}
]
}
Import-loader може да се използва и за ръчно въвеждане на променливи от всякакъв вид. Но в повечето случаи ProvidePlugin
е по-полезен, когато става въпрос за имплицитни глобали.
Съществуват модули, които поддържат различни стилове на модулите, като AMD, CommonJS и legacy. В повечето случаи обаче те първо проверяват за define
и след това използват някакъв странен код за експортиране на свойства. В тези случаи може да е от полза да се наложи използването на пътя на CommonJS чрез задаване на define = false
.
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?define=>false"
}
]
}
Ако не се интересувате от глобалните променливи и просто искате наследените скриптове да работят, можете да използвате и скрипт-loader. Той изпълнява модула в глобален контекст, точно както ако ги бяхте включили чрез тага <script>
.
noParse
, за да включите големи дистрибуцииКогато няма AMD/CommonJS версия на модула и искате да включите dist
, можете да маркирате този модул като noParse
. Тогава webpack просто ще включи модула, без да го анализира, което може да се използва за подобряване на времето за изграждане. Това означава, че всяка функция, изискваща AST, като например ProvidePlugin
, няма да работи.
module: {
noParse: [
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
]
}
За глобален достъп до jquery има няколко възможности. В последния ми проект Webpack исках глобален достъп до jquery, затова добавих следното към декларациите на плъгините си:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
Това означава, че jquery е достъпен от изходния код на JavaScript чрез глобалните референции $ и jQuery.
Разбира се, трябва също така да сте инсталирали jquery чрез npm:
$ npm i jquery --save
За работещ пример на този подход, моля, не се колебайте да се възползвате от моето приложение в github
Не знам дали разбирам много добре какво се опитвате да направите, но трябваше да използвам плъгини jQuery, които изискваха jQuery да бъде в глобалния контекст (прозореца) и поставих следното в моя entry.js
:
var $ = require('jquery');
window.jQuery = $;
window.$ = $;
След това просто трябва да изисквам, където искам, jqueryplugin.min.js
и window.$
се разширява с плъгина, както се очаква.