Electron: jQuery n'est pas défini globalement car "module" est défini

Créé le 6 mai 2014  ·  71Commentaires  ·  Source: electron/electron

jQuery contient quelque chose dans ce sens :

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

module est défini, même dans les scripts côté navigateur. Cela oblige jQuery à ignorer l'objet window et à utiliser module , de sorte que les autres scripts ne trouveront pas $ ni jQuery dans la portée globale.

Je ne sais pas s'il s'agit d'un bogue jQuery ou atom-shell, mais je voulais le mettre sur le Web, afin que les autres ne recherchent pas aussi longtemps que moi.

Commentaire le plus utile

Désactivez simplement module .

Je voulais que ma page Web fonctionne à la fois dans le navigateur et dans l'électron.
Comme expliqué dans ce fil, electron expose un module global lorsque nodeIntegration: true , que jQuery voit et réagit en conséquence :

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

J'ai pu faire en sorte que jQuery se lie à l'objet window et utilise nodeIntegration: true en procédant comme suit dans mon fichier 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>

J'espère que cela aide quelqu'un.

Tous les 71 commentaires

Ce n'est pas vraiment un bogue pour l'un ou l'autre système, vous avez le même problème lorsque vous utilisez browserify. jQuery voit qu'il s'exécute dans un environnement CommonJS et s'attend à être utilisé comme tel.

La solution est pourtant relativement simple. Au lieu de charger jQuery en tant que balise de script, chargez-le via require :

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

Je suis d'accord avec @ChiperSoft , c'est un comportement attendu dans l'environnement CommonJS, j'ai donc marqué cela comme wontfix . Et merci d'avoir partagé ta trouvaille.

@ChiperSoft , où dois-je mettre le fichier jquery.js pour que require('jquery') fonctionne ? J'ai essayé de le mettre au même niveau que package.js et main.js mais le runtime ne semble pas le capter.

Vous pouvez utiliser require('jquery.js') notez le .js à la fin, pour charger jquery par rapport à votre fichier HTML.

Désolé, j'ai utilisé window.$ = window.jQuery = require('/path/to/jquery'); comme mentionné mais cela ne fonctionne pas,
Uncaught Error: Cannot find module 'scripts/jquery-1.10.2.min.js' module.js:339

Je l'utilise tout le temps et ça marche très bien ! Voici ce que j'utilise, attention au chemin :

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

@frankhale oh, ça a marché avec ./ , merci !

Impressionnant! La chose du chemin m'a aussi fait trébucher.

Si votre application n'a pas besoin d'intégration de nœud, ajoutez "node-integration": false à vos options BrowserWindow. Dans ce cas, module.exports n'est pas disponible, jQuery fonctionne comme prévu.

@kabalage a fonctionné à merveille, merci !

:+1:

J'ai abordé le même problème. Installez jQuery via NPM puis l'a requis et cela a fonctionné.

que se passe-t-il si l'entieration de nœuds et jquery sans l'exigence sont nécessaires ...

J'essaie de comprendre cela car cela semble être quelque chose que je pourrais utiliser. Cependant, je me demande quand pouvez-vous être sûr de pouvoir utiliser $ en toute sécurité. La journalisation de $ juste après cette ligne résultera en require et non en jquery puisque require est asynchrone?

window.$ = window.jQuery = require('/chemin/vers/jquery');
console.log($) // les journaux 'require' pas 'jQuery'

@dieroux essaie de l'installer via npm :

npm install jquery

Cela a fonctionné pour moi tout en essayant la même chose. Ensuite, vous n'avez pas besoin de donner un chemin, vous dites simplement :

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

Que se passe-t-il si nous avons besoin d'une intégration de nœuds et que nous ne pouvons pas utiliser require('quelque chose') ?
Actuellement, cela fonctionne en faisant « supprimer le module ; » avant de charger des éléments problématiques.
Quel est l'impact de faire cela ?

