Esponi jQuery a un vero oggetto Window con Webpack


111

Voglio esporre l'oggetto jQuery all'oggetto finestra globale accessibile all'interno della console per sviluppatori nel browser. Ora nella mia configurazione del webpack ho le seguenti righe:

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

Queste righe aggiungono le definizioni jQuery a ogni file nei miei moduli webpack. Ma quando creo il progetto e provo ad accedere a jQuery nella console per sviluppatori in questo modo:

window.$;
window.jQuery;

dice che queste proprietà sono indefinite ...

C'è un modo per risolvere questo problema?


1
Posso impostare this: 'window'anche io ? Poiché molte librerie presumono che la thisvariabile sia l'oggetto Window
Abhinav Singi

Risposte:


129

È necessario utilizzare il caricatore di esposizioni .

npm install expose-loader --save-dev

Puoi farlo quando ne hai bisogno:

require("expose?$!jquery");

oppure puoi farlo nella tua configurazione:

loaders: [
    { test: require.resolve('jquery'), loader: 'expose?jQuery!expose?$' }
]

AGGIORNAMENTO : A partire dal webpack 2, è necessario utilizzare expose-loader invece di expose :

module: {
    rules: [{
        test: require.resolve('jquery'),
        use: [{
            loader: 'expose-loader',
            options: '$'
        }]
    }]
}

11
Il ProvidePlugindovrebbe essere utilizzato principalmente in situazioni in cui le librerie di terze parti si basano sulla presenza di una variabile globale.
Johannes Ewald

Ho fatto l'ipotesi errata che la domanda stesse utilizzando il plug-in di fornitura per scopi "pigri" che ho visto molto online ma hai ragione :)
Matt Derrick

8
Questo è esattamente quello che stavo cercando e solo per aggiungere altro, per i caricatori, puoi farlo anche in una riga:{test: /jquery\.js$/, loader: 'expose?jQuery!expose?$'}
Fernando

8
Non puoi semplicemente aggiungere un primo script che lo faccia $ = require('jquery'); window.jQuery = $; window.$ = $;? (non necessario expose-loader)
herman

1
Secondo la pagina esporre caricatore GitHub la sintassi webpack 2 è la seguente: module: { rules: [{ test: require.resolve('jquery'), use: [{ loader: 'expose-loader', options: 'jQuery' },{ loader: 'expose-loader', options: '$' }] }] }. Questo è l'unico modo in cui ho potuto esporre jQuery e sta usando la nuova sintassi module.rules .
Gavin Sutherland

84

ProvidePlugin sostituisce un simbolo in un'altra origine tramite la rispettiva importazione, ma non espone il simbolo nello spazio dei nomi globale. Un classico esempio sono i plugin jQuery. La maggior parte di loro si aspetta solo jQuerydi essere definita a livello globale. Con il ProvidePluginti assicureresti che jQuery sia una dipendenza (ad es. Caricato prima) e la presenza di jQuerynel loro codice verrebbe sostituita con l'equivalente grezzo webpack di require('jquery').

Se hai script esterni che fanno affidamento sul simbolo per essere nello spazio dei nomi globale (come diciamo un JS ospitato esternamente, chiamate Javascript in Selenium o semplicemente accedendo al simbolo nella console del browser), vuoi usare expose-loaderinvece.

In breve: ProvidePlugin gestisce le dipendenze in fase di compilazione ai simboli globali mentre expose-loadergestisce le dipendenze di runtime ai simboli globali.


2
Grazie per la spiegazione
Foton

Esempio di ProvidePlugin con webpack dai documenti ufficiali: webpack.js.org/plugins/provide-plugin/#usage-jquery
James Gentes

33

Sembra che l' windowoggetto sia esposto in tutti i moduli.

Perché non importare / richiedere JQuerye inserire:

window.$ = window.JQuery = JQuery;

Dovrai assicurarti che ciò avvenga prima di richiedere / importare qualsiasi modulo che ne fa uso window.JQuery, sia in un modulo che richiede o nel modulo in cui viene utilizzato.


Soluzione più semplice senza aggiungere una nuova dipendenza. Grazie!
fatihpense

Ciò non funzionerà quando altri moduli annidati utilizzano la variabile, semplicemente 'non definito'
aboutqx

4
Bene, funziona quando si utilizza requirementre nonimport
aboutqx

@aboutqx Non sono sicuro di cosa intendi. La mia risposta presupponeva che JQuery fosse già stato importato / richiesto e assegnato a una variabile denominata JQuery.
mhess

2
@mhess quando usi import, potresti ricevere un errore, perché imports vengono ordinati all'inizio del file e requirerimangono dove sono stati messi. Quindi l'ordine di esecuzione cambia solo con importquando la finestra variabile non è impostata.
qx

16

Questo ha sempre funzionato per me. incluso per webpack 3 window.$ = window.jQuery = require("jquery");


2
soluzione migliore ! 2018
waza123

6

Nessuno dei precedenti ha funzionato per me. (e davvero non mi piace la sintassi expose-loader). Anziché,

Ho aggiunto a webpack.config.js:

var webpack = require('webpack');
module.exports = {
   plugins: [
       new webpack.ProvidePlugin({
           $: 'jquery',
       })     
   ]
}

Quindi tutti i moduli hanno accesso tramite jQuery tramite $.

Puoi esporlo alla finestra aggiungendo quanto segue a uno qualsiasi dei tuoi moduli in bundle da webpack:

window.$ = window.jQuery = $

1
Questo ha funzionato per me utilizzando webpack-stream dietro le quinte
klewis

1

Aggiornamento per Webpack v2

Installa expose-loader come descritto da Matt Derrick:

npm install expose-loader --save-dev

Quindi inserisci il seguente snippet nel tuo webpack.config.js:

module.exports = {
    entry: {
        // ...
    },
    output: {
        // ...
    },
    module: {
        loaders: [
                { test: require.resolve("jquery"), loader: "expose-loader?$!expose-loader?jQuery" }
        ]
    }
};

(dai documenti di expose-loader )


Ora non riesco più a farlo funzionare in nessuna versione di Webpack. Non sono sicuro di cosa sia cambiato, ma l'unico modo in cui posso far riconoscere jQuery o $ è farlowindow.jQuery = require('jquery');
trpt4him

0

Nel mio caso funziona

{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" } 
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.