Electron: jQuery не установлен глобально, потому что определен "модуль"

Созданный на 6 мая 2014  ·  71Комментарии  ·  Источник: electron/electron

jQuery содержит что-то вроде этого:

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

модуль определен даже в скриптах на стороне браузера. Это заставляет jQuery игнорировать объект window и использовать module , поэтому другие сценарии не найдут ни $ ни jQuery в глобальной области видимости ..

Я не уверен, что это ошибка jQuery или атомной оболочки, но я хотел разместить это в Интернете, чтобы другие не выполняли поиск так долго, как я.

Самый полезный комментарий

Просто отключите module .

Я хотел, чтобы моя веб-страница работала как в браузере, так и в электронном.
Как объясняется в этом потоке, при nodeIntegration: true электрон предоставляет глобальный module nodeIntegration: true , который затем jQuery видит и реагирует соответствующим образом:

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

Мне удалось заставить jQuery привязаться к объекту window и использовать nodeIntegration: true , выполнив в моем 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>

Надеюсь, это кому-то поможет.

Все 71 Комментарий

На самом деле это не ошибка для обеих систем, у вас такая же проблема при использовании browserify. jQuery видит, что он работает в среде CommonJS, и ожидает, что он будет использоваться как таковой.

Однако решение относительно простое. Вместо того, чтобы загружать jQuery как тег скрипта, загрузите его через require:

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

Я согласен с @ChiperSoft , это ожидаемое поведение в среде CommonJS, поэтому я пометил это как wontfix . И спасибо, что поделились своим открытием.

@ChiperSoft , куда мне положить файл jquery.js, чтобы require('jquery') ? Я пытался поставить его на тот же уровень, что и package.js и main.js но среда выполнения, похоже, не улавливает его.

Вы можете использовать require('jquery.js') обратите внимание на .js в конце, чтобы загрузить jquery относительно вашего HTML-файла.

Извините, я использовал window.$ = window.jQuery = require('/path/to/jquery'); как упоминалось, но это не работает,
Uncaught Error: Cannot find module 'scripts/jquery-1.10.2.min.js' module.js:339

Я использую это все время, и он отлично работает! Вот что я использую, помните о пути:

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

@frankhale о, это сработало с ./ , спасибо!

Потрясающий! Путь тоже сбил меня с толку.

Если вашему приложению не требуется интеграция узлов, добавьте "node-integration": false в параметры BrowserWindow. В этом случае module.exports недоступен, jQuery работает нормально.

@kabalage отлично поработал, спасибо!

: +1:

Подошел к той же проблеме. Установите jQuery через NPM, затем он потребовался, и он сработал.

что, если требуется интеграция узлов и jquery без требования ...

Я пытаюсь разобраться в этом, поскольку мне кажется, что это то, что я мог бы использовать. Однако мне интересно, когда вы можете быть уверены, что можете безопасно использовать $. Ведение журнала $ сразу после этой строки будет требовать, а не jquery, поскольку require является асинхронным?

window. $ = window.jQuery = require ('/ path / to / jquery');
console.log ($) // журналы 'требуют', а не 'jQuery'

@dieroux попробуйте установить его через npm:

npm install jquery

Это сработало для меня, пока я пытался то же самое. Тогда вам не нужно указывать путь, вы просто говорите:

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

Что, если нам нужна интеграция узлов, а мы не можем использовать require ('something')?
В настоящее время он работает, выполняя «удалить модуль;» перед загрузкой проблемных вещей.
Какое влияние это окажет?

У меня возникают аналогичные проблемы, когда jquery может быть загружен правильно в первый раз, когда он мне понадобится в сценарии предварительной загрузки в веб-просмотре. Однако во второй раз jquery ссылается на внешнюю страницу, строка для его назначения через:

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

выдает в консоли свойство Cannot read createElement of undefined при назначении window.jQuery из require, в результате чего jQuery не загружается.

Сообщение об ошибке на консоли:
Гостевая страница зарегистрировала сообщение: TypeError: Невозможно прочитать свойство createElement неопределенной строки: 40

Есть ли дополнительные мысли о том, как успешно загрузить jquery на последующих страницах?

Спасибо.

Это было первое, о чем я споткнулся при запуске электронного быстрого запуска и попытался обернуть локальное приложение - что-то, что работает в Chrome, внезапно не участвует в выборах. Погребение ошибки в неудачных загрузках модуля angular, конечно, не помогает, поэтому я предположил, что возникла проблема с порядком загрузки скриптов, и именно так я нашел этот поток. Возможно, ключевые слова помогут другим.

