Definisci la variabile globale con il webpack


138

È possibile definire una variabile globale con webpack per ottenere qualcosa del genere:

var myvar = {};

Tutti gli esempi che ho visto stavano usando un file esterno require("imports?$=jquery!./file.js")

Risposte:


272

Esistono diversi modi per avvicinarsi ai globi:

1) Inserisci le tue variabili in un modulo.

Webpack valuta i moduli una sola volta, quindi l'istanza rimane globale e porta le modifiche da un modulo all'altro. Quindi, se crei qualcosa di simile a globals.jsed esporti un oggetto di tutti i tuoi globi, puoi import './globals'e leggere / scrivere in questi globi. È possibile importare in un modulo, apportare modifiche all'oggetto da una funzione e importare in un altro modulo e leggere tali modifiche in una funzione. Ricorda anche l'ordine in cui accadono le cose. Webpack prenderà prima tutte le importazioni e le caricherà per iniziare a partire da entry.js. Quindi verrà eseguito entry.js. Quindi, dove leggi / scrivi a livello globale è importante. Proviene dall'ambito radice di un modulo o in una funzione chiamata in seguito?

Nota : se si desidera che l'istanza sia newogni volta, utilizzare una classe ES6 . Tradizionalmente in JS dovresti capitalizzare le classi (al contrario della minuscola per gli oggetti) come
import FooBar from './foo-bar' // <-- Usage: myFooBar = new FooBar()

2) ProvidePlugin di Webpack

Ecco come puoi farlo utilizzando ProvidePlugin di Webpack (che rende un modulo disponibile come variabile in ogni modulo e solo quei moduli in cui lo usi effettivamente). Ciò è utile quando non si desidera continuare a digitare import Bar from 'foo'più e più volte. Oppure puoi portare un pacchetto come jQuery o lodash come globale qui (anche se potresti dare un'occhiata agli esterni di Webpack ).

Passaggio 1) Creare qualsiasi modulo. Ad esempio, un insieme globale di utilità sarebbe utile:

utils.js

export function sayHello () {
  console.log('hello')
}

Passaggio 2) Alias ​​il modulo e aggiungere a ProvidePlugin:

webpack.config.js

var webpack = require("webpack");
var path = require("path");

// ...

module.exports = {

  // ...

  resolve: {
    extensions: ['', '.js'],
    alias: {
      'utils': path.resolve(__dirname, './utils')  // <-- When you build or restart dev-server, you'll get an error if the path to your utils.js file is incorrect.
    }
  },

  plugins: [

    // ...

    new webpack.ProvidePlugin({
      'utils': 'utils'
    })
  ]  

}

Ora chiama semplicemente utils.sayHello()qualsiasi file js e dovrebbe funzionare. Assicurati di riavviare il tuo dev-server se lo stai usando con Webpack.

Nota: non dimenticare di dire alla tua linter del mondo, quindi non si lamenterà. Ad esempio, vedi la mia risposta per ESLint qui .

3) Utilizzare DefinePlugin di Webpack

Se vuoi solo usare const con valori stringa per i tuoi globali, puoi aggiungere questo plugin al tuo elenco di plugin Webpack:

new webpack.DefinePlugin({
  PRODUCTION: JSON.stringify(true),
  VERSION: JSON.stringify("5fa3b9"),
  BROWSER_SUPPORTS_HTML5: true,
  TWO: "1+1",
  "typeof window": JSON.stringify("object")
})

Usalo come:

console.log("Running App version " + VERSION);
if(!BROWSER_SUPPORTS_HTML5) require("html5shiv");

4) Utilizzare l'oggetto finestra globale (o globale del nodo)

window.foo = 'bar'  // For SPA's, browser environment.
global.foo = 'bar'  // Webpack will automatically convert this to window if your project is targeted for web (default), read more here: https://webpack.js.org/configuration/node/

Vedrai questo comunemente usato per i polyfill, ad esempio: window.Promise = Bluebird

5) Utilizzare un pacchetto come dotenv

(Per progetti lato server) Il pacchetto dotenv prenderà un file di configurazione locale (che è possibile aggiungere al proprio .gitignore se ci sono chiavi / credenziali) e aggiunge le variabili di configurazione all'oggetto process.env di Node .

// As early as possible in your application, require and configure dotenv.    
require('dotenv').config()

Crea un .envfile nella directory principale del tuo progetto. Aggiungi variabili specifiche dell'ambiente su nuove righe sotto forma di NAME=VALUE. Per esempio:

DB_HOST=localhost
DB_USER=root
DB_PASS=s1mpl3

Questo è tutto.

process.envora ha le chiavi e i valori che hai definito nel tuo .envfile.

