Gestire le dipendenze dei plugin jQuery in webpack
Sto usando Webpack nella mia applicazione, in cui creo due punti di ingresso - bundle.js per tutti i miei file/codici JavaScript, e vendors.js per tutte le librerie come jQuery e React. Cosa devo fare per utilizzare i plugin che hanno jQuery come dipendenze e voglio averli anche in vendors.js? E se questi plugin hanno più dipendenze?
Attualmente sto cercando di usare questo plugin jQuery qui - https://github.com/mbklein/jquery-elastic. La documentazione di Webpack menziona providePlugin e imports-loader. Ho usato providePlugin, ma ancora l'oggetto jQuery non è disponibile. Ecco come appare il mio 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;
Ma nonostante questo, lancia ancora un errore nella console del browser:
Uncaught ReferenceError: jQuery non è definito
Allo stesso modo, quando uso l'imports-loader, lancia un errore,
require non è definito'
in questa linea:
var jQuery = require("jquery")
Tuttavia, potrei usare lo stesso plugin quando non lo aggiungo al mio file vendors.js e invece lo richiedo nel modo normale AMD come includo i miei altri file di codice JavaScript, come-
define(
[
'jquery',
'react',
'../../common-functions',
'../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
$("#myInput").elastic() //It works
});
Ma questo non è quello che voglio fare, perché questo significherebbe che jquery.elastic.source.js è in bundle con il mio codice JavaScript in bundle.js, e io voglio che tutti i miei plugin jQuery siano nel bundle vendors.js. Quindi come posso fare per ottenere questo?
Hai mescolato diversi approcci su come includere i moduli legacy del fornitore. Questo è il modo in cui lo affronterei:
1. Preferire CommonJS/AMD non minato rispetto a `dist
La maggior parte dei moduli collega la versione
dist
nel campomain
del loropackage.json
. Mentre questo è utile per la maggior parte degli sviluppatori, per webpack è meglio dare un alias alla versionesrc
perché in questo modo webpack è in grado di ottimizzare meglio le dipendenze (ad esempio quando si usa ilDedupePlugin
.Tuttavia, nella maggior parte dei casi anche la versione
dist
funziona bene.2. Usare il
ProvidePlugin
per iniettare globals implicitiLa maggior parte dei moduli legacy si basa sulla presenza di specifici globali, come fanno i plugin jQuery su
$
ojQuery
. In questo scenario si può configurare webpack, per anteporrevar $ = require("jquery")
ogni volta che incontra l'identificatore globale$
.3. Usare il imports-loader per configurare
this
Alcuni moduli legacy si basano sul fatto che
this
sia l'oggettowindow
. Questo diventa un problema quando il modulo viene eseguito in un contesto CommonJS dovethis
è uguale amodule.exports
. In questo caso è possibile sovrascriverethis
con il imports-loader.Esegui
npm i imports-loader --save-dev
e poiL'imports-loader può anche essere usato per iniettare manualmente variabili di ogni tipo. Ma la maggior parte delle volte il
ProvidePlugin
è più utile quando si tratta di globali impliciti.4. Usa il imports-loader per disabilitare AMD
Ci sono moduli che supportano diversi stili di moduli, come AMD, CommonJS e legacy. Tuttavia, la maggior parte delle volte controllano prima la presenza di
define
e poi usano del codice bizzarro per esportare le proprietà. In questi casi, potrebbe essere utile forzare il percorso di CommonJS impostandodefine = false
.5. Usare lo script-loader per importare globalmente gli script
Se non ti importa delle variabili globali e vuoi solo che gli script legacy funzionino, puoi anche usare lo script-loader. Esegue il modulo in un contesto globale, proprio come se li avessi inclusi tramite il tag
<script>
.6. Usa
noParse
per includere grandi distQuando non c'è una versione AMD/CommonJS del modulo e si vuole includere il
dist
, si può contrassegnare questo modulo comenoParse
. Allora webpack includerà semplicemente il modulo senza analizzarlo, il che può essere usato per migliorare il tempo di compilazione. Questo significa che qualsiasi funzione che richieda il AST, come ilProvidePlugin
, non funzionerà.Per l'accesso globale a jquery esistono diverse opzioni. Nel mio progetto webpack più recente, volevo un accesso globale a jquery, quindi ho aggiunto quanto segue alle dichiarazioni dei miei plugin:
Questo significa che jquery è accessibile dall'interno del codice sorgente JavaScript tramite i riferimenti globali $ e jQuery.
Naturalmente, è necessario aver installato anche jquery tramite npm:
Per un esempio funzionante di questo approccio, sentitevi liberi di fare un fork della mia app su github
Non so se ho capito molto bene quello che stai cercando di fare, ma ho dovuto usare plugin jQuery che richiedevano che jQuery fosse nel contesto globale (finestra) e ho messo il seguente nel mio
entry.js
:Devo solo richiedere dove voglio il
jqueryplugin.min.js
ewindow.$
viene esteso con il plugin come previsto.