Gestion de la dépendance du plugin 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 JavaScript/les codes et les fournisseurs.js pour toutes les bibliothèques comme jQuery et React. Que dois-je faire pour utiliser des plugins qui ont jQuery comme dépendances et je veux les avoir aussi dans les vendeurs.js? Et si ces plugins avaient plusieurs dépendances?

actuellement je suis en train d'essayer d'utiliser ce plugin jQuery ici - https://github.com/mbklein/jquery-elastic . La documentation de Webpack mentionne providePlugin et import-loader. J'ai utilisé providePlugin, mais l'objet jQuery n'est toujours pas disponible. Voici comment mon webpack.config.js ressemble à -

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;

mais malgré cela, il envoie toujours une erreur dans la console du navigateur:

Uncaught ReferenceError: jQuery n'est pas défini

de même, quand j'utilise le import-loader, il jette une erreur,

besoin n'est pas défini " les

dans cette ligne:

var jQuery = require("jquery")

cependant, je pourrais utiliser le même plugin quand je ne l'ajoute pas à mes vendeurs.le fichier js et à la place l'a exigé dans la manière AMD normale comme la façon dont 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 signifie que jquery.élastique.source.js est livré avec mon code JavaScript en paquet.js, et je veux que tous mes plugins jQuery soient dans les vendeurs.js bundle. Comment dois-je m'y prendre pour y parvenir?

359
demandé sur Florian Grell 2015-03-10 20:06:14

11 réponses

vous avez mélangé différentes approches comment inclure les modules fournisseurs traditionnels. C'est ainsi que je m'y attaquerais:

1. Prefer unminified CommonJS / AMD over 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'alias la version src parce que de cette façon webpack est capable d'optimiser les dépendances mieux (par exemple quand 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 tout aussi bien.


2. Utiliser le ProvidePlugin pour injecter des globals implicites

la plupart des anciens modules s'appuient sur la présence de globals spécifiques, comme le font les plugins jQuery sur $ ou jQuery . Dans ce scénario, vous pouvez configurer webpack, à ajouter var $ = require("jquery") chaque fois qu'il rencontre l'identifiant mondial $ .

var webpack = require("webpack");

    ...

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

3. Utiliser le import-loader pour configurer this

certains modules hérités 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 égale module.exports . Dans ce cas, vous pouvez outrepasser this avec le import-loader .

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

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

le chargeur imports peut également être utilisé pour injecter manuellement des variables de toutes sortes. Mais la plupart du temps le ProvidePlugin est plus utile quand il s'agit de l'implicite globals.


4. Utiliser le importations-loader pour désactiver AMD

il y a des modules qui prennent en charge différents styles de modules, comme AMD, CommonJS et legacy. Cependant, la plupart du temps ils vérifient d'abord pour define et ensuite utiliser certains excentrique code pour exporter des propriétés. Dans ces cas, il pourrait être utile de forcer la voie commune en mettant define = false .

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

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

Si vous ne vous souciez pas des variables globales et juste pour que les scripts hérités fonctionnent, vous pouvez aussi utiliser le script-loader. 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 grands dists

Lorsqu'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 va juste inclure le module sans parsing elle, qui peut être utilisé pour améliorer les temps de construction. Cela signifie que toute caractéristique nécessitant le AST , comme le ProvidePlugin , ne fonctionnera pas.

module: {
    noParse: [
        /[\/\]node_modules[\/\]angular[\/\]angular\.js$/
    ]
}
669
répondu Johannes Ewald 2017-02-27 06:45:12

pour l'accès global à jquery alors plusieurs options existent. Dans mon dernier projet webpack, je voulais un accès global à jquery et j'ai donc ajouté ce qui suit à mes déclarations de 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 sûr, vous devez aussi avoir installé jquery via npm:

$ npm i jquery --save

pour une exemple de cette approche s'il vous plaît n'hésitez pas à bifurquer mon application sur github

69
répondu arcseldon 2017-10-02 16:34:48

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.$ = $;

j'ai juste besoin là où je veux jqueryplugin.min.js et window.$ est étendu avec le plugin comme prévu.

50
répondu sanfilippopablo 2015-05-19 17:11:44

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

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

alors exiger jQuery normalement

require('jquery');

si la douleur persiste obtenir d'Autres scripts pour le voir, essayer de le placer explicitement dans le contexte global via (dans l'entrée js)

window.$ = jQuery;
15
répondu KhaledMohamedP 2016-10-07 02:40:51

j'ai obtenu que les choses fonctionnent bien tout en exposant $ et jQuery comme variables globales avec Webpack 3.8.1 et ce qui suit.

installer jQuery comme une 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 jquery@3.2.1

installer expose-loader comme une dépendance de développement si elle n'est pas déjà installée.

npm install expose-loader --save-dev

configurer 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'
    })
  ]
}
9
répondu HarlemSquirrel 2017-12-01 15:38:48

cela fonctionne dans webpack 3:

dans le webpack.config.Babel.fichier js:

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

et utiliser ProvidePlugin

new webpack.ProvidePlugin({
        '$': 'jquery',
        'jQuery': 'jquery',
    })
6
répondu SharpCoder 2017-08-08 18:54:29

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

5
répondu Cam Tullos 2017-08-31 00:26:45

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

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

en gros, vous devez inclure une variable fictive sur les typographies.D. ts, supprimez tout "importer * comme $ de 'jquery" de votre code, puis ajoutez manuellement une balise à jQuery script à votre html SPA. De cette façon, webpack ne sera pas sur votre chemin, et vous devriez être en mesure d'accéder à la même variable jQuery globale dans tous les vos scripts.

2
répondu the.fabricio 2017-05-23 18:55:55

Cela fonctionne pour moi sur le webpack.config.js

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

dans un autre javascript ou dans HTML ajouter:

global.jQuery = require('jquery');
2
répondu JPRLCol 2017-11-20 22:19:26

modifier: parfois, vous voulez utiliser webpack simplement comme un module bundler pour un projet web simple - pour garder votre propre code organisé. La solution suivante est pour ceux qui veulent juste qu'une bibliothèque externe fonctionne comme prévu à l'intérieur de leurs modules - sans passer beaucoup de temps à plonger dans les configurations webpack. (Révisé après -1)

solution rapide et simple (es6) si vous êtes encore en difficulté ou si vous voulez éviter les externes config / 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>

dans un module:

const { jQuery: $, Underscore: _, etc } = window;
0
répondu frdnrdb 2017-09-30 07:03:38

dans votre webpack.config.Ajouter ci-dessous:

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

installer jQuery en utilisant npm:

$ npm i jquery --save

Dans l'app.ajouter les lignes suivantes:

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

ça a marché pour moi. :)

0
répondu ashwini 2018-05-19 15:53:44