Electron: jQuery não está definido globalmente porque "módulo" está definido

Criado em 6 mai. 2014  ·  71Comentários  ·  Fonte: electron/electron

jQuery contém algo neste sentido:

if ( typeof module === "object" && typeof module.exports === "object" ) {
  // set jQuery in `module`
} else {
  // set jQuery in `window`
}

módulo é definido, mesmo nos scripts do lado do navegador. Isso faz com que o jQuery ignore o objeto window e use module , então os outros scripts não encontrarão $ nem jQuery no escopo global.

Não tenho certeza se este é um bug do jQuery ou do atom-shell, mas queria colocá-lo na web para que outros não pesquisassem por tanto tempo quanto eu.

Comentários muito úteis

Basta remover module .

Eu queria que minha página da web funcionasse no navegador e no elétron.
Conforme explicado neste tópico, o elétron expõe um module global quando nodeIntegration: true , que o jQuery então vê e reage de acordo:

if ( typeof module === "object" && typeof module.exports === "object" ) {
    // bind to module
} else {
    // bind to window
}

Consegui fazer com que o jQuery se vinculasse ao objeto window e usasse nodeIntegration: true fazendo o seguinte em meu arquivo html:

<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.highcharts.com/highcharts.js"></script>
<script>if (window.module) module = window.module;</script>

Espero que isso ajude alguém.

Todos 71 comentários

Este não é realmente um bug para nenhum dos sistemas, você tem o mesmo problema ao usar o browserify. jQuery vê que está sendo executado em um ambiente CommonJS e espera ser usado como tal.

A solução é relativamente simples, entretanto. Em vez de carregar o jQuery como uma tag de script, carregue-o por meio de require:

window.$ = window.jQuery = require('/path/to/jquery');

Eu concordo com @ChiperSoft , este é o comportamento esperado no ambiente CommonJS, então eu marquei isso como wontfix . E obrigado por compartilhar sua descoberta.

@ChiperSoft , Onde devo colocar o arquivo jquery.js para que require('jquery') funcione? Tentei colocá-lo no mesmo nível de package.js e main.js mas o tempo de execução não parece melhorá-lo.

Você pode usar require('jquery.js') note o .js no final, para carregar o jquery relativo ao seu arquivo HTML.

Desculpe, usei window.$ = window.jQuery = require('/path/to/jquery'); como mencionado, mas não funciona,
Uncaught Error: Cannot find module 'scripts/jquery-1.10.2.min.js' module.js:339

Eu uso isso o tempo todo e funciona muito bem! Aqui está o que eu uso, esteja atento ao caminho:

window.$ = window.jQuery = require('./scripts/jquery-2.1.1.min.js');

@frankhale oh, funcionou com ./ , obrigado!

Impressionante! A coisa do caminho também me fez tropeçar.

Se seu aplicativo não precisa de integração de nó, adicione "node-integration": false às opções do BrowserWindow. Neste caso module.exports não está disponível, o jQuery funciona como esperado.

@kabalage funcionou maravilhosamente, obrigado!

: +1:

Aproximou-se do mesmo problema. Instale o jQuery via NPM, em seguida, exigiu e funcionou.

e se a integração do nó e o jquery sem o requerer forem necessários ...

Estou tentando entender isso, pois parece ser algo que eu poderia usar. No entanto, eu me pergunto quando você pode ter certeza de que pode usar $ com segurança. O log de $ logo após essa linha resultará em require e não jquery, pois require é asynchronus?

janela. $ = window.jQuery = require ('/ path / to / jquery');
console.log ($) // logs 'requerem' e não 'jQuery'

@dieroux tente instalá-lo via npm:

npm install jquery

Isso funcionou para mim enquanto tentava o mesmo. Então você não precisa indicar um caminho, basta dizer:

window.$ = window.jQuery = require('jquery');
console.log( [$, jQuery ]);

E se precisarmos de integração de nó e não pudermos usar require ('something')?
Atualmente funciona fazendo "deletar módulo;" antes de carregar coisas problemáticas.
Qual é o impacto de fazer isso?

Estou tendo problemas semelhantes em que jquery pode ser carregado corretamente na primeira vez que preciso em um script de pré-carregamento em um webview. No entanto, na segunda vez que jquery é referenciado em uma página externa, a linha para atribuí-lo via:

  try {
        module.exports = null;
        if (typeof require === 'function') {
          alert('window: ' + window);
          alert('jquery: ' + window.jQuery);
          alert('export: ' + module.exports);
          if ( !window.jQuery ) {
            alert('before load');
            window.jQuery = require('./node_modules/jquery/dist/jquery.js');
            alert('after load');
            window.$ = window.jQuery;
            alert('after assignment');
         }
          alert('jquery: ' + window.jQuery);
        }
    } catch(e) {
        alert('failed load.');
        console.log(e);
    }