Решение @kabalage , приведенное выше, сработало отлично.

Привет всем, я просто хочу добавить некоторую информацию об этой проблеме. Если я вставлю код библиотеки jquery в электронную консоль $, а jQuery будет добавлен как функция в объект окна. я смог запустить jquery.

Ссылка на jQuery с тегом скрипта, та же ошибка. Обязательно "узел-интеграция": false в BrowserWindow ()

Привет, ребята ... Я не уверен, почему эта проблема закрыта, здесь определенно есть проблема, позвольте мне объяснить. Если я устанавливаю jQuery локально через NPM и загружаю локальный файл html, используя:

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

тогда он работает как положено. Однако если я сделаю mainWindow.loadUrl ('http://external.site.com ");

Я получаю упомянутые ошибки, когда $ и jQuery не определены. Отключение интеграции узлов - действительно неприемлемый ответ; Это причина, по которой я использую Electron в первую очередь, он мне нужен.

Я бы с удовольствием разобрался в источнике и сам решил эту проблему, но подумал, что посмотрю, есть ли у кого-нибудь дополнительная информация по этому поводу, которая укажет мне правильное направление, прежде чем я пойду туда. Кто-нибудь смог заставить это работать _с_ интеграцией узлов против внешних сайтов?

Спасибо ... и отличная работа, кстати. Все новое и красивое, как это, начнется с нескольких морщинок.

С уважением

/ Вт

Я заставил его работать с интеграцией узлов.

  1. Установите его с помощью npm, поэтому он определен в package.json
  2. Используйте require с именем модуля <script>window.$ = window.jQuery = require('jquery');</script>
  3. Не используйте путь в обязательном параметре.
  4. Не устанавливайте trough bower, это заставит вас использовать path в параметре require.
  5. Если вы используете бутстрап, вам нужно сначала загрузить jQuery.

Все вышесказанное подтверждено только моим опытом.

Буду работать

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

Не буду

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

Привет, dilmdeep, спасибо за быстрый ответ. Ваше решение зависит от контроля над внешним сайтом? Я пытаюсь загрузить сайт, к которому у меня нет доступа к источнику. Однако то, что вы сказали о package.json, интересно. Я установил jQuery через npm (и использовал документированную перестройку для электрона), и, как я уже сказал, я могу использовать jQuery с локальным файлом HTML, но jQuery не определен в моем package.json ..... О, и я тестировал с отключением интеграции узлов, и хотя это действительно работает, это не то, что мне нужно. Спасибо.

Я просто хотел обновить это на случай, если у кого-то возникнет такая же проблема. То, как я работал над этим (после загрузки 10 ГБ исходного кода Electron), было изначально указано в документации. Вместо вызова URL-адреса внешнего сайта я загрузил локальный HTML-файл и использовал веб-просмотр из этого HTML-файла для загрузки внешнего сайта. Он отлично загружается с включенной интеграцией узлов. Просто посмотрите документацию на веб-просмотр, это довольно просто. Также выражаю благодарность Полу в чате за то, что помог мне начать работу с исходным кодом. Если кому-то интересно, они используют Atom (конечно) для программирования Electron, WinDbg в Windows для отладки и Ninja для компиляции. К вашему сведению, компиляция исходников была чрезвычайно простой и удивительно быстрой, она компилировалась в первую очередь с использованием их скриптов и предоставленной документации. Опять молодцы, ребята поработали!

@WolfieWerewolf Браво! Должен сказать, что этот пример немного вводит в заблуждение, если принять во внимание безопасность.

@ Shufeng01 Ура,

@diimdeep спасибо, ваше решение работает для меня (не то, что хочет @WolfieWerewolf !)

Для нас это небольшая проблема. Мы связываем jquery с нашим приложением js, и этот объединенный JS затем используется в сборке как для веб-версии, так и для настольной версии (мы использовали NWJS). Установка NPM может быть для нас вариантом, но в нашей ситуации она не идеальна по нескольким причинам.

Нет ли теоретического способа заставить его работать с помощью тегов скрипта?

@bgSosh , почему бы не отключить интеграцию узлов (о ключе node-integration читайте здесь )? Если вы это сделаете, теги скрипта должны работать правильно. Если вам нужны какие-то вещи, связанные с узлами, вы можете сделать это в сценарии preload (они всегда имеют интеграцию узлов).

@etiktin, не могли бы вы рассказать, как это сделать при предварительной загрузке? Я новичок в электронике, и мне удалось получить сценарий предварительной загрузки для выполнения (по крайней мере, он не запускается, console.log не работает, изменение window.myExposedIPC = require ('ipc'), например, позже недоступно и т. д.

у меня он работает, если у кого-то такая же проблема: https://github.com/atom/electron/issues/1753#issuecomment -157409572

@matthiasg рад, что у вас все заработало. Я добавил несколько комментариев к вашему примеру.

Когда интеграция узлов отключена, и вы хотите сделать что-то с узлами в своем сценарии предварительной загрузки, важно иметь ссылку на то, что вам нужно. Вам нужно сделать это, потому что на следующем тике глобальные ссылки удаляются (так реализовано отключение интеграции узлов), поэтому, если вы не держали ссылку, а затем пытаетесь потребовать что-то при вызове функции или таймера , это не удастся.

@etiktin спасибо. Конечно, это было частью этого, но чего мне не хватало, так это документации для process.once('loaded', ... ) когда она была на месте, и я действительно могу предоставить API, который я хотел.

Привет, ребята,

Поскольку ничего из вышеперечисленного у меня не сработало (используя w2ui и JQuery как с электронной, так и с независимой HTML-страницей, пусть также w2ui использует jQuery), я почувствовал необходимость опубликовать свое рабочее решение здесь:

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

Я новичок в JS и занимаюсь технологическим исследованием, и теперь немного беспокоюсь об этой непонятной загрузке модуля. Это может быть глупый вопрос, но почему электронная загрузка JS-модулей так отличается от обычных браузеров при загрузке HTML-страницы?

@forman Вы отключили интеграцию узлов и использовали сценарий предварительной загрузки для взаимодействия с узлами? См. Комментарии выше от меня и @matthiasg. Если вы это сделаете, jquery и все остальное будут работать точно так же, как в браузере.

Буду работать

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 Спасибо !! Ничего из вышеперечисленного не сработало, кроме вашего решения. (с использованием предварительно созданной электроники 0.35.5)
@etiktin Это сработало для меня, не меняя ничего на стороне mainProcess

Подумал, что мне следует добавить нашу проблему и решение в эту ветку для дальнейшего использования.

Мы загружаем внешний URL-адрес в веб-просмотр, и нам нужно выполнить наш собственный Javascript, который может использовать файл electronic / Node. Включение интеграции узлов в веб-просмотр не является вариантом, поскольку это нарушит jQuery, который используется внешним URL-адресом.

В итоге мы добавили сценарий предварительной загрузки в веб-просмотр, в который мы поместили нужные нам модули в глобальную область видимости. Это делает их доступными позже, когда мы выполняем наш Javascript.

preload.js:

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

И тогда мы можем получить доступ к ipcRenderer, например:

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

Uncaught Error: Cannot find module 'jquery' и из этой ветки ничего не помогает = /

Просто отключите module .

Я хотел, чтобы моя веб-страница работала как в браузере, так и в электронном.
Как объясняется в этом потоке, при nodeIntegration: true электрон предоставляет глобальный module nodeIntegration: true , который затем jQuery видит и реагирует соответствующим образом:

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

Мне удалось заставить jQuery привязаться к объекту window и использовать nodeIntegration: true , выполнив в моем 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>

Надеюсь, это кому-то поможет.

@tomkel вот еще одно решение:

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

В моем случае мне нужно иметь возможность запускать свое приложение как веб-сайт, так и приложение Electron. Вот мое решение:

<!-- 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 Да, похоже, это тоже работает. Однако я использую Highcharts вместе с jQuery. Highcharts делает то же самое, помещая себя на module если он существует. По какой-то причине я не смог получить

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

работать. Я обновил свой предыдущий комментарий, чтобы отразить это.

@tomkel ваше решение с временным сокрытием module мне очень хорошо подходит . Моя проблема возникла во время миграции с nw.js с ngDialog, предполагая, что в среде CommonJS не удалось выполнить require('angular') и зарегистрироваться как модуль angular.

В Electron 0.36.7 я обнаружил, что не могу выполнить простой window.$ = require('jquery'); поскольку он не смог бы найти модуль. Рендерер, похоже, не имеет того же пути разрешения модуля, что и основной процесс

На самом деле это не работает, потому что jQuery будет работать в основном процессе, в котором нет document . И require('jquery') у меня не сработало, потому что я обслуживаю страницу через HTTP, например # 4243. Чтобы исправить это, я попытался добавить пути к модулям из основного процесса в процесс рендеринга:

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

После этого я могу без проблем делать require('jquery') . Не уверен, какое еще влияние это может иметь

И require ('jquery') у меня не сработал, потому что я обслуживаю страницу через HTTP, например # 4243.

Если вы разрешаете удаленному контенту доступ к node.js, ваше приложение очень небезопасно, вам необходимо отключить интеграцию узлов при запуске удаленного контента и использовать сценарий предварительной загрузки

Даже если «удаленный контент» - это localhost? Я использую узел для создания и обслуживания страницы вместо чтения из локального файла, вот и все

Расширяя @dkfiresky , вы можете получить Uncaught ReferenceError: module is not defined в версии браузера.

Если да, попробуйте это:

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

@dspint module будет неопределенным только в том случае, если интеграция узлов отключена, поэтому вам, вероятно, следует использовать мой пример только с включенной интеграцией узлов.

Если вы используете window.open , вы можете передать nodeIntegration=0 с параметрами окна.

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

Я делаю:

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

У меня была та же проблема, что и у @gnail. У меня был сервер узлов, на котором запущен угловой проект. Его код исправил это для меня.

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

У меня это работает 😄

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

У меня проблема, я уже перепробовал всю эту ветку. но ничего не работает, я застрял в начале
из всех.
Я пользуюсь электронным стартером

@PauloGaldo в основном любое решение в этой теме должно работать. Пожалуйста, опубликуйте соответствующий отрывок из вашего кода и все сообщения об ошибках, с которыми вы столкнетесь.

@ChiperSoft Подскажите , пожалуйста, где мне использовать ваш код?

@tomkel Очень мило!
Наконец-то я заставил масонство работать в Electron!

По какой-то причине я до сих пор не могу заставить jQuery работать как в браузере, так и в приложении Electron.
Мое веб-приложение отлично работает в браузере, тогда как когда я пытаюсь загрузить тот же URL-адрес через электронное приложение, оно выдает -

image

Веб-приложение - https://github.com/zulip/zulip
Приложение Electron - https://github.com/zulip/zulip-electron

Веб-приложение использует версию jquery 1.12.1 через npm.
Я не могу отключить интеграцию узлов, потому что мне это нужно в моем процессе рендеринга.
Мне сложно это решить. Кто-нибудь знает, как заставить работать?
cc @aaaaahaaaaa @maykefreitas @paulcbetts @tomkel @dkfiresky

@englishextra не повезло. Я попытался включить ваш код в preload.js своего приложения, но получил ту же ошибку.

@englishextra Нет, мне не нужен jquery в моем приложении. Смотрите код обновления здесь . Я не могу включить ваш код в свою логику приложения, так как я использую его только для загрузки указанного URL-адреса, см. Это .

для тех, кто использует фреймворк Aurelia:
https://github.com/aurelia/skeleton-navigation/pull/675/commit/6292e698dcb8f383afc748aa7c8a50e540dfbe2e

Я решил эту проблему с помощью этого

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

и установить

webPreferences: {
            nodeIntegration: false, 
        }

если вы используете nodeIntegration: true, imorot jQuery вроде этого

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

ссылка на
https://github.com/electron/electron/issues/345

Я имею в виду, что это кажется серьезной проблемой, так почему бы не включить ее в настоящий Electron? Может быть, интегрировать основные библиотеки JavaScript в Electron?

Скорее всего, если вы используете jQuery в приложении Electron, вы делаете что-то очень неправильно или, по крайней мере, неэффективно.

<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 Включение 3-х сторонних библиотек в Electron кажется плохой идеей. Представьте, например, процедуру обновления или выбор версии.
@amhoho Это потому, что вам нужно require jQuery или изменить его код инициализации в верхней функции, оставив только factory( global );

Здесь:

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

В моем случае я загружаю библиотеки через fetch / Promise или xhr, поэтому у меня есть эта процедура для удаления проверок модулей в библиотеках поставщиков.
@RRorg странно, что ты говоришь

отметка

@kabalage Я думаю, что конфигурация в вашем сообщении выше устарела. Похоже, сейчас должно быть так:

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

В официальных документах:
https://electronjs.org/docs/faq#i -can-not-use-jqueryrequirejsmeteorangularjs-in-electronic
`` ''