Webpack ProvidePlugin vs externes?

J'explore l'idée de l'utilisation de Webpack avec épine Dorsale.js .

J'ai suivi le guide de démarrage rapide et j'ai une idée générale du fonctionnement de Webpack, mais je ne sais pas comment charger la bibliothèque de dépendances comme jquery / backbone / underscore.

Devraient-ils être chargés en externe avec <script> ou est-ce quelque chose que Webpack peut gérer comme le shim de RequireJS?

Selon le document webpack : modules de shimming, ProvidePlugin et externals semblent être liés à cela (c'est donc bundle! loader quelque part) mais je ne peux pas savoir quand utiliser lequel.

Merci

75
demandé sur Henry 2014-04-26 05:39:52

3 réponses

C'est possible: vous pouvez inclure des bibliothèques avec un <script> (c'est-à-dire utiliser une bibliothèque à partir d'un CDN) ou les inclure dans le bundle généré.

Si vous le chargez via la balise <script>, Vous pouvez utiliser l'option externals pour permettre d'écrire require(...) dans vos modules.

Exemple avec la bibliothèque de CDN:

<script src="https://code.jquery.com/jquery-git2.min.js"></script>

// the artifial module "jquery" exports the global var "jQuery"
externals: { jquery: "jQuery" }

// inside any module
var $ = require("jquery");

Exemple avec la bibliothèque incluse dans le bundle:

copy `jquery-git2.min.js` to your local filesystem

// make "jquery" resolve to your local copy of the library
// i. e. through the resolve.alias option
resolve: { alias: { jquery: "/path/to/jquery-git2.min.js" } }

// inside any module
var $ = require("jquery");

Le ProvidePlugin peut mapper des modules à des variables (libres). Vous pouvez donc définir: "chaque fois que j'utilise la variable (libre) xyz dans un module, vous (webpack) devez définir xyz sur require("abc")."

Exemple sans ProvidePlugin:

// You need to require underscore before you can use it
var _ = require("underscore");
_.size(...);

Exemple avec ProvidePlugin:

plugins: [
  new webpack.ProvidePlugin({
    "_": "underscore"
  }) 
]

// If you use "_", underscore is automatically required
_.size(...)

Résumé:

  • bibliothèque de CDN: utilisez la balise <script> et l'optionexternals
  • Bibliothèque du système de fichiers: incluez la bibliothèque dans le bundle. (Peut-être modifier resolve options pour trouver la bibliothèque)
  • externals: Rendre les variables globales disponibles en tant que module
  • ProvidePlugin: rendre les modules disponibles en tant que variables libres à l'intérieur les modules
139
répondu Tobias K. 2014-10-01 11:27:50

Quelque chose de cool à noter est que si vous utilisez le ProvidePlugin en combinaison avec la propriété externals, il vous permettra d'avoir jQuery passé dans votre fermeture de module webpack sans avoir à explicitement require. Cela peut être utile pour refactorer le code hérité avec beaucoup de fichiers différents faisant référence à $.

//webpack.config.js
module.exports = {
  entry: './index.js',
  output: { 
    filename: '[name].js' 
  },
  externals: {
    jquery: 'jQuery'
  },
  plugins: [
    new webpack.ProvidePlugin({
      $: 'jquery',
    })
  ]
};

Maintenant dans l'index.js

console.log(typeof $ === 'function');

Aura une sortie compilée avec quelque chose comme ci-dessous passé dans la fermeture webpackBootstrap:

/******/ ([
/* 0 */
/***/ function(module, exports, __webpack_require__) {

    /* WEBPACK VAR INJECTION */(function($) {
        console.log(typeof $ === 'function');

    /* WEBPACK VAR INJECTION */}.call(exports, __webpack_require__(1)))

/***/ },
/* 1 */
/***/ function(module, exports, __webpack_require__) {

    module.exports = jQuery;

/***/ }
/******/ ])

Par conséquent, vous pouvez voir que $ fait référence au global / window jQuery à partir du CDN, mais est passé dans la fermeture. Je ne suis pas sûr si c'est une fonctionnalité prévue ou un hack chanceux, mais cela semble bien fonctionner pour mon cas d'utilisation.

21
répondu dtothefp 2015-06-02 04:18:33

Je sais que c'est un ancien post mais j'ai pensé qu'il serait utile de mentionner que le chargeur de script webpack peut également être utile dans ce cas. À partir des documents webpack:

"script: exécute un fichier JavaScript une fois dans un contexte global (comme dans la balise script), les requires ne sont pas analysés."

Http://webpack.github.io/docs/list-of-loaders.html

Https://github.com/webpack/script-loader

J'ai trouvé cela particulièrement utile lors de la migration de build plus ancienne processus qui concattent les fichiers fournisseurs JS et les fichiers d'applications ensemble. Un mot d'avertissement est que le chargeur de script semble fonctionner uniquement en surchargeant require() et ne fonctionne pas autant que je peux dire en étant spécifié dans un webpack.fichier de configuration. Bien que, beaucoup soutiennent que la surcharge require est une mauvaise pratique, il peut être très utile pour concéder le script du fournisseur et de l'application en un seul paquet, et en même temps exposer les Globals JS qui ne doivent pas être intégrés dans des bundles webpack supplémentaires. Pour exemple:

require('script!jquery-cookie/jquery.cookie');
require('script!history.js/scripts/bundled-uncompressed/html4+html5/jquery.history');
require('script!momentjs');

require('./scripts/main.js');

Cela ferait $.cookie, historique et moment globalement disponibles à l'intérieur et à l'extérieur de ce bundle, et regrouper ces bibliothèques de fournisseur avec le principal.script js et tous ses fichiers requireD.

Aussi, utile avec cette technique est:

resolve: {
  extensions: ["", ".js"],
  modulesDirectories: ['node_modules', 'bower_components']
},
plugins: [
  new webpack.ResolverPlugin(
    new webpack.ResolverPlugin.DirectoryDescriptionFilePlugin("bower.json", ["main"])
   )
]

Qui utilise Bower, examinera le fichier main dans chaque paquet de bibliothèques requireD.json. Dans l'exemple ci-dessus, de l'Histoire.js n'a pas de fichier main spécifié, donc le chemin d'accès au fichier est nécessaire.

11
répondu dtothefp 2015-01-25 22:14:24