Electron: Das Anfordern von Elektron außerhalb von main.js verursacht einen TypeError

Erstellt am 22. Sept. 2016  ·  82Kommentare  ·  Quelle: electron/electron

  • Elektronenversion: 1.3.5
  • Betriebssystem: Mint 17

Hallo

Ich verwende unter anderem Electron mit React.js und babelify (Liste unten).
Der Versuch, require('electron') zu verwenden, um beispielsweise Zugriff auf BrowserWindow von electron zu erhalten, führt dazu, dass die Konsole den folgenden Fehler anzeigt:
index.js:4 Uncaught TypeError: fs.readFileSync is not a function

Ich kann jedoch const electron = require('electron'); in main.js verwenden. Für das, was es wert ist, verwende ich auch watchify, um alles in ein js-Bundle zu packen.

Hier ist die vollständige Liste der Abhängigkeiten in meiner package.json:

"devDependencies": {
        "axios": "^0.9.1",
        "babel-preset-es2015": "^6.6.0",
        "babel-preset-react": "^6.5.0",
        "babelify": "^7.2.0",
        "classnames": "^2.2.3",
        "electron": "^1.3.5",
        "electron-reload": "^0.2.0",
        "jquery": "^2.2.3",
        "react": "^0.14.8",
        "react-autocomplete": "^1.0.0-rc2",
        "react-dom": "^0.14.7",
        "react-sound": "^0.4.0",
        "soundmanager2": "^2.97.20150601-a"
    },
blockeneed-info ❌

Hilfreichster Kommentar

Für alle, die in Zukunft auf dieses Problem stoßen und diesen Thread lesen, ist die Verwendung window.require anstelle von require eine Möglichkeit, den Konflikt zwischen der Funktion require von electron und browserify zu vermeiden.

Alle 82 Kommentare

index.js:4 Uncaught TypeError: fs.readFileSync ist keine Funktion

Können Sie Zeile 4 von index.js hier einfügen? Oder ein vollerer Stack-Trace?

Ich glaube, es bezieht sich auf index.js von Elektron, das sich selbst in Knotenmodulen des Projekts befindet. Hier sind die Inhalte dieser Datei:

var fs = require('fs')
var path = require('path')

module.exports = path.join(__dirname, fs.readFileSync(path.join(__dirname, 'path.txt'), 'utf-8'))

Der gesamte Stack-Trace deutet auf einen Konflikt mit React.js hin:

Stack trace

Was passiert, wenn Sie require('fs').readFileSync über die Registerkarte „Konsole“ der Entwicklertools ausführen?

Es sieht so aus, als würde das electron-prebuilt -Knotenmodul (die von Ihnen eingefügte Datei) in Ihrer gepackten App landen, was Sie meiner Meinung nach nicht möchten, da es stattdessen das integrierte electron -Requirement verwenden sollte.