lança um createElement de não é possível ler de undefined no console na atribuição a window.jQuery de require, resultando em jQuery não sendo carregado.

A mensagem de erro no console é:
A página do convidado registrou uma mensagem: TypeError: Não é possível ler a propriedade 'createElement' da linha indefinida: 40

Alguma ideia adicional sobre como carregar o jquery com êxito nas páginas subsequentes?

Obrigado.

Essa foi a primeira coisa em que tropecei ao passar pelo guia de início rápido do elétron e tentar embrulhar um aplicativo local - algo que funciona no Chrome de repente não funciona na eleição. Ter o erro oculto em carregamentos de módulo angular com falha não ajuda, é claro, então presumi que havia um problema com a ordem de carregamento do script, que foi como encontrei este segmento. Talvez as palavras-chave ajudem outras pessoas.

A solução de @kabalage acima funcionou perfeitamente.

Olá a todos, só quero adicionar algumas informações sobre esse problema, se eu colar o código da biblioteca jquery no console $ eletrônico e o jQuery for adicionado como uma função no objeto janela. Eu poderia executar o jquery.

JQuery referenciado com tag de script, mesmo erro. Tem que "node-integration": false em BrowserWindow ()

Olá pessoal ... Não sei por que esse problema foi encerrado. Definitivamente, ainda há um problema aqui, deixe-me explicar. Se eu instalar o jQuery localmente via NPM e carregar um arquivo html local, use:

mainWindow. $ = require ('jQuery');
mainWindow.jQuery = require ('jQuery');

