J'utilise Webpack dans mon application, dans laquelle je crée deux points d'entrée : bundle.js pour tous mes fichiers/codes JavaScript, et vendors.js pour toutes les bibliothèques comme jQuery et React. Que dois-je faire pour utiliser des plugins qui ont jQuery comme dépendance et je veux les avoir aussi dans vendors.js ? Que faire si ces plugins ont des dépendances multiples ?
Actuellement, j'essaie d'utiliser ce plugin jQuery ici - https://github.com/mbklein/jquery-elastic. La documentation de Webpack mentionne [providePlugin][1] et imports-loader. J'ai utilisé providePlugin, mais l'objet jQuery n'est toujours pas disponible. Voici à quoi ressemble mon 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;
Malgré cela, une erreur s'affiche dans la console du navigateur :
Uncaught ReferenceError : jQuery n'est pas défini.
De même, lorsque j'utilise l'import-loader, une erreur est générée,
require is not defined' ;
dans cette ligne :
var jQuery = require("jquery")
Cependant, je pourrais utiliser le même plugin lorsque je ne l'ajoute pas à mon fichier vendors.js et que je l'exige à la place de la manière normale de l'AMD comme j'inclus mes autres fichiers de code JavaScript, comme...
define(
[
'jquery',
'react',
'../../common-functions',
'../../libs/jquery.elastic.source'
],function($,React,commonFunctions){
$("#myInput").elastic() //It works
});
Mais ce n'est pas ce que je veux faire, car cela signifierait que jquery.elastic.source.js est regroupé avec mon code JavaScript dans bundle.js, et je veux que tous mes plugins jQuery soient dans le bundle vendors.js. Comment dois-je m'y prendre pour y parvenir ?
Vous avez mélangé différentes approches sur la façon d'inclure les modules des anciens fournisseurs. Voici comment je m'y prendrais :
dist
.La plupart des modules lient la version dist
dans le champ main
de leur package.json
. Bien que cela soit utile pour la plupart des développeurs, pour webpack il est préférable d'aliaser la version src
car de cette façon webpack est capable de mieux optimiser les dépendances (par exemple en utilisant le DedupePlugin
).
// webpack.config.js
module.exports = {
...
resolve: {
alias: {
jquery: "jquery/src/jquery"
}
}
};
Cependant, dans la plupart des cas, la version dist
fonctionne très bien aussi.
ProvidePlugin
pour injecter des globales implicitesLa plupart des modules existants dépendent de la présence de globaux spécifiques, comme les plugins jQuery le font sur $
ou jQuery
. Dans ce scénario, vous pouvez configurer webpack pour qu'il ajoute en préambule var $ = require("jquery" ;)
chaque fois qu'il rencontre l'identifiant global $
.
var webpack = require("webpack");
...
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
this
.Certains anciens modules s'appuient sur le fait que this
est l'objet window
. Cela devient un problème lorsque le module est exécuté dans un contexte CommonJS où this
est égal à module.exports
. Dans ce cas, vous pouvez surcharger this
avec le imports-loader.
Lancez npm i imports-loader --save-dev
et ensuite
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?this=>window"
}
]
}
L'utilitaire imports-loader peut aussi être utilisé pour injecter manuellement des variables de toutes sortes. Mais la plupart du temps, le ProvidePlugin
est plus utile lorsqu'il s'agit de globales implicites.
Il existe des modules qui supportent différents styles de modules, comme AMD, CommonJS et legacy. Cependant, la plupart du temps, ils vérifient d'abord la présence de define
et utilisent ensuite un code bizarre pour exporter les propriétés. Dans ces cas, il peut être utile de forcer le chemin CommonJS en mettant define = false
.
module: {
loaders: [
{
test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
loader: "imports-loader?define=>false"
}
]
}
Si vous ne vous souciez pas des variables globales et que vous voulez simplement que les scripts hérités fonctionnent, vous pouvez également utiliser le script-loader. Il exécute le module dans un contexte global, comme si vous l'aviez inclus via la balise <script>
.
noParse
pour inclure de gros disques.Quand il n'y a pas de version AMD/CommonJS du module et que vous voulez inclure le dist
, vous pouvez marquer ce module comme noParse
. Alors webpack inclura simplement le module sans l'analyser, ce qui peut être utilisé pour améliorer le temps de construction. Cela signifie que toute fonctionnalité nécessitant le AST, comme le ProvidePlugin
, ne fonctionnera pas.
module: {
noParse: [
/[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
]
}
Pour un accès global à jquery, plusieurs options existent. Dans mon projet webpack le plus récent, je voulais un accès global à jquery et j'ai donc ajouté ce qui suit aux déclarations de mes plugins :
plugins: [
new webpack.ProvidePlugin({
$: "jquery",
jQuery: "jquery"
})
]
Cela signifie donc que jquery est accessible depuis le code source JavaScript via les références globales $ et jQuery.
Bien entendu, vous devez également avoir installé jquery via npm :
$ npm i jquery --save
Pour un exemple fonctionnel de cette approche, n'hésitez pas à forker mon application sur [github][1].
[1] : https://github.com/arcseldon/react-babel-webpack-starter-app
Je ne sais pas si je comprends très bien ce que vous essayez de faire, mais j'ai dû utiliser des plugins jQuery qui nécessitaient que jQuery soit dans le contexte global (fenêtre) et j'ai mis ce qui suit dans mon entry.js
:
var $ = require('jquery');
window.jQuery = $;
window.$ = $;
Je n'ai plus qu'à demander où je veux le fichier jqueryplugin.min.js
et window.$
est étendu avec le plugin comme prévu.