Vo svojej aplikácii používam Webpack, v ktorom mám vytvorené dva vstupné body - bundle.js pre všetky súbory/kódy JavaScriptu a vendors.js pre všetky knižnice, ako je jQuery a React. Čo mám urobiť, aby som mohol používať zásuvné moduly, ktoré majú ako svoje závislosti jQuery a chcem ich mať aj vo vendors.js? Čo ak majú tieto zásuvné moduly viacero závislostí?
Momentálne sa snažím používať tento plugin jQuery tu - https://github.com/mbklein/jquery-elastic. V dokumentácii Webpack sa spomína providePlugin a imports-loader. Použil som providePlugin, ale objekt jQuery stále nie je k dispozícii. Takto vyzerá môj 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;
Ale napriek tomu to stále hádže chybu do konzoly prehliadača:
Uncaught ReferenceError: jQuery is not defined
Podobne, keď použijem import-loader, vyhodí to chybu,
require is not defined'
v tomto riadku:
var jQuery = require("jquery")
Mohol by som však použiť ten istý zásuvný modul, keď ho nepridám do súboru vendors.js a namiesto toho ho vyžadujem normálnym spôsobom AMD, ako keď zahŕňam svoje ostatné súbory s kódom JavaScript, ako napríklad-
define(
[
'jquery',
'react',
'../../common-functions',
'../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
$("#myInput").elastic() //It works
});
Ale to nie je to, čo chcem urobiť, pretože by to znamenalo, že jquery.elastic.source.js je spolu s mojím kódom JavaScript v zväzku bundle.js a ja chcem, aby všetky moje zásuvné moduly jQuery boli vo zväzku vendors.js. Ako to mám teda dosiahnuť?
Zmiešali ste rôzne prístupy, ako zahrnúť staršie moduly dodávateľa. Ja by som to riešil takto:
dist
Väčšina modulov spája verziu dist
v poli main
svojho súboru package.json
. Aj keď je to pre väčšinu vývojárov užitočné, pre webpack je lepšie aliasovať verziu src
, pretože takto dokáže webpack lepšie optimalizovať závislosti (napr. pri použití DedupePlugin
).
// webpack.config.js
module.exports = {
...
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}
};
Vo väčšine prípadov však rovnako dobre funguje aj verzia dist
.
ProvidePlugin
Väčšina starších modulov sa spolieha na prítomnosť špecifických globálov, ako to robia pluginy jQuery na $
alebo jQuery
. V tomto prípade môžete nakonfigurovať webpack tak, aby predvyplnil var $ = require("jquery")
vždy, keď narazí na globálny identifikátor $
.
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
this
Niektoré staršie moduly sa spoliehajú na to, že this
je objekt window
. To sa stáva problémom, keď je modul spustený v kontexte CommonJS, kde sa this
rovná module.exports
. V takom prípade môžete prepísať this
pomocou imports-loader.
Spustite npm i imports-loader --save-dev
a potom
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?this=>window"
}
]
}
Import-loader možno použiť aj na ručné injektovanie premenných všetkých druhov. Väčšinou je však ProvidePlugin
užitočnejší, keď ide o implicitné globály.
Existujú moduly, ktoré podporujú rôzne štýly modulov, napríklad AMD, CommonJS a legacy. Väčšinou však najprv skontrolujú, či je v nich define
, a potom použijú nejaký bizarný kód na export vlastností. V týchto prípadoch by mohlo pomôcť vynútiť cestu CommonJS nastavením define = false
.
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?define=>false"
}
]
}
Ak sa nestaráte o globálne premenné a chcete, aby fungovali len staršie skripty, môžete použiť aj skript-loader. Spustí modul v globálnom kontexte, rovnako ako keby ste ich zahrnuli prostredníctvom značky <script>
.
noParse
na zahrnutie veľkých distAk neexistuje verzia modulu AMD/CommonJS a chcete zahrnúť dist
, môžete tento modul označiť ako noParse
. Potom webpack len zahrnie modul bez jeho rozboru, čo sa dá použiť na zlepšenie času zostavenia. To znamená, že žiadna funkcia vyžadujúca AST, ako napríklad ProvidePlugin
, nebude fungovať.
module: {
noParse: [
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
]
}
Pre globálny prístup k jquery existuje niekoľko možností. V mojom najnovšom projekte Webpack som chcel globálny prístup k jquery, takže som do deklarácií zásuvných modulov pridal nasledujúce možnosti:
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
To potom znamená, že jquery je prístupné zo zdrojového kódu JavaScriptu prostredníctvom globálnych odkazov $ a jQuery.
Samozrejme, musíte mať nainštalované aj jquery prostredníctvom npm:
$ npm i jquery --save
Pre funkčný príklad tohto prístupu neváhajte forknúť moju aplikáciu na github.
Neviem, či dobre rozumiem tomu, čo sa snažíte urobiť, ale musel som použiť pluginy jQuery, ktoré vyžadovali, aby jQuery bolo v globálnom kontexte (okno) a do môjho súboru entry.js
som vložil nasledujúce:
var $ = require('jquery');
window.jQuery = $;
window.$ = $;
The I just have to require wherever I want the jqueryplugin.min.js
a window.$
je rozšírený o plugin podľa očakávania.