var db = require('db')
db.connect({
  host: process.env.DB_HOST,
  username: process.env.DB_USER,
  password: process.env.DB_PASS
})

Appunti:

Per quanto riguarda gli esterni di Webpack , utilizzalo se desideri escludere alcuni moduli dall'inclusione nel bundle integrato. Webpack renderà il modulo disponibile a livello globale ma non lo inserirà nel pacchetto. Questo è utile per le grandi librerie come jQuery (perché i pacchetti esterni che agitano gli alberi non funzionano in Webpack ) dove li hai caricati sulla tua pagina già in tag di script separati (forse da una CDN).


3
+1. Sto ristrutturando un'app per sfruttare il webpack come strumento di compilazione e questo inizialmente non ha funzionato per me perché non avevo incluso alcun riferimento al mio utilsspazio dei nomi nel file di destinazione - inizialmente avevo appena inserito un punto di interruzione nel browser finestra sorgente e ho continuato a scervellarci perché utilsnon è stato definito Finalmente ho scoperto che webpack (piuttosto intelligentemente) solo include un modulo se il suo spazio dei nomi viene fatto riferimento almeno una volta. Pertanto, una volta eseguita la prefazione di una delle funzioni di utilità del file di destinazione utils, il modulo è stato incluso.
nb1987,

Sì, solo dove lo usi, lo rende disponibile. L'ho inserito nella prima riga della risposta, ma ho apportato una leggera modifica, quindi forse è meglio leggere. Grazie per il +1!
prograhammer

1
Nota che ProvidePlugin carica effettivamente i moduli e se hai solo bisogno di una variabile, non funziona in questo modo. Basta usare externalsinvece se è necessario creare una variabile globale. Esempio: externals: { 'webpackVariables': `{ serverUrl: '${ env.server }', cordovaBuild: '${ env.cordova }', }`, }, quindi const webpackVariables = require('webpackVariables');
usalo

1
E sai come posso usare questo approccio con TypeScript? Lì se usi una variabile non dichiarata genera un errore ...
knaos,

2
@prograhammer In realtà, ho già trovato la soluzione. Nella radice dell'applicazione, in genere dove si trova tsconfig.json , è necessario aggiungere un file di definizione denominato global.d.ts . In esso puoi dichiarare le variabili globali, in questo modo: declare const isProduction: bool;Per riferimento, dai un'occhiata a typescriptlang.org/docs/handbook/declaration-files/templates/…
knaos,

45

Stavo per fare la stessa domanda. Dopo aver cercato un po 'di più e aver decifrato parte della documentazione del webpack, penso che quello che vuoi sia il output.librarye output.libraryTargetnel webpack.config.jsfile.

Per esempio:

JS / index.js:

var foo = 3;
var bar = true;

webpack.config.js

module.exports = {
   ...
   entry: './js/index.js',
   output: {
      path: './www/js/',
      filename: 'index.js',
      library: 'myLibrary',
      libraryTarget: 'var'
   ...
}

Ora, se colleghi il www/js/index.jsfile generato in un tag di script html, puoi accedere myLibrary.fooda qualsiasi parte degli altri script.


3
Penso che questo manchi export { foo }dal index.js?
LondonAppDev,

myLibrary fornisce indefinito in un altro file nel mio caso. Potete per favore aiutarmi
RVCoder

17

Usa DefinePlugin .

DefinePlugin consente di creare costanti globali che possono essere configurate in fase di compilazione.

new webpack.DefinePlugin(definitions)

Esempio:

plugins: [
  new webpack.DefinePlugin({
    PRODUCTION: JSON.stringify(true)
  })
  //...
]

Uso:

console.log(`Environment is in production: ${PRODUCTION}`);

14

Puoi usare define window.myvar = {}. Quando vuoi usarlo, puoi usare likewindow.myvar = 1


Questo non funziona con EMCAScript 6. Produce un errore con var window.CKEDITOR_BASEPATH = {};Errore "Token imprevisto" dopowindow.
Routhinator,

1
Scusate. Ho appena aggiornato la mia risposta. Dovresti varparole chiave. window.CKEDITOR_BASEPATH = {};
Anh Nguyen il

Questo funziona, sfortunatamente il problema che sto riscontrando è che ho bisogno che sia caricato nel bundle prima di CKEditor, tuttavia Webpack insiste nel metterlo dopo, indipendentemente da dove lo metto nelle mie importazioni / js. : /
Routhinator il

2

Ho risolto questo problema impostando le variabili globali come proprietà statiche sulle classi per le quali sono più rilevanti. In ES5 è simile al seguente:

var Foo = function(){...};
Foo.globalVar = {};
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.