Exponha o jQuery a um objeto Window real com Webpack

111

Quero expor o objeto jQuery ao objeto de janela global que pode ser acessado dentro do console do desenvolvedor no navegador. Agora, na configuração do meu webpack, tenho as seguintes linhas:

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

Essas linhas adicionam as definições jQuery a cada arquivo em meus módulos do webpack. Mas quando eu construo o projeto e tento acessar o jQuery no console do desenvolvedor assim:

window.$;
window.jQuery;

diz que essas propriedades são indefinidas ...

Existe uma maneira de corrigir isso?

Ferbolg
fonte
1
Posso definir this: 'window'também? Como muitas bibliotecas assumem que a thisvariável é o objeto Window
Abhinav Singi

Respostas:

129

Você precisa usar o carregador de exposição .

npm install expose-loader --save-dev

Você pode fazer isso quando precisar:

require("expose?$!jquery");

ou você pode fazer isso em sua configuração:

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

ATUALIZAÇÃO : a partir do webpack 2, você precisa usar expose -loader em vez de expor :

module: {
    rules: [{
        test: require.resolve('jquery'),
        use: [{
            loader: 'expose-loader',
            options: '$'
        }]
    }]
}
Matt Derrick
fonte
11
O ProvidePlugindeve ser usado principalmente em situações em que bibliotecas de terceiros dependem da presença de uma variável global.
Johannes Ewald,
Fiz a suposição incorreta de que a questão estava usando o plugin de provisão para propósitos 'preguiçosos' que tenho visto muito online, mas você está correto :)
Matt Derrick
8
Isso é exatamente o que eu estava procurando e só para acrescentar mais, para carregadores, você pode fazer em uma linha também:{test: /jquery\.js$/, loader: 'expose?jQuery!expose?$'}
Fernando
8
Você não pode simplesmente adicionar um primeiro script que o faça $ = require('jquery'); window.jQuery = $; window.$ = $;? (não é necessário expose-loader)
herman
1
De acordo com a página de expor-loader GitHub a sintaxe Webpack 2 é a seguinte: module: { rules: [{ test: require.resolve('jquery'), use: [{ loader: 'expose-loader', options: 'jQuery' },{ loader: 'expose-loader', options: '$' }] }] }. Esta é a única maneira de expor o jQuery e está usando a nova sintaxe module.rules .
Gavin Sutherland
84

O ProvidePlugin substitui um símbolo em outra fonte por meio da respectiva importação, mas não expõe o símbolo no namespace global. Um exemplo clássico são os plug-ins jQuery. A maioria deles espera jQueryser definida globalmente. Com o, ProvidePluginvocê se certificaria de que o jQuery é uma dependência (por exemplo, carregado antes) e a ocorrência de jQueryem seu código seria substituída pelo equivalente bruto do webpack require('jquery').

Se você tiver scripts externos que dependem do símbolo para estar no namespace global (como digamos um JS hospedado externamente, chamadas de Javascript no Selenium ou simplesmente acessando o símbolo no console do navegador), você deseja usar o expose-loader.

Resumindo: o ProvidePlugin gerencia dependências de tempo de construção para símbolos globais, enquanto expose-loadergerencia dependências de tempo de execução para símbolos globais.

Joscha
fonte
2
Obrigado pela explicação
Foton
Exemplo de ProvidePlugin com webpack dos documentos oficiais: webpack.js.org/plugins/provide-plugin/#usage-jquery
James Gentes
33

Parece que o windowobjeto está exposto em todos os módulos.

Por que não apenas importar / exigir JQuerye colocar:

window.$ = window.JQuery = JQuery;

Você precisará garantir que isso aconteça antes de solicitar / importar qualquer módulo que faz uso window.JQuery, seja em um módulo de exigência ou no módulo onde está sendo usado.

senhora
fonte
Solução mais fácil sem adicionar uma nova dependência. Obrigado!
fatihpense de
Isso não funcionará enquanto outros módulos aninhados usando a variável, apenas 'não definidos'
qx
4
Bem, funciona quando requirenão é import
usado
@aboutqx Não tenho certeza do que você quer dizer. Minha resposta presumiu que JQuery já tinha sido importado / exigido e atribuído a uma variável chamada JQuery.
Sra.
2
@mhess quando você usa import, você pode obter erro, porque imports são classificados no início do arquivo e requirepermanecem onde foram colocados. Portanto, a ordem de execução só muda importquando a variável da janela não está definida.
qx
16

Isso sempre funcionou para mim. incluindo para webpack 3 window.$ = window.jQuery = require("jquery");

SharpCoder
fonte
2
melhor solução ! 2018
waza123
6

Nenhuma das opções acima funcionou para mim. (e eu realmente não gosto da sintaxe expose-loader). Em vez de,

Eu adicionei a webpack.config.js:

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

Todos os módulos têm acesso através do jQuery através de $.

Você pode expô-lo na janela adicionando o seguinte a qualquer um de seus módulos agrupados por webpack:

window.$ = window.jQuery = $
Antoine Vo
fonte
1
Isso funcionou para mim usando webpack-stream nos bastidores
Klewis
1

Atualização para Webpack v2

Instale o expose-loader conforme descrito por Matt Derrick:

npm install expose-loader --save-dev

Em seguida, insira o seguinte snippet em webpack.config.js:

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

(dos documentos expose-loader )

Cologne_Muc
fonte
Agora não consigo mais fazer isso funcionar em nenhuma versão do Webpack. Não tenho certeza do que mudou, mas a única maneira de fazer com que jQuery ou $ sejam reconhecidos é fazendowindow.jQuery = require('jquery');
trpt4him
0

No meu caso funciona

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