J'ai des problèmes similaires où jquery peut être chargé correctement la première fois que j'en ai besoin dans un script de préchargement sur une vue Web. Cependant la deuxième fois que jquery est référencé depuis une page externe, la ligne pour l'affecter 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);
    }

lève une propriété Cannot read createElement d'undefined dans la console lors de l'affectation à window.jQuery à partir de require, ce qui fait que jQuery n'est pas chargé.

Le message d'erreur sur la console est :
La page d'invité a enregistré un message : TypeError : Impossible de lire la propriété 'createElement' de la ligne non définie : 40

Avez-vous des idées supplémentaires sur la façon de charger avec succès jquery sur les pages suivantes ?

Merci.

C'est la première chose sur laquelle j'ai trébuché en parcourant le démarrage rapide d'électrons et j'ai essayé d'encapsuler une application locale - quelque chose qui fonctionne dans Chrome n'est soudainement pas en élection. Bien sûr, avoir l'erreur enterrée dans les chargements de modules angulaires échoués n'aide pas, alors j'ai supposé qu'il y avait un problème avec l'ordre de chargement des scripts, c'est ainsi que j'ai trouvé ce fil. Peut-être que les mots-clés aideront les autres.

La solution de @kabalage ci-dessus a parfaitement fonctionné.

Bonjour à tous, je veux juste ajouter des informations sur ce problème, si je colle le code de la bibliothèque jquery dans la console électronique $ et que jQuery est ajouté en tant que fonction dans l'objet window. Je pourrais exécuter jquery.

JQuery référencé avec balise script, même erreur. Avoir à "node-integration": false dans BrowserWindow()

Salut les gars... Je ne sais pas pourquoi ce problème est fermé, il y a certainement toujours un problème ici, laissez-moi vous expliquer. Si j'installe jQuery localement via NPM et charge un fichier html local, puis en utilisant :

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

alors cela fonctionne comme prévu. Si, cependant, je fais mainWindow.loadUrl('http://external.site.com");

J'obtiens les erreurs mentionnées où $ et jQuery ne sont pas définis. La désactivation de l'intégration des nœuds n'est vraiment pas une réponse acceptable ; c'est la raison pour laquelle j'utilise Electron en premier lieu, j'en ai besoin.

Je serais ravi d'entrer dans la source et de résoudre ce problème moi-même, mais j'ai pensé que je verrais si quelqu'un avait des informations supplémentaires à ce sujet pour m'orienter dans la bonne direction avant d'aller là-bas. Quelqu'un a-t-il réussi à faire fonctionner cela avec l'intégration de nœuds, contre des sites externes ?

Merci... et excellent travail BTW. Tout ce qui est nouveau et beau, comme celui-ci, va commencer par quelques rides.

Sincères amitiés

/W

Je l'ai fait fonctionner avec l'intégration de nœuds.

  1. Installez-le avec npm, il est donc défini dans package.json
  2. Utilisez require avec le nom du module <script>window.$ = window.jQuery = require('jquery');</script>
  3. N'utilisez pas le chemin dans le paramètre require.
  4. N'installez pas trough bower, cela vous obligera à utiliser path dans le paramètre require.
  5. Si vous utilisez bootstrap, vous devez d'abord charger jQuery.

Tout ce qui précède n'est soutenu que par mon expérience.

Marchera

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

Ne fera pas

    <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>

Salut dilmdeep, merci pour la réponse rapide. Votre solution dépend-elle du contrôle du site externe ? J'essaie de charger un site auquel je n'ai pas accès aux sources. Ce que vous avez dit à propos de packages.json est intéressant cependant. J'ai installé jQuery via npm (et j'ai utilisé la reconstruction documentée pour electron) et, comme je l'ai dit, je peux utiliser jQuery avec un fichier HTML local, mais jQuery n'est pas défini dans mon package.json..... Oh et j'ai testé avec la désactivation de l'intégration des nœuds et bien que cela fonctionne, ce n'est pas ce dont j'ai besoin. Merci.