@nukeop Wie startest du deine App? Ihr `Startskript sollte so aussehen.

"scripts": {
  "start": "electron ."
}

Ich habe das Gefühl, dass Sie versuchen, Ihr main.js mit Knoten auszuführen

node main.js

Was nicht funktionieren wird

Was passiert, wenn Sie require('fs').readFileSync auf der Registerkarte "Konsole" der Entwicklertools ausführen?

Unmittelbar nachdem dieser Fehler ausgelöst wurde, kann ich require('fs').existsSync in der Konsole ausführen, um eine Definition der Funktion zu drucken. Es funktioniert auch vor dem Fehler.

Es sieht so aus, als würde das von Electron vorgefertigte Knotenmodul (die Datei, die Sie eingefügt haben) in Ihrer gepackten App landen, was Sie meiner Meinung nach nicht wollen, da es stattdessen das eingebaute Electron require verwenden sollte.

Während ich entwickle, läuft im Hintergrund eine Watchify-Instanz, die mein Paket ständig aktualisiert. Ich habe es im scripts-Abschnitt von package.json wie folgt definiert:

"watch": "watchify app/app.js -t babelify -o public/js/bundle.js --debug --verbose"

Irgendwelche Ratschläge zur Vermeidung der Bündelung electron-prebuilt ?

@nukeop Electron unterstützt intern erfordern, sodass Sie browserify nicht verwenden müssen.

Soweit mir bekannt ist, möchten Sie browserify verwenden, müssen Sie "Elektron" ausschließen.

Interessant, könnte es sein, dass watchify/browserify dies ruiniert? Es hat bisher ok funktioniert.

Jetzt bin ich mir nicht sicher, wie ich das Programm ohne es ausführen soll.

Laufen Sie buchstäblich nur

electron .

Aus Ihrem Haupt-App-Ordner müssen Sie nichts bündeln, wenn Sie Electron verwenden, da es intern über eine vollständige Knotenumgebung verfügt.

_Ich werde dies schließen, da es sich um ein Browserify-Problem handelt_

Das habe ich die ganze Zeit gemacht, das Programm in eine einzige .js-Datei gepackt, die in einer einfachen HTML-Datei enthalten ist mit:

  <script src="public/js/bundle.js">
  </script>

Und alles funktioniert, außer wenn ich require verwende. Dies ist ein Problem bei der Interaktion zwischen den beiden Modulen.

Wenn ich nicht das ganze Programm in ein Bundle packe, habe ich keine einfache Möglichkeit, es auszuführen, da meine main.js nur electron startet und die HTML-Datei lädt, die das Bundle enthält.

@nukeop Der Renderer-Prozess in Electron hat auch Zugriff auf eine vollständige Node/Commonjs-Umgebung, sodass Sie nichts bündeln müssen.

Wenn ich nicht das ganze Programm in ein Bundle packe, habe ich keine einfache Möglichkeit, es auszuführen, da meine main.js nur electron startet und die HTML-Datei lädt, die das Bundle enthält.

Ich bin mir nicht sicher, ob ich das hier verstehe, jedes Skript, das Sie in Ihre HTML-Datei laden, hat eine vollständige commonjs-Umgebung und kann daher require verwenden, um zusätzliche Dateien zu laden, ohne etwas zu durchsuchen

Für alle, die in Zukunft auf dieses Problem stoßen und diesen Thread lesen, ist die Verwendung window.require anstelle von require eine Möglichkeit, den Konflikt zwischen der Funktion require von electron und browserify zu vermeiden.

FWIW, ich bin auf das gleiche Problem gestoßen, als ich versuchte, Elektron im Renderer-Prozess mit create-react-app zu verwenden, das webpack im Backend anstelle von browserify verwendet. window.require scheint es auch für mich zu lösen, obwohl mir nicht ganz klar ist, warum.

Bearbeiten : Ich habe herausgefunden, warum :-) Wir wollen require electron während der Laufzeit aus der zur Laufzeit bereitgestellten nodejs-Umgebung und nicht aus der nodejs-Umgebung, die während der Kompilierung durch das Webpack verwendet wird. Standardmäßig sind Globals an window gebunden und die Webpack-Kompilierung ignoriert das Globale window - daher funktioniert window.require .

Eine andere Möglichkeit, webpack anzuweisen, einen globalen Namen zu ignorieren, besteht darin, einen Kommentar wie /*global Android*/ in der JS-Datei zu verwenden. In einem anderen Projekt, bei dem eine von CRA erstellte App in einem Android-WebView verwendet wurde, habe ich das obige verwendet, um Zugriff auf ein Java-Objekt zu erhalten, das JS über die von Webview bereitgestellte JavaScript-Schnittstelle bereitgestellt wird.

@nukeop - danke für deinen letzten Beitrag; es hat mir sehr geholfen. window.require hat bei mir funktioniert.

Ja, mein Problem beim Erstellen einer Reaktions-App / Webpack wurde behoben.
Veränderung

import electron, { ipcRenderer } from 'electron'

zu

const electron = window.require("electron")

@srinathh wie stellen Sie Ihre CRA-App als Renderer in Ihrem Main zur Verfügung / laden Sie sie? bauen Sie zuerst (und ändern die statischen HTML-Ressourcenpfade)

Ja, mein Arbeitsablauf besteht derzeit darin, npm run build mit den CRA-Skripten auszuführen und dann die Ausgabe im Ordner build mit Elektron auszuführen. Sie müssen die statischen Ressourcenpfade nicht manuell ändern. In den package.json für CRA-Skripten müssen Sie nur die homepage wie folgt festlegen und die Pfade werden entsprechend festgelegt.

    "homepage": "./"

Außerdem habe ich main.js und package.json für die Elektron-App im Ordner public . Wenn Sie also den Build ausführen, werden sie automatisch kopiert und Sie können einfach electron build/ ausführen, um Ihre App zu starten.

Ich würde eigentlich gerne in der Lage sein, die npm start mit Elektron für die Entwicklung zu machen, aber ich bin noch nicht dazu gekommen, herauszufinden, wie das funktioniert. Ich schätze, ich muss eject machen und das Skript von Hand ändern.

Wenn Sie ein Beispiel für die Einrichtung sehen möchten, werfen Sie einen Blick auf https://github.com/srinathh/snippetfu

Ich verwende nicht Electron, sondern Node-Webkit (nw.js).
Die Verwendung window.require hat auch mein Problem behoben. Vielen Dank dafür!

@nukeop window.require hat es mir auch angetan, vielen Dank! 🎉

@nukeop Ich habe den gleichen Fehler, aber es ist gelöst window.require Trick, vielen Dank!

window.require hat das Problem von fs.existsSync is not a function gelöst, aber es führte zu einem weiteren Fehler: window.require ist keine Funktion. Wie soll ich es lösen?

@steric85 verwendest du browserify, babel oder webpack? Möglicherweise müssen Sie Ihren Code transpilieren

@Alxmerino Ich verwende Webpack.

Stellen Sie sicher, dass Sie Ihren Code kompilieren

@ steric85 , ich habe das window.require is not a function in Typoskript gesehen, ich habe es geschafft, es auf diese Weise zu beheben:

declare global {
  interface Window {
    require: any;
  }
}

const electron = window.require('electron');

Ich verwende die obige Methode für den Zugriff auf den ipcRenderer von Elektron in meiner Angular-App, aber die Angular-Änderungserkennung funktioniert nicht, wenn ich ein Observable mit einem ipcRenderer-Nachrichtenhandler aktualisiere.
Liegt es daran, dass Angular nicht weiß, dass ipcRenderer ein EventEmitter ist und dass es eine Änderungserkennung ausführen muss, wenn ipcRenderer-Ereignisse eingehen?

In Angular 2 habe ich applicationRef.tick() aufgerufen, um Angular explizit mitzuteilen, dass es seinen Zustand aktualisieren soll. https://angular.io/api/core/ApplicationRef

Ich stehe vor einem sehr ähnlichen Problem wie @nukeop und @srinathh : Ich habe mein Electron + React + Webpack-Projekt nach dieser Artikelanleitung eingerichtet, wo der Autor am Ende den Trick mit window.require erwähnt. Ich habe nur require('electron') zwei Stellen in meinem Projekt; im Einstiegspunkt für Electron und in einer JavaScript-Controller-Klasse, die von einigen React-Komponenten benötigt wird. In meiner Electron-Einstiegspunktdatei mache ich einfach const electron = require('electron'); , da es im Hauptprozess laufen sollte (richtig?), und in meiner Controller-Klasse mache ich const Electron = window.require('electron').remote; gefolgt von const Jsonfile = Electron.require('jsonfile'); , was der richtige Weg sein sollte, da es im Renderer-Prozess ausgeführt wird. Aber ich bekomme den gleichen Fehler wie @nukeop ("TypeError: fs.ExistsSync is not a function") in Zeile sechs in node_modules/electron/index.js, der so aussieht:

var fs = require('fs')
var path = require('path')

var pathFile = path.join(__dirname, 'path.txt')

if (fs.existsSync(pathFile)) {
  module.exports = path.join(__dirname, fs.readFileSync(pathFile, 'utf-8'))
} else {
  throw new Error('Electron failed to install correctly, please delete node_modules/electron and try installing again')
}

Ich habe versucht, node_modules/electron zu löschen und erneut zu installieren.
Ich verwende Electron 1.7.5 unter macOS 10.12.6 und starte mein Projekt mit npm run dev als Setup im Artikel.

Aktualisieren; Ich habe das require gefunden, das meinen Fehler verursacht hat. Ich habe versucht, require('electron-react-devtools') in meiner React index.js auszuführen. Das Ändern in const ReactDevtools = Electron.require('electron-react-devtools'); hat die Fehler gestoppt, aber jetzt scheint es, dass ich .inject() in der ReactDevtools-Instanz nicht aufrufen kann ("ist keine Funktion"), aber das sollte hier nicht besprochen werden .

@steric85 Das liegt daran, dass Sie die App in der Webseitenumgebung ausführen => Sie müssen die App in der Electron-Umgebung (Nodejs-Umgebung) ausführen.

  • require('electron') => Webpack bündelt das Elektron-Modul in bundle.js => Elektron verwendet das fs-Modul => Webpack versteht es nicht
  • window.require('electron') => Webpack wird die Require-Funktion ignorieren
  • In der Webseitenumgebung ist window.require nicht definiert
  • In der nodejs-Umgebung funktioniert window.require
    => Öffnen Sie Ihre App im Electron-Fenster (nicht im Browserfenster wie Chrome, Firefox usw.

Ich bekomme immer noch window.require is not a function . Ich verwende Electron mit React Starter Kit (https://github.com/kriasoft/react-starter-kit). Alles funktioniert gut, außer diesem.

Ich habe meine Electron-App so eingestellt, dass sie meine App aus dem Internet lädt, sodass die App nicht lokal ausgeführt wird:
https://gist.github.com/holgersindbaek/68f6db82f507967a51ca75c527faeff6

Was ich versuche, ist, ipcRenderer in einer meiner React-Dateien aufzurufen. Ich bin mir nicht sicher, ob es überhaupt möglich ist, wenn meine App aus dem Internet geladen wird. Irgendwelche Vorschläge?

@holgersindbaek Sie sollten Ihre App nicht in Browsern wie Chrome, Firefox usw. anzeigen. Es funktioniert nicht, da es sich um die Webseitenumgebung handelt.
Sie sollten Ihre App in einem Electron-Fenster anzeigen.

Das bin ich, aber ich verwende Electron so, dass ich meine App bei jedem Start von der Website lade. Im Wesentlichen zeige ich eine Website in meiner Elektron-App. Siehe obige Datei. Ich will nur sichergehen, dass ich wirklich nichts tun kann?!

Electron kann beliebige URLs laden. Um eine URL zu laden, verwenden Sie diese Funktion mainWindow.loadURL(url)
=> In der Elektronenfensteransicht kann dieser URL-Javascript-Code auf require, ipc usw. zugreifen.

In Ordnung. Ich werde das versuchen.

window.require auf Elektron hat nicht funktioniert, aber window.require für fs hat funktioniert.

Nicht wirklich sicher, warum. Aber es funktioniert und da es sich um ein kleines persönliches Projekt handelt, werde ich das Thema nicht vorantreiben.

Danke @nukeop

Hallo, das ist meine package.json, ich benutze Webpack, keines davon hat mein Problem gelöst, hat jemand eine Lösung? Nachdem ich window.require verwendet habe, habe ich den Fehler "Fenster ist nicht definiert" erhalten.

'streng verwenden';

var Elektron = require('Elektron')
var app = elektron.app;
var BrowserWindow = Elektron.BrowserWindow;
var mainWindow = null;

app.on('bereit', function() {
mainWindow = new BrowserWindow({width: 800, height: 600});

mainWindow.loadURL('file://' + __dirname + '/index.electron.html');

mainWindow.webContents.openDevTools();

});

Ich verwende Typoskript und ich musste verwenden

const electron = (<any>window).require("electron");

um meinen Renderer dazu zu bringen, mit meinem Main zu kommunizieren. Hoffe, das hilft jemandem.

Das hat bei mir funktioniert.
Wenn Sie zB eine Fernbedienung benötigen, dann

const window deklarieren: any;
const {remote} = window.require('electron');

Hallo, danke Mann.

Am Sonntag, 3. Dezember 2017 um 21:29 Uhr, Michael - ሚካኤል ሰልጠነ <
[email protected]> schrieb:

Das hat bei mir funktioniert.
Wenn Sie zB eine Fernbedienung benötigen, dann

const window deklarieren: any;
const {remote} = window.require('electron');


Sie erhalten dies, weil Sie kommentiert haben.
Antworten Sie direkt auf diese E-Mail und zeigen Sie sie auf GitHub an
https://github.com/electron/electron/issues/7300#issuecomment-348801405 ,
oder den Thread stumm schalten
https://github.com/notifications/unsubscribe-auth/ARDyd4c3aOkMbb058xklujMMbnmaoxKGks5s8uGVgaJpZM4KDU6t
.

@solominh Danke für deine Erklärungen hier . Ich habe jedoch eine ähnliche Konfiguration wie @holgersindbaek , welche Umgebung ist ein Preload-Skript in einer Webansicht?

Die Info:

  • Mein Elektron-Eintrag läuft mainWindow.loadURL(url) , wobei url eine lokale index.html ist
  • Diese index.html hat ein <webview>
  • Die Webansicht hat ein preload -Feld, das inject.js lädt, und dieses Skript führt window.require('electron') aus.

Bemerkungen:

  • Wenn ich const electron = require('electron') verwende, bekomme ich den Fehler fs.readFileSync is not a function
  • Wenn ich const electron = window.require('electron') verwende, bekomme ich den Fehler window.require is not a function .
  • inject.js wird über das Webpack gebündelt (kann bei Bedarf die Konfiguration einfügen).

BEARBEITEN: Gelöst für mich mit <webview nodeintegration="true"> und window.require. Hinterlassen Sie hier eine Notiz zum späteren Nachschlagen.

window.require hat bei mir funktioniert! Danke Leute!

https://imgur.com/a/ekWwD

Fehlermeldung im Browser, als ich dies versuchte

Ich habe vergessen, nodeIntegration: false zurückzusetzen, wodurch sogar window.require().. deaktiviert wird. dummer Fehler. Ich hoffe, das erspart jemandem eine Stunde Recherche.

@phil294 Danke Mann! Sie haben wirklich eine Stunde der Recherche gespart.

Hallo @micsel ,
Ich habe das const-Fenster deklariert: any;
aber es wirft einen Syntaxfehler.
Irgendwelche Ideen warum?

Ja, setzen Sie das const-Fenster deklarieren: beliebig; ganz oben, direkt hinter den Importen.

Wenn Sie erhalten, dass window.require keine Funktion ist und Sie Angular-CLI verwenden, verwenden Sie Folgendes, um die Windows-Schnittstelle zu instanziieren:

./src/typings.d.ts

declare var window: Window;
interface Window {
    require: any;
}

Dann können Sie dies verwenden, um Elektron einzuschließen:
const { ipcRenderer } = window.require('electron');

Wenn Sie Angular 2+ in der Elektron-App verwenden, importieren Sie die Bibliothek „ngx-electron“ und verwenden Sie diese in any.componets.ts

import { ElectronService } from 'ngx-electron';

//constructor
constructor(
    private elt: ElectronService
  ){
  var fs = this.elt.remote.require('fs');
}

Ich verwende React Js mit Electron und wenn ich diese Zeile in den Start des Terminal-Garns führe, wird mir der Fehler Uncaught Type Error angezeigt: window.require ist keine Funktion. Ich verwende kein Typoskript, wie das Fenster in React Js deklariert wird

Leute, die immer noch mit dem Problem konfrontiert sind, verderben irgendwie die Konsistenz der Verwendung von import -Anweisungen in der gesamten Codebasis, wenn sie window.require() machen. Eine einfache Alternative besteht darin, Ihr Webpack target auf electron-renderer zu setzen. Wenn Sie Create React App verwenden, kann das Auswerfen ein Chaos sein. Daher können Sie dieses Paket verwenden, das das Webpack-Hooking für Sie übernimmt, und Sie können es z. B. für import fs from 'fs' in Ihren React-Komponenten (oder jedem anderen Knotenmodul) verwenden, glücklich in Ihrem Leben :)

Unter Windows mit Vue CLI 3 funktioniert window.require, erfordert jedoch einen vollständigen Pfad anstelle eines relativen Pfads von "node_modules/".

Aber ähnlich wie im React-Fall kann Webpack durch Bearbeiten von vue.config.js richtig für Vue konfiguriert werden. "require" funktioniert dann wie erwartet.

vue.config.js:

module.exports = {
    configureWebpack: config => {
      if (process.env.NODE_ENV === 'production') {
        config.output.publicPath = `${process.cwd()}/dist/`
      }
      config.target = 'electron-renderer'
    }
  }

router.js (dies ist nur ein Beispiel, es würde in jeder anderen vue js-Datei funktionieren)

const Store = require("electron-store");
const store = new Store();

_Ich möchte das fast nicht hinzufügen, aber es hätte mir ein oder zwei Stunden Debugging erspart._

Ich musste rm -rf node_modules && npm install um dieses Problem zu beheben. Ich konnte dann window aus window.require entfernen und die Dinge funktionierten wieder. Hoffentlich hilft das jemand anderem.

@cperthuis Ich möchte nur DANKE sagen!! Hahah, ich benutze nicht einmal Vue, aber logisches Denken hat mich dazu gebracht, herauszufinden, dass ich meine webpack.config.js ändern kann, um eine Zieleigenschaft zu haben :)
image
LIEF WIE AM SCHNÜRCHEN.

Hallo,

window.require funktioniert in einer lokalen Dev-Serverumgebung, aber nicht in einer Prod-Umgebung, nachdem die React-App in einer minimierten HTML-Datei erstellt wurde.

function createWindow() {
  win = new BrowserWindow({
    width: 1280,
    height: 720,
    icon: path.join(__dirname, 'assets/icons/png/64x64.png'),
    webPreferences: {
      nodeIntegration: true,
      preload: __dirname + '/preload.js'
    }
  })

  win.setPosition(0, 0)

  win.loadURL(isDev ? 'http://localhost:3000' : `file://${path.join(__dirname, 'build/index.html')}`)
}

