web-dev-qa-db-fra.com

Gestion de la dépendance du plug-in jQuery dans Webpack

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 telles que jQuery et React. Que dois-je faire pour utiliser les plugins qui ont jQuery comme dépendances et je veux les avoir aussi dans vendors.js? Que se passe-t-il si ces plugins ont plusieurs dépendances?

Actuellement, j'essaie d'utiliser ce plugin jQuery ici - https://github.com/mbklein/jquery-elastic . La documentation Webpack mentionne ProvidePlugin et imports-loader. J'ai utilisé offerPlugin, 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 est toujours générée dans la console du navigateur:

Uncaught ReferenceError: jQuery n'est pas défini

De la même façon, quand j'utilise imports-loader, cela génère une erreur,

require n'est pas défini '

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 mais que je l'exige à la manière habituelle d'AMD, comme pour inclure 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 voudrait dire que jquery.elastic.source.js est fourni avec mon code JavaScript dans bundle.js, et je veux que tous mes plugins jQuery soient dans le paquet vendors.js. Alors, comment puis-je y parvenir?

412
booleanhunter

Vous avez mélangé différentes approches pour inclure des modules de fournisseur hérités. Voici comment je l'aborderais:

1. Préférez CommonJS/AMD non minié à 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 manière, webpack est en mesure d’optimiser les dépendances (par exemple, lorsqu’on utilise DedupePlugin ).

// webpack.config.js

module.exports = {
    ...
    resolve: {
        alias: {
            jquery: "jquery/src/jquery"
        }
    }
};

Cependant, dans la plupart des cas, la version dist fonctionne également très bien.


2. Utilisez le ProvidePlugin pour injecter des globals implicites

La plupart des modules existants s'appuient sur la présence de globaux spécifiques, comme les plugins jQuery sur $ ou jQuery. Dans ce scénario, vous pouvez configurer Webpack pour ajouter var $ = require("jquery") chaque fois qu'il rencontre l'identificateur global $.

var webpack = require("webpack");

    ...

    plugins: [
        new webpack.ProvidePlugin({
            $: "jquery",
            jQuery: "jquery"
        })
    ]

3. Utilisez le imports-loader pour configurer this

Certains modules hérités reposent sur le fait que this soit 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 remplacer this par imports-loader .

Exécutez npm i imports-loader --save-dev puis

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?this=>window"
        }
    ]
}

Le imports-loader peut également être utilisé pour injecter manuellement des variables de toutes sortes. Mais la plupart du temps, ProvidePlugin est plus utile en ce qui concerne les globals implicites.


4. Utilisez le imports-loader pour désactiver AMD.

Certains modules prennent en charge différents styles de modules, tels que AMD, CommonJS et Legacy. Cependant, la plupart du temps, ils vérifient d'abord define, puis utilisent un code bizarre pour exporter les propriétés. Dans ces cas, il pourrait être utile de forcer le chemin CommonJS en définissant define = false.

module: {
    loaders: [
        {
            test: /[\/\\]node_modules[\/\\]some-module[\/\\]index\.js$/,
            loader: "imports-loader?define=>false"
        }
    ]
}

5. Utilisez le script-loader pour importer globalement des scripts

Si vous ne vous souciez pas des variables globales et souhaitez simplement que les scripts hérités fonctionnent, vous pouvez également utiliser le chargeur de scripts. Il exécute le module dans un contexte global, comme si vous les aviez inclus via la balise <script>.


6. Utilisez noParse pour inclure les grandes distributions

Lorsqu'il n'existe pas de version AMD/CommonJS du module et que vous souhaitez inclure dist, vous pouvez le marquer en tant que noParse. Ensuite, webpack inclura simplement le module sans l’analyser, ce qui peut être utilisé pour améliorer le temps de compilation. Cela signifie que toute fonctionnalité nécessitant le AST , comme le ProvidePlugin, ne fonctionnera pas.

module: {
    noParse: [
        /[\/\\]node_modules[\/\\]angular[\/\\]angular\.js$/
    ]
}
731
Johannes Ewald

Pour un accès global à jquery, plusieurs options existent. Dans mon dernier projet de pack Web, je voulais un accès global à jquery. J'ai donc ajouté ce qui suit à mes déclarations de plugins:

 plugins: [
    new webpack.ProvidePlugin({
      $: "jquery",
      jQuery: "jquery"
    })
  ]

Cela signifie alors 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 concret de cette approche, n'hésitez pas à ajouter mon application github

82
arcseldon

Je ne sais pas si je comprends très bien ce que vous essayez de faire, mais je devais 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.$ = $;

