V svoji aplikaciji uporabljam paket Webpack, v katerem ustvarim dve vstopni točki - bundle.js za vse datoteke/kode JavaScript in vendors.js za vse knjižnice, kot sta jQuery in React. Kaj naj storim, če želim uporabljati vtičnike, ki imajo v odvisnosti jQuery in jih želim imeti tudi v vendors.js? Kaj če imajo ti vtičniki več odvisnosti?
Trenutno poskušam uporabiti ta vtičnik jQuery tukaj - https://github.com/mbklein/jquery-elastic. Dokumentacija Webpack omenja providePlugin in imports-loader. Uporabil sem providePlugin, vendar objekt jQuery še vedno ni na voljo. Tukaj je videti moj 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;
Toda kljub temu se v konzoli brskalnika še vedno pojavi napaka:
Neopažena referenčna napaka: jQuery ni definiran
Podobno se pojavi napaka, ko uporabim uvozni nalagalnik,
require is not defined'
v tej vrstici:
var jQuery = require("jquery")
Vendar pa bi lahko uporabil isti vtičnik, če ga ne bi dodal v datoteko vendors.js in bi ga namesto tega zahteval na običajen način AMD, tako kot sem vključil druge datoteke s kodo JavaScript, na primer-
define(
[
'jquery',
'react',
'../../common-functions',
'../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
$("#myInput").elastic() //It works
});
Vendar tega ne želim storiti, saj bi to pomenilo, da je jquery.elastic.source.js vključen skupaj z mojo kodo JavaScript v svežnju bundle.js, jaz pa želim, da so vsi moji vtičniki jQuery v svežnju vendors.js. Kako naj to dosežem?
Mešali ste različne pristope, kako vključiti starejše module prodajalcev. Jaz bi se tega lotil takole:
dist
imejte neokrnjenemu CommonJS/AMDVečina modulov poveže različico dist
v polju main
v svojem package.json
. Čeprav je to koristno za večino razvijalcev, je za webpack bolje, da je različica src
alias, saj lahko tako webpack bolje optimizira odvisnosti (npr. pri uporabi DedupePlugin
).
// webpack.config.js
module.exports = {
...
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}
};
Vendar pa v večini primerov tudi različica dist
deluje dobro.
ProvidePlugin
za vbrizgavanje implicitnih globalovVečina starejših modulov se zanaša na prisotnost določenih globalov, kot to počnejo vtičniki jQuery na $
ali jQuery
. V tem primeru lahko nastavite Webpack, da vsakič, ko naleti na globalni identifikator $
, doda var $ = require("jquery")
.
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
this
Nekateri starejši moduli se zanašajo na to, da je this
objekt okno
. To postane težava, ko se modul izvaja v kontekstu CommonJS, kjer je this
enak module.exports
. V tem primeru lahko this
prekrijete z ukazom imports-loader.
Zaženite npm i imports-loader --save-dev
in nato
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?this=>window"
}
]
}
Import-loader lahko uporabite tudi za ročno injiciranje vseh vrst spremenljivk. Vendar je največkrat bolj uporaben ProvidePlugin
, ko gre za implicitne globale.
Obstajajo moduli, ki podpirajo različne sloge modulov, kot so AMD, CommonJS in legacy. Vendar pa večinoma najprej preverijo, ali je v njih define
, nato pa za izvoz lastnosti uporabijo neko nenavadno kodo. V teh primerih lahko pomaga, če z nastavitvijo define = false
izsilimo pot CommonJS.
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?define=>false"
}
]
}
Če vam ni mar za globalne spremenljivke in želite le, da starejše skripte delujejo, lahko uporabite tudi script-loader. Ta izvede modul v globalnem kontekstu, kot če bi jih vključili prek oznake <script>
.
noParse
za vključitev velikih distribucijKadar ni različice modula AMD/CommonJS in želite vključiti dist
, lahko ta modul označite kot noParse
. Takrat bo Webpack samo vključil modul, ne da bi ga razčlenil, kar lahko uporabite za izboljšanje časa izgradnje. To pomeni, da nobena funkcija, ki zahteva AST, kot je ProvidePlugin
, ne bo delovala.
module: {
noParse: [
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
]
}
Za globalni dostop do programa jquery obstaja več možnosti. V svojem zadnjem projektu Webpack sem želel globalni dostop do jqueryja, zato sem v deklaracije vtičnikov dodal naslednje:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
To pomeni, da je jquery dostopen iz izvorne kode JavaScript prek globalnih referenc $ in jQuery.
Seveda morate imeti jquery nameščen tudi prek npm:
$ npm i jquery --save
Za delujoči primer tega pristopa si lahko ogledate mojo aplikacijo na github
Ne vem, če dobro razumem, kaj želite narediti, vendar sem moral uporabiti vtičnike jQuery, ki so zahtevali, da je jQuery v globalnem kontekstu (okno), in sem v svoj entry.js
vstavil naslednje:
var $ = require('jquery');
window.jQuery = $;
window.$ = $;
Nato moram samo zahtevati, kjerkoli želim, jqueryplugin.min.js
in window.$
se razširi z vtičnikom, kot je bilo pričakovano.