Es funktioniert mit localhost:3000 , aber nicht mit file://${path.join(__dirname, 'build/index.html')}

https://imgur.com/EE7jxZq

@cperthuis , Ihr Fix funktionierte für nicht ausgeworfene CRA-Apps mit „react-app-rewired“. Danke schön.
image

Mit Create-React-App 2 können Sie das npm-Modul craco verwenden:

https://www.npmjs.com/package/@craco/craco

Ändern Sie in Ihrer package.json react-scripts durch craco

craco.config.js

module.exports = {
    webpack: {
        configure: {
            target: 'electron-renderer'
        }
    }
};

Und in haben Sie so Zugriff auf Ihren Electron-Kontext:

import Electron from 'electron';
const { dialog } = Electron.remote;

@ Maxou44 danke für den Tipp zu Craco & Elektron. Es ist genau das, was ich brauchte. Falls jemand ein Beispiel sucht...

https://github.com/wwlib/cra-craco-electron-example

@wwlib Kein Problem, freut mich zu sehen, dass es dir geholfen hat 🥳

Ich habe vergessen, nodeIntegration: false zurückzusetzen, wodurch sogar window.require().. deaktiviert wird. dummer Fehler. Ich hoffe, das erspart jemandem eine Stunde Recherche.

Ich danke dir sehr.