Je voulais juste mettre à jour ceci au cas où quelqu'un d'autre aurait le même problème. La façon dont j'ai travaillé autour de cela (après avoir téléchargé 10 Go de source Electron) était en fait dans la documentation pour commencer. Au lieu d'appeler l'URL du site externe, j'ai chargé un fichier HTML local et utilisé une vue Web à partir de ce fichier html pour charger le site externe. Il se charge parfaitement avec l'intégration de nœuds activée. Il suffit de regarder dans la documentation pour la vue Web, c'est assez simple. Mes remerciements également à Paul dans la salle de discussion pour m'avoir aidé à démarrer avec la source. Si quelqu'un se demande, il utilise Atom (bien sûr) pour coder Electron, WinDbg sur Windows pour déboguer et Ninja pour compiler. Pour info, la compilation des sources était extrêmement simple et étonnamment rapide, elle a été compilée d'abord en utilisant leurs scripts et la documentation fournie. Encore une fois, excellent travail les gars!

@WolfieWerewolf Bravo ! Je dois dire que l'exemple est un peu trompeur si l'on considère la sécurité.

@ Shufeng01 Salut mon pote, j'arrive à ce froid de la terre .Net, je me sens donc comme un n00b complet. Vous avez raison, la sécurité était un problème, mais l'utilisation de l'indicateur disablewebsecurity sur la vue Web elle-même en a résolu la plupart. Je pense que la sécurité, en général, est le plus grand défi pour amener le Web sur le bureau... mais cela en vaut la peine. Roches électroniques.