Le je dois juste demander où je veux le jqueryplugin.min.js et window.$ est étendu avec le plugin comme prévu.

51
sanfilippopablo

Les choses fonctionnent bien tout en exposant $ et jQuery en tant que variables globales avec Webpack 3.8.1 et les suivants.

Installez jQuery en tant que dépendance de projet. Vous pouvez omettre @3.2.1 pour installer la dernière version ou spécifier une autre version.

npm install --save [email protected]

Installez expose-loader en tant que dépendance de développement, si ce n’est déjà fait.

npm install expose-loader --save-dev

Configurez Webpack pour charger et exposer jQuery pour nous.

// webpack.config.js
const webpack = require('webpack')

module.exports = {
  entry: [
    // entry bits
  ],
  output: {
    // output bits
  },
  module: {
    rules: [
      // any other rules
      {
        // Exposes jQuery for use outside Webpack build
        test: require.resolve('jquery'),
        use: [{
          loader: 'expose-loader',
          options: 'jQuery'
        },{
          loader: 'expose-loader',
          options: '$'
        }]
      }
    ]
  },
  plugins: [
    // Provides jQuery for other JS bundled with Webpack
    new webpack.ProvidePlugin({
      $: 'jquery',
      jQuery: 'jquery'
    })
  ]
}
18
HarlemSquirrel

Ajoutez ceci à votre tableau de plugins dans webpack.config.js

new webpack.ProvidePlugin({
    'window.jQuery': 'jquery',
    'window.$': 'jquery',
})

alors besoin de jquery normalement

require('jquery');

Si douleur persiste pour que d'autres scripts le voient, essayez explicitement de le placer dans le contexte global via (dans l'entrée js)

window.$ = jQuery;
16
KhaledMohamedP

Dans votre fichier webpack.config.js, ajoutez ci-dessous:

 var webpack = require("webpack");
 plugins: [
    new webpack.ProvidePlugin({
        $: "jquery",
        jQuery: "jquery"
    })
 ],

Installez jQuery en utilisant npm:

$ npm i jquery --save

Dans le fichier app.js, ajoutez les lignes suivantes:

import $ from 'jquery';
window.jQuery = $;
window.$ = $;

Cela a fonctionné pour moi. :)

15
ashwini

J'ai essayé certaines des réponses fournies mais aucune ne semblait fonctionner. Puis j'ai essayé ceci:

new webpack.ProvidePlugin({
    'window.jQuery'    : 'jquery',
    'window.$'         : 'jquery',
    'jQuery'           : 'jquery',
    '$'                : 'jquery'
});

Semble fonctionner quelle que soit la version que j'utilise

8
Cam Tullos

Cela fonctionne dans webpack 3:

dans le fichier webpack.config.babel.js:

resolve: {
    alias: {
         jquery: "jquery/src/jquery"
    },
 ....
}

Et utilisez ProvidePlugin

new webpack.ProvidePlugin({
        '$': 'jquery',
        'jQuery': 'jquery',
    })
7
SharpCoder

Cela fonctionne pour moi sur le webpack.config.js

    new webpack.ProvidePlugin({
        $: 'jquery',
        jQuery: 'jquery',
        'window.jQuery': 'jquery'
    }),

dans un autre javascript ou HTML, ajoutez:

global.jQuery = require('jquery');
2
JPRLCol

La meilleure solution que j'ai trouvée était:

https://github.com/angular/angular-cli/issues/5139#issuecomment-283634059

Fondamentalement, vous devez inclure une variable factice sur le fichier typings.d.ts, supprimer de votre code toute "importation * en tant que $ de 'jquery", puis ajouter manuellement une balise au script jQuery dans votre code html SPA. Ainsi, WebPack ne vous gênera pas et vous devriez pouvoir accéder à la même variable globale jQuery dans tous vos scripts.

2
Fabricio

Éditer: Parfois, vous voulez utiliser webpack simplement comme un bundle de modules pour un projet web simple - pour garder votre propre code organisé. La solution suivante est destinée à ceux qui souhaitent simplement qu'une bibliothèque externe fonctionne comme prévu dans leurs modules, sans passer beaucoup de temps à plonger dans les configurations Webpack. (Edité après -1)

Solution simple et rapide (es6) si vous avez encore du mal à éviter les configurations externes/externes avec le plugin webpack config:

<script src="cdn/jquery.js"></script>
<script src="cdn/underscore.js"></script>
<script src="etc.js"></script>
<script src="bundle.js"></script>

à l'intérieur d'un module:

const { jQuery: $, Underscore: _, etc } = window;
0
frdnrdb