Bitte beachten Sie, dass es beim Laden von Remote-Inhalten wichtig ist, nodeIntegration auf false zu setzen: https://electronjs.org/docs/tutorial/security#2 -disable-nodejs-integration-for-remote -Inhalt

Hallo,
Ich habe den gleichen Fehler. Bei der Verwendung von window.require wird der Fehler Uncaught TypeError: fs.readFileSync is not a function behoben, aber ich habe einen anderen Fehler Uncaught TypeError: window.require is not a function gefunden.

Gibt es einen Vorschlag, wie man das beheben kann. Ich verwende browserify auf node js.

Für alle, die immer noch daran festhalten: Sie erhalten den Fehler window.require is not a function , es sei denn, Sie deklarieren nodeIntergation explizit als true , wenn Sie Ihr BrowserWindow deklarieren:

new BrowserWindow({
    webPreferences: {
      nodeIntegration: true,
    }
});

Die einzige gute Lösung, die ich gefunden habe, ist folgende:

  1. als dev-abhängiges react-app-rewired -Paket installieren
  2. Verwenden Sie dieses Modul, um eine benutzerdefinierte Webpack-Konfiguration ohne eject -ing des CRA einzufügen:
 "scripts": {
   ...
    "start": "react-app-rewired start",
  },
  1. und füge die Datei config-overrides.js mit entsprechendem Inhalt hinzu:
