Webpack ProvidePlugin vs esterni?


84

Sto esplorando l'idea di utilizzare Webpack con Backbone.js .

Ho seguito la guida rapida e ho un'idea generale di come funziona Webpack, ma non sono chiaro come caricare la libreria delle dipendenze come jquery / backbone / underscore.

Dovrebbero essere caricati esternamente <script>o è qualcosa che Webpack può gestire come lo shim di RequireJS?

Secondo il documento webpack: moduli di shimming , ProvidePlugine externalssembrano essere correlati a questo (così è bundle!loader da qualche parte) ma non riesco a capire quando usarli.

Grazie

Risposte:


153

È possibile entrambe le cose: puoi includere librerie con <script>(ad esempio, per utilizzare una libreria da un CDN) o includerle nel bundle generato.

Se lo carichi tramite <script>tag, puoi utilizzare l' externalsopzione per consentire la scrittura require(...)nei tuoi moduli.

Esempio con libreria da 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");

Esempio con libreria inclusa nel 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");

Il ProvidePlugingrado di mappare i moduli alle variabili (gratuito). Così si potrebbe definire: "Ogni volta che uso la variabile (gratuito) xyzall'interno di un modulo che (webpack) dovrebbe impostare xyza require("abc")."

Esempio senza ProvidePlugin:

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

Esempio con ProvidePlugin:

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

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

Sommario:

  • Libreria da CDN: usa <script>tag e externalsopzione
  • Libreria dal filesystem: include la libreria nel bundle. (Forse modificare le resolveopzioni per trovare la libreria)
  • externals: Rende le variabili globali disponibili come modulo
  • ProvidePlugin: Rende i moduli disponibili come variabili libere all'interno dei moduli

Da aggiungere newprima di webpack.ProvidePlugin webpack.github.io/docs/list-of-plugins.html
MK Yung,

Perché non utilizzare semplicemente il caricatore di script? Questo è molto più semplice, come ha spiegato
@dtothefp

Se il mio file webpack.config si trova in una cartella chiamata javascript e al suo interno ho una cartella chiamata vendor con il mio file jquery. il percorso non dovrebbe essere. risolvere: {alias: {jquery: "vendor / jquery-1.10.2.js"}}. Ancora non funziona per me usando l'alias
me-me

3
Basta passare un percorso assoluto all'opzione alias. Se si passa un percorso relativo è relativo alla posizione di require / import in webpack 1. In webpack 2 è relativo al file webpack.config.js risp. l'opzione di contesto.
Tobias K.

@TobiasK. Un percorso assoluto non collabora con le esportazioni predefinite. Ricevo un oggetto {__esModule: true, default: MY_DEFAULT_EXPORT}invece che MY_DEFAULT_EXPORTnei file.
mgol

26

Una cosa interessante da notare è che se usi la ProvidePlugincombinazione con la externalsproprietà ti permetterà di essere jQuerypassato alla chiusura del tuo modulo webpack senza doverlo esplicitamente require. Ciò può essere utile per il refactoring del codice legacy con molti riferimenti a file diversi $.

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

ora in index.js

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

avrà un output compilato con qualcosa di simile sotto passato alla webpackBootstrapchiusura:

/******/ ([
/* 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;

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

Pertanto, puoi vedere che $fa riferimento alla finestra / globale jQuerydal CDN, ma viene passato alla chiusura. Non sono sicuro che questa sia una funzionalità prevista o un hack fortunato, ma sembra funzionare bene per il mio caso d'uso.


non avevi bisogno di nessuno dei due plugin se non volevi require/importfarlo. $funzionerebbe semplicemente perché raggiungerà l'ambito globale, qualunque cosa accada. Il ProviderPluginrichiede l'analisi del AST quindi è un plugin costoso e aggiungere al vostro tempo di costruzione notevolmente. Quindi è fondamentalmente uno spreco.
faceyspacey.com

@dtohefp questa risposta è una manna dal cielo. Puoi spiegare perché ha ProvidePluginrestituito un oggetto simile, a myModule.defaultmeno che non abbia aggiunto il modulo a esterni? Non ho mai saputo che ci sarebbe stata una relazione diretta.
Slbox

11

So che questo è un vecchio post, ma ho pensato che sarebbe stato utile menzionare che il caricatore di script webpack potrebbe essere utile anche in questo caso. Dai documenti del webpack:

"script: esegue un file JavaScript una volta nel contesto globale (come nel tag script), i requisiti non vengono analizzati."

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

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

L'ho trovato particolarmente utile durante la migrazione di processi di compilazione precedenti che concatenano file di fornitori JS e file di app insieme. Un avvertimento è che il caricatore di script sembra funzionare solo tramite il sovraccaricorequire() e non funziona per quanto posso dire essendo specificato all'interno di un file webpack.config. Sebbene molti sostengano che il sovraccarico requiresia una cattiva pratica, può essere abbastanza utile per conciliare il fornitore e lo script dell'app in un unico pacchetto e allo stesso tempo esporre JS Globals che non devono essere spessorati in bundle webpack aggiuntivi. Per esempio:

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

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

Ciò renderebbe $ .cookie, History e moment disponibili a livello globale all'interno e all'esterno di questo bundle e raggrupperebbe queste librerie del fornitore con lo script main.js e tutti i suoi requirefile d.

Inoltre, utile con questa tecnica è:

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

che sta usando Bower, esaminerà il mainfile in ogni required librerie package.json. Nell'esempio precedente, History.js non ha un mainfile specificato, quindi è necessario il percorso del file.

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.