então ele funciona conforme o esperado. Se, no entanto, eu fizer mainWindow.loadUrl ('http://external.site.com ");

Recebo os erros mencionados em que $ e jQuery não estão definidos. Desativar a integração do nó realmente não é uma resposta aceitável; é a razão pela qual estou usando o Electron em primeiro lugar, eu preciso dele.

Eu gostaria de entrar na fonte e solucionar o problema sozinho, mas pensei em ver se alguém tinha alguma informação adicional sobre isso que me apontasse na direção certa antes de eu ir até lá. Alguém conseguiu fazer isso funcionar com integração de _with_ node em sites externos?

Obrigado ... e bom trabalho BTW. Tudo novo e lindo, assim, vai começar com algumas rugas.

Atenciosamente

/C

Eu fiz funcionar com integração de nós.

  1. Instale-o com npm, para que seja definido em package.json
  2. Use require com o nome do módulo <script>window.$ = window.jQuery = require('jquery');</script>
  3. Não use o caminho no parâmetro de requerimento.
  4. Não instale através do caramanchão, isso fará com que você use o caminho no parâmetro requerido.
  5. Se você usar o bootstrap, você precisa primeiro carregar o jQuery.

Todos os itens acima são suportados apenas por minha experiência.

Vai funcionar

    <script>window.$ = window.jQuery = require('jquery');</script>
    <script src="path_to/bootstrap.js"></script>

Não vou

    <script>window.$ = window.jQuery = require('./path/to/jquery.js');</script>
    // or
    <script src="path_to/jquery.js"></script>
    <script src="path_to/bootstrap.js"></script>

Oi dilmdeep, obrigado pela resposta rápida. A sua solução depende de ter controle sobre o site externo? Estou tentando carregar um site ao qual não tenho acesso à fonte. O que você disse sobre packages.json é interessante. Eu instalei o jQuery através do npm (e usei a reconstrução documentada para electron) e, como eu disse, posso usar o jQuery com um arquivo HTML local, mas o jQuery não está definido no meu package.json ..... Oh e eu testei com a desativação da integração de nós e enquanto isso funciona, não é o que eu preciso. Obrigado.

Eu só queria atualizar isso, caso outra pessoa tenha o mesmo problema. A maneira como resolvi isso (depois de baixar 10 GB do código-fonte do Electron) estava na documentação para começar. Em vez de chamar a url do site externo, carreguei um arquivo HTML local e usei um webview desse arquivo html para carregar o site externo. Ele carrega perfeitamente com a integração de nós ativada. Basta olhar os documentos para webview, é bastante simples. Também agradeço a Paul na sala de chat por me ajudar a começar com a fonte. Se alguém está se perguntando, eles usam Atom (é claro) para codificar Electron, WinDbg no Windows para depurar e Ninja para compilar. Para sua informação, a compilação dos fontes foi extremamente fácil e surpreendentemente rápida, ela compilou primeiro usando seus scripts e a documentação fornecida. Novamente, ótimo trabalho, pessoal!

@WolfieWerewolf Bravo! tenho que dizer que o exemplo é um pouco enganador se a segurança for considerada.

@ Shufeng01 Cheers, companheiro, estou chegando a esse frio da terra .Net e me sinto como um n00b completo. Você está certo que a segurança era um problema, no entanto, usar o sinalizador disablewebsecurity no webview resolveu a maior parte. Acho que a segurança, em geral, é o maior desafio para trazer a web para o desktop ... mas vale a pena o esforço. Rochas de elétrons.

@diimdeep obrigado, sua solução funciona para mim (não é o que @WolfieWerewolf quer!)

Isso é um pouco problemático para nós. Agrupamos jquery com nosso aplicativo js, ​​e este JS concatenado é então usado na construção para as versões web e desktop (temos usado o NWJS). A instalação do NPM pode ser uma opção para nós, mas não é a ideal em nossa situação por alguns motivos.

Não existe uma maneira teórica de fazê-lo funcionar usando tags de script?

@bgSosh , por que não desabilitar a integração de nós (leia sobre a chave node-integration aqui )? Se você fizer isso, as tags de script devem funcionar corretamente. Se você precisar de alguma coisa relacionada ao nó, poderá fazer isso em um script preload (eles sempre têm integração de nó).

@etiktin você pode explicar como fazer isso no pré-carregamento? sou novo no electron e não consegui executar um script de pré-carregamento (pelo menos parece não executar, o console.log não está funcionando, alterando a janela. myExposedIPC = require ('ipc') por exemplo, não está disponível mais tarde etc.

Eu coloquei para funcionar caso alguém tenha o mesmo problema: https://github.com/atom/electron/issues/1753#issuecomment -157409572

@matthiasg que bom que você fez funcionar. Eu adicionei alguns comentários ao seu exemplo.

Quando a integração do nó está desativada e você deseja fazer algumas coisas do nó em seu script de pré-carregamento, é importante manter uma referência para qualquer nó global de que você precisa. Você precisa fazer isso, porque no próximo tick as referências globais são excluídas (é assim que a desativação da integração do nó é implementada), então, se você não reteve uma referência e então tenta requerer algo em uma chamada de função ou um cronômetro , iria falhar.

@etiktin obrigado. Claro que fazia parte, mas o que estava faltando é a documentação de process.once('loaded', ... ) uma vez que estava no lugar, eu posso realmente expor a apis que eu queria.

Oi pessoal,

Como nenhuma das opções acima funcionou para mim (usando w2ui e JQuery com electron e página HTML independente, deixe também w2ui usar jQuery), senti a necessidade de postar minha solução de trabalho aqui:

<html>
<head>
    <title>MyApp</title>
    <link rel="stylesheet" type="text/css" href="./lib/w2ui-1.4.3.css"/>
    <script type="text/javascript" src="./lib/require.js"></script>
    <script type="text/javascript" src="./lib/jquery-2.1.4.js" onload="$ = jQuery = module.exports;"></script>
    <script type="text/javascript" src="./lib/w2ui-1.4.3.js"></script>
</head>
<body>
<script type="text/javascript">
    // use global $ and w2ui here... 
    ...

Sou um novato em JS e estou realizando um estudo de tecnologia e agora um pouco preocupado com esse tipo de carregamento de módulo obscuro. Pode ser uma pergunta boba, mas por que o elétron carrega módulos JS de maneira tão diferente dos navegadores normais ao carregar uma página HTML?

@forman você desativou a integração do nó e usou um script de pré-carregamento para interação do nó? Veja os comentários acima meus e de @matthiasg. Se você fizer isso, jquery e o resto funcionarão exatamente como no navegador.

Vai funcionar

requirejs(['require', '../require.config'], function (requirejs, config) {
        //fixed jQuery isn't set globally
        requirejs(['jquery'],function(jquery){
            window.$ = window.jQuery =jquery;
        });
        // update global require config
        window.requirejs.config(config);
        // load app
        requirejs(['main'],function(main){
        });
    });

@forman Obrigado !! Nenhuma das opções acima funcionou, exceto a sua solução. (usando 0,35,5 elétron pré-construído)
@etiktin Isso funcionou para mim sem ter que mudar nada no lado do mainProcess

Achei que deveria adicionar nosso problema e solução a este tópico para referência futura.

Estamos carregando uma url externa em um webview e precisamos executar nosso próprio Javascript que pode usar electron / Node. Habilitar o nodeintegration no webview não é uma opção, pois isso quebrará o jQuery que está sendo usado pelo url externo.

O que acabamos fazendo foi adicionar um script de pré-carregamento ao webview onde colocamos os módulos de que precisamos no escopo global. Isso os torna acessíveis mais tarde, quando executamos nosso Javascript.

preload.js:

global.ipcRenderer = require('electron').ipcRenderer;

E então podemos acessar o ipcRenderer como:

webview.executeJavaScript("ipcRenderer.sendToHost('hello');");

Uncaught Error: Cannot find module 'jquery' e nada ajuda neste tópico = /

Basta remover module .

Eu queria que minha página da web funcionasse no navegador e no elétron.
Conforme explicado neste tópico, o elétron expõe um module global quando nodeIntegration: true , que o jQuery então vê e reage de acordo:

if ( typeof module === "object" && typeof module.exports === "object" ) {
    // bind to module
} else {
    // bind to window
}

Consegui fazer com que o jQuery se vinculasse ao objeto window e usasse nodeIntegration: true fazendo o seguinte em meu arquivo html:

<script>if (typeof module === 'object') {window.module = module; module = undefined;}</script>
<script src="//code.jquery.com/jquery-1.12.0.min.js"></script>
<script src="//code.highcharts.com/highcharts.js"></script>
<script>if (window.module) module = window.module;</script>

Espero que isso ajude alguém.

@tomkel aqui está outra solução:

<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script>window.jQuery = window.$ = module.exports;</script>

No meu caso, preciso ser capaz de iniciar meu aplicativo como um site e um aplicativo Electron. Aqui está minha solução:

<!-- Launched with Electron -->
<script>
    if ('require' in window) {
        window.$ = window.jQuery = require('jquery');
    }
</script>

<!-- From CDN, Bower, etc... -->
<script src="https://code.jquery.com/jquery-2.2.0.js"></script>

<!-- Others libraries depending on jQuery -->
<script src="..."></script>

@dkfiresky Sim, parece funcionar também. No entanto, estou usando Highcharts em conjunto com jQuery. Highcharts faz uma coisa semelhante, colocando-se em module se existir. Por alguma razão, eu não consegui

<script>window.Highcharts = module.exports;</script>

trabalhar. Eu atualizei meu comentário anterior para refletir isso.

@tomkel sua solução com ocultação temporal de module funciona muito bem para mim. Meu problema foi durante a migração do nw.js com o ngDialog assumindo que ele estava no ambiente CommonJS falhando em require('angular') e em se registrar como módulo angular.

No Electron 0.36.7, descubro que não posso fazer um window.$ = require('jquery'); simples, pois não conseguiria encontrar o módulo. O renderizador não parece ter o mesmo caminho de resolução de módulo que o processo principal

Na verdade, isso não funciona porque o jQuery estaria rodando no processo principal que não tem document . E require('jquery') não funcionou para mim porque estou servindo a página por meio de HTTP como # 4243. Para corrigir isso, tentei adicionar caminhos de módulo do processo principal ao processo de renderização:

require('electron').remote.process.mainModule.paths.forEach(function(path) {
    require('module').globalPaths.push(path);
});

Depois disso, posso fazer require('jquery') sem problemas. Não tenho certeza de que outro impacto isso pode ter, no entanto

E require ('jquery') não funcionou para mim porque estou servindo a página por meio de HTTP como # 4243.

Se você estiver permitindo que o conteúdo remoto acesse node.js, seu aplicativo é muito inseguro, você precisa desativar a integração do nó ao executar o conteúdo remoto e usar um script de pré-carregamento

Mesmo que o "conteúdo remoto" seja localhost? Estou usando o node para construir e me servir a página em vez de ler um arquivo local, isso é tudo

Expandindo em @dkfiresky , você pode obter um Uncaught ReferenceError: module is not defined na versão do navegador.

Se sim, tente isto:

<script src="./bower_components/jquery/dist/jquery.min.js"></script>
<script>window.jQuery = window.$ = typeof module === 'object' ? module.exports : jQuery</script> 

@dspint module será indefinido apenas no caso de a integração do nó ser desabilitada, então você provavelmente deve usar meu exemplo apenas com a integração do nó habilitada.

Se você estiver usando window.open , pode passar nodeIntegration=0 com as opções da janela.

window.open('https://your.cool/url', 'title', 'nodeIntegration=0');

Estou fazendo:

<script>
  var saveModule = module;
  delete module;
</script>
  <script src="jquery.js"></script>
  <script src="jquery-ui.js"></script>
<script>
  module = saveModule;
</script>

Eu tive o mesmo problema que @gnail. Eu tinha um servidor de nó executando um projeto angular. Seu código consertou para mim.

require('electron').remote.process.mainModule.paths.forEach(function(path) {
  require('module').globalPaths.push(path);
});

Está funcionando para mim 😄

<script>
    window['old_module'] = window['module'];
    delete window.module;
</script>

<script src="any_lib_like_jquery.js" />

<script>
    window['module'] = window['old_module'];
    delete window.old_module;
</script>

Estou tendo esse problema, já tentei todo esse tópico. mas nada funciona, estou preso no começo
de tudo.
estou usando o representante de iniciação de elétrons

@PauloGaldo basicamente qualquer solução neste tópico deve estar funcionando. Publique o trecho relevante do seu código e todas as mensagens de erro que encontrar.

@ChiperSoft Você pode me dizer onde devo usar seu código?

@tomkel Muito bom!
Eu finalmente consegui que a Maçonaria trabalhasse dentro do Electron!

Por algum motivo, ainda não consigo fazer o jQuery funcionar no navegador e no aplicativo Electron.
Meu aplicativo da web funciona bem no navegador, ao passo que quando tento carregar o mesmo url por meio do aplicativo de elétrons, ele lança -

image

Webapp - https://github.com/zulip/zulip
Aplicativo Electron - https://github.com/zulip/zulip-electron

O webapp está usando a versão jquery 1.12.1 via npm.
Não posso usar o nodeintegration off porque preciso dele no meu processo de renderização.
Estou tendo dificuldade em resolver isso. Alguém sabe como fazer funcionar?
cc @aaaaahaaaaa @maykefreitas @paulcbetts @tomkel @dkfiresky

@englishextra sem sorte. Tentei incluir seu código no preload.js do meu aplicativo, mas obtive o mesmo erro.

@englishextra Não, não preciso do jquery no meu aplicativo. Veja o código de atualização aqui . Não posso incluir seu código na lógica do meu aplicativo, pois estou usando-o apenas para carregar o url especificado, veja isso .

Eu resolvi esse problema com isso

<script type="text/javascript" src="js/jquery.min.js" onload="window.$ = window.jQuery;"></script>

E definir

webPreferences: {
            nodeIntegration: false, 
        }

se você com nodeIntegration: true, imorot jQuery assim

<script type="text/javascript" src="js/jquery.min.js" onload="window.$ = window.jQuery = module.exports;"></script>

referência a
https://github.com/electron/electron/issues/345

Quer dizer, parece ser um problema grave, então por que não incluí-lo no Electron real? Talvez integrar as principais bibliotecas JavaScript no Electron?

Provavelmente, se você estiver usando jQuery em um aplicativo Electron, está fazendo algo muito errado ou pelo menos ineficiente.

<script src="https://code.jquery.com/jquery-2.2.0.min.js"></script>
<script>if (typeof module === 'object') {window.jQuery = window.$ = module.exports;};</script>

@drowlands Incluir libs de 3 partes no Electron parece uma má ideia. Imagine a rotina de atualização, por exemplo, ou a escolha de uma versão.
@amhoho Isso porque você precisa require jQuery ou modificar seu código init na função superior - deixando apenas factory( global );

Aqui:

( function( global, factory ) {

    "use strict";

    if ( typeof module === "object" && typeof module.exports === "object" ) {

        // For CommonJS and CommonJS-like environments where a proper `window`
        // is present, execute the factory and get jQuery.
        // For environments that do not have a `window` with a `document`
        // (such as Node.js), expose a factory as module.exports.
        // This accentuates the need for the creation of a real `window`.
        // e.g. var jQuery = require("jquery")(window);
        // See ticket #14549 for more info.
        module.exports = global.document ?
            factory( global, true ) :
            function( w ) {
                if ( !w.document ) {
                    throw new Error( "jQuery requires a window with a document" );
                }
                return factory( w );
            };
    } else {
        factory( global );
    }

No meu caso, carrego libs via fetch / Promise ou xhr, então tenho essa rotina para remover verificações de módulo nas libs dos fornecedores.
@RRorg estranho o que você está dizendo

marca

@kabalage Acho que a configuração do seu post acima está desatualizada. Parece que deveria ser assim agora:

const window = new BrowserWindow({
  webPreferences: {
    nodeIntegration: false, 
  },
});

Nos documentos oficiais:
https://electronjs.org/docs/faq#i -can-not-use-jqueryrequirejsmeteorangularjs-in-electron
`` `