module.exports = function override (config, env) {
  config.target = 'electron-renderer'
  return config;
}

Danke an: @Lilanga Kommentar , @agrublev Kommentar und Ersteller von React-App-Rewired .

Aktualisiert:
Eigentlich die 2. Version, wie man dasselbe macht: https://www.codementor.io/randyfindley/how-to-build-an-electron-app-using-create-react-app-and-electron-builder-ss1k0sfer

Aktualisiert2:
@nukeop Ich habe einige irreführende Aussagen entfernt, da ich keine Zeit hatte, Debatten darüber zu verfolgen, warum Browserify nicht verwendet werden sollte oder warum es verwendet werden sollte, und kann jetzt keine detaillierte Erklärung aufschreiben, was ich meinte. Aber ich werde meine persönliche Meinung dazu behalten, dass "nur window.require das Problem lösen wird" sehr unzuverlässig erscheint.

Wie falsch?

Es ist eine React-App, die innerhalb der Electron-Umgebung ausgeführt werden muss und nicht umgekehrt

Was?

_Ich möchte das fast nicht hinzufügen, aber es hätte mir ein oder zwei Stunden Debugging erspart._

Ich musste rm -rf node_modules && npm install um dieses Problem zu beheben. Ich konnte dann window aus window.require entfernen und die Dinge funktionierten wieder. Hoffentlich hilft das jemand anderem.

