Exponer jQuery a un objeto de ventana real con Webpack

111

Quiero exponer el objeto jQuery al objeto de ventana global al que se puede acceder dentro de la consola del desarrollador en el navegador. Ahora en mi configuración de paquete web tengo las siguientes líneas:

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

Estas líneas agregan las definiciones de jQuery a cada archivo en mis módulos de paquete web. Pero cuando construyo el proyecto e intento acceder a jQuery en la consola de desarrollador de esta manera:

window.$;
window.jQuery;

dice que estas propiedades no están definidas ...

¿Hay alguna forma de solucionar este problema?

Ferbolg
fuente
1
¿Puedo configurar yo this: 'window'también? Dado que muchas bibliotecas asumen que la thisvariable es el objeto Window
Abhinav Singi

Respuestas:

129

Necesita utilizar el cargador de exposición .

npm install expose-loader --save-dev

Puede hacer esto cuando lo necesite:

require("expose?$!jquery");

o puede hacer esto en su configuración:

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

ACTUALIZACIÓN : A partir de webpack 2, debe usar expose-loader en lugar de exponer :

module: {
    rules: [{
        test: require.resolve('jquery'),
        use: [{
            loader: 'expose-loader',
            options: '$'
        }]
    }]
}
Matt Derrick
fuente
11
Se ProvidePlugindebe utilizar principalmente en situaciones en las que las bibliotecas de terceros dependen de la presencia de una variable global.
Johannes Ewald
Hice la suposición incorrecta de que la pregunta estaba usando el complemento de proporcionar para fines 'perezosos' que he visto mucho en línea, pero tiene razón :)
Matt Derrick
8
Esto es exactamente lo que estaba buscando y solo para agregar más, para los cargadores, también pueden hacerlo en una línea:{test: /jquery\.js$/, loader: 'expose?jQuery!expose?$'}
Fernando
8
¿No puede simplemente agregar un primer script que lo haga $ = require('jquery'); window.jQuery = $; window.$ = $;? (no necesita expose-loader)
herman
1
De acuerdo con la página exponer-loader GitHub la sintaxis webpack 2 es como sigue: module: { rules: [{ test: require.resolve('jquery'), use: [{ loader: 'expose-loader', options: 'jQuery' },{ loader: 'expose-loader', options: '$' }] }] }. Esta es la única forma en que podría exponer jQuery y está usando la nueva sintaxis de module.rules .
Gavin Sutherland
84

ProvidePlugin reemplaza un símbolo en otra fuente a través de la importación respectiva, pero no expone el símbolo en el espacio de nombres global. Un ejemplo clásico son los complementos de jQuery. La mayoría de ellos solo esperan jQueryser definidos globalmente. Con el ProvidePlugin, se aseguraría de que jQuery sea una dependencia (por ejemplo, cargada antes) y la aparición de jQueryen su código se reemplazará con el equivalente en bruto del paquete web require('jquery').

Si tiene scripts externos que dependen de que el símbolo esté en el espacio de nombres global (como, digamos, un JS alojado externamente, llamadas de Javascript en Selenium o simplemente accediendo al símbolo en la consola del navegador), desea usar el expose-loader.

En resumen: ProvidePlugin gestiona las dependencias de tiempo de compilación de los símbolos globales, mientras que expose-loadergestiona las dependencias de tiempo de ejecución de los símbolos globales.

Joscha
fuente
2
Gracias por la explicación
Foton
Ejemplo de ProvidePlugin con paquete web de documentos oficiales: webpack.js.org/plugins/provide-plugin/#usage-jquery
James Gentes
33

Parece que el windowobjeto está expuesto en todos los módulos.

¿Por qué no solo importar / requerir JQueryy poner:

window.$ = window.JQuery = JQuery;

Deberá asegurarse de que esto suceda antes de requerir / importar cualquier módulo que haga uso window.JQuery, ya sea en un módulo requerido o en el módulo donde se está utilizando.

mhess
fuente
La solución más sencilla sin agregar una nueva dependencia. ¡Gracias!
fatihpense
Eso no funcionará mientras otros módulos anidados usan la variable, simplemente 'no definida'
aboutqx
4
Bueno, funciona cuando se usa requiremientras noimport
aboutqx
@aboutqx No estoy seguro de lo que quieres decir. Mi respuesta asumió que JQuery ya había sido importado / requerido y asignado a una variable nombrada JQuery.
mhess
2
@mhess cuando usa import, puede obtener un error, porque los imports se ordenan al principio del archivo y los requires permanecen donde se colocaron. Por lo tanto, el orden de ejecución solo cambia importcuando la variable de ventana no está configurada.
aboutqx
16

Esto siempre funcionó para mí. incluido para webpack 3 window.$ = window.jQuery = require("jquery");

SharpCoder
fuente
2
mejor solución ! 2018
waza123
6

Ninguno de los anteriores funcionó para mí. (y realmente no me gusta la sintaxis del cargador de exposición). En lugar,

Agregué a webpack.config.js:

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

Que todos los módulos tengan acceso a través de jQuery a través de $.

Puede exponerlo a la ventana agregando lo siguiente a cualquiera de sus módulos incluidos en el paquete web:

window.$ = window.jQuery = $
Antoine Vo
fuente
1
Esto funcionó para mí usando webpack-stream detrás de escena
klewis
1

Actualización para Webpack v2

Instale expose-loader como lo describe Matt Derrick:

npm install expose-loader --save-dev

Luego inserte el siguiente fragmento en su webpack.config.js:

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

(de los documentos de expose-loader )

Cologne_Muc
fuente
Ahora ya no puedo hacer que esto funcione en ninguna versión de Webpack. No estoy seguro de lo que ha cambiado, pero la única forma en que puedo hacer que jQuery o $ sean reconocidos es hacerlowindow.jQuery = require('jquery');
trpt4him
0

En mi caso funciona

{ test: require.resolve("jquery"), loader: "expose?$!expose?jQuery" } 
FeDev
fuente