@diimdeep merci, votre solution fonctionne pour moi (pas ce que veut

C'est un peu un problème pour nous. Nous combinons jquery avec notre application js, et ce JS concaténé est ensuite utilisé dans la construction pour les versions Web et de bureau (nous utilisons NWJS). L'installation de NPM peut être une option pour nous, mais ce n'est pas idéal dans notre situation pour plusieurs raisons.

N'y a-t-il aucun moyen théorique de le faire fonctionner en utilisant des balises de script ?

@bgSosh , pourquoi ne pas désactiver l'intégration des nœuds (lisez à propos de la clé node-integration ici ) ? Si vous faites cela, les balises de script devraient fonctionner correctement. Si vous avez besoin de choses liées aux nœuds, vous pouvez le faire dans un script preload (ils ont toujours une intégration de nœuds).

@etiktin pouvez-vous s'il vous plaît expliquer comment faire cela en préchargement ? Je suis nouveau sur electron et je n'ai pas réussi à exécuter un script de préchargement (au moins, il semble ne pas s'exécuter, console.log ne fonctionne pas, changeant window.myExposedIPC = require('ipc') par exemple n'est pas disponible plus tard, etc.

je l'ai fait fonctionner au cas où quelqu'un aurait le même problème: https://github.com/atom/electron/issues/1753#issuecomment -157409572

@matthiasg content que ça marche. J'ai ajouté quelques commentaires à votre exemple.

Lorsque l'intégration des nœuds est désactivée et que vous souhaitez effectuer des tâches sur les nœuds dans votre script de préchargement, il est important de conserver une référence au nœud global dont vous avez besoin. Vous devez le faire, car à la prochaine coche, les références globales sont supprimées (c'est ainsi que la désactivation de l'intégration de nœuds est implémentée), donc si vous ne détenez pas de référence et que vous essayez ensuite d'exiger quelque chose sur un appel de fonction ou une minuterie , cela échouerait.

@etiktin merci. Bien sûr, cela en faisait partie, mais ce qui me manquait, c'est la documentation pour process.once('loaded', ... ) une fois qu'elle était en place, je peux réellement exposer l'API que je voulais.

Salut les gars,

Étant donné qu'aucun de ce qui précède n'a fonctionné pour moi (en utilisant w2ui et JQuery à la fois avec une page HTML électronique et indépendante, w2ui utilise également jQuery), j'ai ressenti le besoin de publier ma solution de travail ici :

<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... 
    ...

Je suis un débutant en JS et j'effectue une étude technologique et maintenant un peu inquiet à propos de ce chargement de module obscur. C'est peut-être une question idiote, mais pourquoi l'électron charge-t-il les modules JS si différemment des navigateurs habituels lors du chargement d'une page HTML ?

@forman avez-vous désactivé l'intégration des nœuds et utilisé un script de préchargement pour l'interaction des nœuds ? Voir les commentaires ci-dessus par moi et @matthiasg. Si vous faites cela, jquery et le reste fonctionneront exactement comme dans le navigateur.

Marchera

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 Merci !! Aucune des solutions ci-dessus n'a fonctionné, à l'exception de votre solution. (en utilisant 0.35.5 pré-construit par électrons)
@etiktin Cela a fonctionné pour moi sans avoir à changer quoi que ce soit du côté principalProcess

J'ai pensé que je devrais ajouter notre problème et notre solution à ce fil pour référence future.

Nous chargeons une URL externe dans une vue Web et devons exécuter notre propre Javascript qui peut utiliser electron/Node. L'activation de l'intégration de nœuds sur la vue Web n'est pas une option car cela casserait jQuery qui est utilisé par l'URL externe.

Ce que nous avons fini par faire, c'est d'ajouter un script de préchargement à la vue Web où nous avons placé les modules dont nous avons besoin dans la portée globale. Cela les rend accessibles plus tard lorsque nous exécutons notre Javascript.

preload.js :

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

Et puis nous pouvons accéder à l'ipcRenderer comme :

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

Uncaught Error: Cannot find module 'jquery' et rien n'aide de ce fil =/

Désactivez simplement module .

Je voulais que ma page Web fonctionne à la fois dans le navigateur et dans l'électron.
Comme expliqué dans ce fil, electron expose un module global lorsque nodeIntegration: true , que jQuery voit et réagit en conséquence :

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

J'ai pu faire en sorte que jQuery se lie à l'objet window et utilise nodeIntegration: true en procédant comme suit dans mon fichier 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>

J'espère que cela aide quelqu'un.

@tomkel voici une autre solution :

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

Dans mon cas, je dois être capable à la fois de lancer mon application en tant que site Web et une application Electron. Voici ma solution :

<!-- 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 Oui, cela semble également fonctionner. Cependant, j'utilise Highcharts en conjonction avec jQuery. Highcharts fait la même chose, se plaçant sur module s'il existe. Pour une raison quelconque, je n'ai pas pu obtenir

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

travailler. J'ai mis à jour mon commentaire précédent pour refléter cela.

@tomkel, votre solution avec la dissimulation temporelle de module fonctionne très bien pour moi. Mon problème était lors de la migration de nw.js avec ngDialog en supposant qu'il se trouve dans l'environnement CommonJS et qu'il ne parvient pas à require('angular') et à s'enregistrer en tant que module angulaire.

Dans Electron 0.36.7, je constate que je ne peux pas faire un simple window.$ = require('jquery'); car cela ne parviendrait pas à trouver le module. Le moteur de rendu ne semble pas avoir le même chemin de résolution de module que le processus principal

En fait, cela ne fonctionne pas car jQuery s'exécuterait dans le processus principal qui n'a pas document . Et require('jquery') n'a pas fonctionné pour moi parce que je sers la page via HTTP comme #4243. Pour résoudre ce problème, j'ai essayé d'ajouter des chemins de module du processus principal au processus de rendu en :

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

Après cela, je peux faire require('jquery') sans aucun problème. Je ne sais pas quel autre impact cela peut avoir cependant

Et require('jquery') n'a pas fonctionné pour moi car je sers la page via HTTP comme #4243.

Si vous autorisez le contenu distant à accéder à node.js, votre application est très peu sécurisée, vous devez désactiver l'intégration de nœud lors de l'exécution de contenu distant et utiliser un script de préchargement

Même si le "contenu distant" est localhost ? J'utilise node pour créer et me servir la page au lieu de lire à partir d'un fichier local, c'est tout

En développant @dkfiresky , vous pourriez obtenir un Uncaught ReferenceError: module is not defined dans la version du navigateur.

Si c'est le cas, essayez ceci :

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

@dspint module ne sera indéfini que si l'intégration de nœud est désactivée, vous devriez donc probablement utiliser mon exemple uniquement avec l'intégration de nœud activée.

Si vous utilisez window.open , vous pouvez passer nodeIntegration=0 avec vos options de fenêtre.

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

Je fais:

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

J'ai eu le même problème que @gnail. J'avais un serveur de nœuds exécutant un projet angulaire. Son code l'a corrigé pour moi.

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

ça marche pour moi

<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>

J'ai ce problème, j'ai déjà essayé tout ce fil. mais rien ne fonctionne, je suis bloqué au début
de tout.
j'utilise le représentant du démarreur électronique

@PauloGaldo fondamentalement, toute solution de ce fil devrait fonctionner. Veuillez publier l'extrait pertinent de votre code et tous les messages d'erreur que vous rencontrez.

@ChiperSoft Pouvez-vous me dire où dois-je utiliser votre code ?

@tomkel Très sympa !
J'ai enfin réussi à faire travailler la maçonnerie au sein d'Electron !

Pour une raison quelconque, je ne parviens toujours pas à faire fonctionner jQuery à la fois dans le navigateur et dans l'application Electron.
Mon application Web fonctionne bien dans le navigateur alors que lorsque j'essaie de charger la même URL via l'application électronique, elle lance -

image

Application Web - https://github.com/zulip/zulip
Application Electron - https://github.com/zulip/zulip-electron

L'application Web utilise la version jquery 1.12.1 via npm.
Je ne peux pas désactiver nodeintegration car j'en ai besoin dans mon processus de rendu.
J'ai du mal à résoudre ça. Est-ce que quelqu'un sait comment le faire fonctionner?
cc @aaaaahaaaaa @maykefreitas @paulcbetts @tomkel @dkfiresky

@englishextra pas de chance. J'ai essayé d'inclure votre code dans le preload.js de mon application, mais

@englishextra Non, je n'ai pas besoin de jquery dans mon application. Voir le code de mise à jour ici . Je ne peux pas inclure votre code dans ma logique d'application car je ne l'utilise que pour charger l'URL spécifiée voir ceci .

J'ai résolu ce problème avec ça

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

Et mettre

webPreferences: {
            nodeIntegration: false, 
        }

si vous avec nodeIntegration: true, imorot jQuery comme ça

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

référence à
https://github.com/electron/electron/issues/345

Je veux dire, cela semble être un mauvais problème, alors pourquoi ne pas l'inclure dans Electron ? Peut-être intégrer les principales bibliothèques JavaScript dans Electron ?

Il y a de fortes chances que si vous utilisez jQuery dans une application Electron, vous faites quelque chose de très mal ou du moins d'inefficace.

<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 L' inclusion de bibliothèques tierces dans Electron semble être une mauvaise idée. Imaginez la routine de mise à jour, par exemple, ou le choix d'une version.
@amhoho C'est parce que vous devez require jQuery, ou modifier son code d'initialisation dans la fonction supérieure - ne laissant que factory( global );

Ici:

( 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 );
    }

Dans mon cas, je charge des bibliothèques via fetch/Promise ou xhr, j'ai donc cette routine pour supprimer les vérifications de module dans les bibliothèques des fournisseurs.
@RRorg bizarre ce que tu dis

marque

@kabalage Je pense que la configuration de votre message ci-dessus est obsolète. On dirait que ça devrait être comme ça maintenant :

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

Sur les documents officiels :
https://electronjs.org/docs/faq#i -can-not-use-jqueryrequirejsmeteorangularjs-in-electron
```