Wow.. ALLES in diesem Thread ausprobiert und deine Wiederholung verpasst, weil es keine Upvotes gibt.. Immer noch window is not a function ..
entfernt und neu installiert node_modules und es funktioniert.

PS: Sie müssen immer noch alle Lösungen machen, aber wenn Sie alles gemacht haben
und immer noch dasselbe neu installieren node_modules

Du hast meinen Tag gerettet @joshuapinter !

Mit React-Create-App habe ich die gleichen Fehler gefunden.
Die Lösung war bisher:
const electron = window.require("electron") im Elektronenteil BrowserWindow fügen Sie nodeIntegration:true wie folgt hinzu.
mainWindow = new BrowserWindow({ width: 900, height: 680, webPreferences: { webSecurity: false, nodeIntegration: true } });

Die einzige gute Lösung, die ich gefunden habe, ist folgende:

  1. als dev-abhängiges react-app-rewired -Paket installieren
  2. Verwenden Sie dieses Modul, um eine benutzerdefinierte Webpack-Konfiguration ohne eject -ing des CRA einzufügen:
 "scripts": {
   ...
    "start": "react-app-rewired start",
  },
  1. und füge die Datei config-overrides.js mit entsprechendem Inhalt hinzu:
module.exports = function override (config, env) {
  config.target = 'electron-renderer'
  return config;
}

Danke an: @Lilanga Kommentar , @agrublev Kommentar und Ersteller von React-App-Rewired .

Aktualisiert:
Eigentlich die 2. Version, wie man dasselbe macht: https://www.codementor.io/randyfindley/how-to-build-an-electron-app-using-create-react-app-and-electron-builder-ss1k0sfer

Aktualisiert2:
@nukeop Ich habe einige irreführende Aussagen entfernt, da ich keine Zeit hatte, Debatten darüber zu verfolgen, warum Browserify nicht verwendet werden sollte oder warum es verwendet werden sollte, und kann jetzt keine detaillierte Erklärung aufschreiben, was ich meinte. Aber ich werde meine persönliche Meinung dazu behalten, dass "nur window.require das Problem lösen wird" sehr unzuverlässig erscheint.

Das hat bei mir funktioniert. Danke schön

Das Problem mit window.require ist, dass es nur für das Paket der obersten Ebene funktioniert.
zB Wenn ich fs direkt verwende, funktioniert es. Aber wenn ich ein Paket verwende, das eine Abhängigkeit von fs hat, bekomme ich immer noch eine Ausnahme.

window.require es funktioniert bei mir nicht, wenn ich die Funktion in der React App aufrufe. Ich habe "TypeError: window.require is not a function" erhalten.

App.js :
``` Javascript
import React, { useEffect, useState } from 'react';
importiere './App.css';

const ipcRenderer = window.require('elektron').ipcRenderer;

Funktion App() {

useEffect( () => {

    ipcRenderer.on('ping', (event, message) => { console.log(message) });

}, []);

return (
<div className = 'App'>
    <div className = 'Header-Arrow'></div>
    <div className = 'Box'>
        <p>Press ⌘ + ⇧ + 4</p>
    </div>
</div>
);

}

Standard-App exportieren;
````

Hauptfenstervariable auf Main.js :
``` Javascript
// Erstellen Sie das Browserfenster.
Hauptfenster = neues Browserfenster ({
alwaysOnTop: wahr,
Rahmen: falsch,
Vollbildfähig: falsch,
transparent: wahr,
titleBarStyle: 'customButtonsOnHover',
zeigen: falsch,
Breite: 300,
Höhe: 350,
Webeinstellungen: {
nodeIntegration: true,
Vorladen: __dirname + '/preload.js'
}
});

``` ** Preload.js`**:

javascript window.ipcRenderer = require('electron').ipcRenderer;

Was fehlt mir?

Also Problem gelöst. Ich antworte mir selbst, weil vielleicht jemand davon profitieren kann (ich hing stundenlang fest). Wenn Sie eine Preload.js -Datei haben, müssen Sie window.require('electron').ipcRenderer nicht erneut vom Àpp.js (Renderer) aufrufen; Sie rufen die Variable direkt als window.ipcRenderer wie folgt auf:

App.js :

````javascript
import React, { useEffect, useState } from 'react';
importiere './App.css';

Funktion App() {

useEffect( () => {

    window.ipcRenderer.on('ping', (event, message) => { console.log(message) });

}, []);

return (
<div className = 'App'>
    <div className = 'Header-Arrow'></div>
    <div className = 'Box'>
        <p>Press ⌘ + ⇧ + 4</p>
    </div>
</div>
);

}

Standard-App exportieren;
````

Hauptfenstervariable auf Main.js :
javascript // Create the browser window. mainWindow = new BrowserWindow({ alwaysOnTop: true, frame: false, fullscreenable: false, transparent: true, titleBarStyle: 'customButtonsOnHover', show: false, width: 300, height: 350, webPreferences: { nodeIntegration: true, preload: __dirname + '/preload.js' } });
Preload.js :

javascript window.ipcRenderer = require('electron').ipcRenderer;

Nach dem Ausführen der App über die Befehlszeile gibt das vom React-Prozess generierte Fenster einen Fehler aus (ipcRenderer ist nicht definiert). Ignoriere es. Das vom Electron-Prozess (Haupt-App) generierte Fenster funktioniert einwandfrei.

Mit Create-React-App 2 können Sie das npm-Modul craco verwenden:

https://www.npmjs.com/package/@craco/craco

Ändern Sie in Ihrer package.json react-scripts durch craco

craco.config.js

module.exports = {
    webpack: {
        configure: {
            target: 'electron-renderer'
        }
    }
};

Ich hatte die Probleme sowohl bei require("fs") als auch bei window.require("fs") . Danke an @Maxou44 für die Einführung von CRACO in diese Diskussion.

Um das Problem zu lösen, habe ich 3 Änderungen in meinem Projekt vorgenommen:

  1. Benutzte CRACO, wie von @Maxou44 vorgeschlagen.
  2. In public/main.js (einige haben diese Datei möglicherweise als electron.js bezeichnet), geändert
    new BrowserWindow({ width: 1200, height: 800 })
    zu
    new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true } })
  3. const fs = require("fs") durch const fs = require("electron").remote.require("fs") ersetzt

Weitere Erläuterungen finden Sie in diesem Git-Repo von @wwlib https://github.com/wwlib/cra-craco-electron-example

Ich habe den ganzen Thread von oben nach unten gelesen und nichts hat funktioniert.
AUSSER, die obige Methode von @Saroopashree . Danke @Saroopashree für das Teilen der Lösung.
Ich denke, da sich React und Webpack seit dem Start des Threads etwas geändert haben, sind die obigen Lösungen veraltet. Ich kann mich natürlich irren, aber mit der obigen Methode hat es funktioniert.
Folgendes habe ich getan:

  1. Lief npm install craco -D
  2. Erstellen Sie die Konfigurationsdatei craco.config.js und fügen Sie den folgenden Code ein
    module.exports = { webpack: { configure: { target: 'electron-renderer' } } };
  3. new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true } }) in main.js aktualisiert. Natürlich mit unterschiedlicher Breite und Höhe.
  4. npm start , um den Entwicklungsserver für die React-App zu starten, die mit create-react-app erstellt wurde. Dadurch wurde ein Tab mit denselben Fehlern geöffnet. Und ich fühlte mich wieder müde.
  5. npm run electron ausgeführt, um die Elektron-App auszuführen.
    Und Bratsche!!! Ich konnte die Seite sehen.

Also danke @Saroopashree.

Wenn Sie versuchen, auf „Elektron“ oder seine andere Komponente innerhalb einer Reaktionskomponente/Klasse zuzugreifen, versuchen Sie Folgendes: #336757899

Vielen Dank an @tumbledwyer für das Posten des Links zu einer Lösung, die für mich funktioniert:

Aktualisiert:
Eigentlich die 2. Version, wie man dasselbe macht: https://www.codementor.io/randyfindley/how-to-build-an-electron-app-using-create-react-app-and-electron-builder-ss1k0sfer

Die Lösung von Randy Findley:
Wenn Sie jetzt wie ich auf das Modul fs zugreifen müssen, werden Sie schnell auf den Fehler Module not found stoßen

Installieren Sie zuerst Rescripts .

yarn add @rescripts/cli @rescripts/rescript-env --dev

Ändern Sie dann die Skript-Tags in package.json von diesem ...

"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",

dazu

"start": "rescripts start",
"build": "rescripts build",
"test": "rescripts test",

Fügen Sie nun eine neue Datei namens .rescriptsrc.js mit folgendem Inhalt hinzu:

module.exports = [require.resolve('./.webpack.config.js')]

Fügen Sie schließlich eine weitere neue Datei namens .webpack.config.js mit folgendem Inhalt hinzu:

// define child rescript
module.exports = config => {
  config.target = 'electron-renderer';
  return config;
}

Jetzt können Sie das Modul fs verwenden, keine Sorge.

Worauf @ledleds hingewiesen hat, hat bei mir funktioniert, indem ich CRA mit Typscript und Electron verwendet habe. Dann habe ich webPreferences so deklariert:

    webPreferences: {
      preload: path.join(__dirname, 'preload.js')
    },

das scheint also das Überschreiben/Setzen von nodeIntegration auf false zu sein, also das Setzen auf true und das Neustarten der App löste das Problem (Sie müssen die App neu starten, um das Electron-Fenster mit dieser Konfiguration zu laden).

NodeIntegration so auf true setzen

    webPreferences: {
      preload: path.join(__dirname, 'preload.js'),
      nodeIntegration: true
    },

Für alle, die immer noch daran festhalten: Sie erhalten den Fehler window.require is not a function , es sei denn, Sie deklarieren nodeIntergation explizit als true , wenn Sie Ihre BrowserWindow deklarieren:

new BrowserWindow({
    webPreferences: {
      nodeIntegration: true,
    }
});

reagieren-app-neu verdrahtet

Dies war die einzige gute Lösung, die ich in Bezug auf die Skalierbarkeit gefunden habe. Ich denke nicht, dass sich jemand auf window.require verlassen sollte

Warum sollte window.require nicht skalierbar sein?

Für alle, die zufällig mit diesem oder ähnlichen Problemen zu kämpfen haben und Vue und vue-electron-builder verwenden, siehe hier

Für alle, die immer noch damit zu kämpfen haben, insbesondere wenn es darum geht, die Elektronenanwendung über eine Reaktionstaste zu beenden, lesen Sie bitte weiter.

Was bei mir geholfen hat war folgendes:

  1. Wenn Sie Ihr Fenster deklarieren, stellen Sie sicher, dass Sie aus Sicherheitsgründen nodeIntegration: true festlegen, da dies derzeit standardmäßig false ist. Normalerweise geschieht dies in Ihrer electron.js -Datei.

  2. Wie @packetstracer bereits erwähnt hat: _Sie müssen die App neu starten, um das Electron-Fenster mit dieser Konfiguration zu laden_

mainWindow = new BrowserWindow({
//...
  webPreferences: {
    nodeIntegration: true,
  },
});
  1. Setzen Sie auch in Ihrem electron.js die folgende Anweisung ganz oben ein, um sicherzustellen, dass ipcMain auf das Ereignis _"close-me"_ lauscht:
const { ipcMain } = require("electron");
ipcMain.on("close-me", (evt, arg) => {
  app.quit();
});
  1. Fügen Sie in der Reaktionskomponente, in der sich Ihre _"Schließen"_-Schaltfläche befindet, nach Ihren Importen die folgende window.require -Anweisung hinzu. Das übliche require hat nicht funktioniert:
const ipcRenderer = window.require("electron").ipcRenderer;
  1. Und um Ihre Anwendung zu schließen, rufen Sie die folgende Anweisung auf. Es sollte das Ereignis _"close-me"_ an ipcMain senden:
<Button label="close" onClick={(e) => ipcRenderer.send("close-me")} />

Fühlen Sie sich frei, zu kommentieren und Feedback zu geben. Ich bin noch neu bei Elektron.
Ich weiß, dass der Zusammenhang mit dem Beenden-Button nicht zusammenhängt, aber ich konnte keinen besser geeigneten Thread finden. Bitte zögern Sie nicht, mich auf einen anderen, passenderen Thread zu verweisen, falls es einen gibt.

Meine Konfiguration:

"electron": "9.2.0",
"electron-builder": "22.8.0",
"electron-packager": "15.0.0",

für mich gelöst!! Danke @nukeop

`
`

Weiß jemand, wie man den richtigen Typ in Typoskript einrichtet?

Ich habe im Moment folgendes

export const electron = window.require('electron').remote

Ich möchte so etwas wie

export const electron = window.require('electron').remote as ElectronType

Die IDE weiß also, wie die Elektronen-API automatisch vervollständigt wird.

@timsamart es funktioniert. Danke, das spart mir Tage Arbeit. 🤣

Nachdem ich viele Stunden damit verbracht habe, buchstäblich alles oben genannte auszuprobieren, habe ich den Teil verpasst, falls Sie BrowserView verwenden, genau wie BrowserWindow müssen Sie node.js explizit aktivieren:

     new BrowserView({ // is a BrowserView not a BrowserWindow
        webPreferences: {
          nodeIntegration: true,
        },
      })
War diese Seite hilfreich?
0 / 5 - 0 Bewertungen

Verwandte Themen

rhnorskov picture rhnorskov  ·  3Kommentare

sindresorhus picture sindresorhus  ·  3Kommentare

etiktin picture etiktin  ·  3Kommentare

jviotti picture jviotti  ·  3Kommentare

cniaulin picture cniaulin  ·  3Kommentare