Electron: Exiger un électron en dehors de main.js provoque une TypeError

Créé le 22 sept. 2016  ·  82Commentaires  ·  Source: electron/electron

  • Version électronique : 1.3.5
  • Système d'exploitation : Mint 17

Bonjour

J'utilise Electron avec React.js et babelify, entre autres plugins (liste en bas).
Tenter d'utiliser require('electron') , par exemple pour accéder au BrowserWindow d'électron, entraîne l'affichage de l'erreur suivante sur la console :
index.js:4 Uncaught TypeError: fs.readFileSync is not a function

Je peux cependant utiliser const electron = require('electron'); dans main.js. Pour ce que ça vaut, j'utilise également watchify pour tout emballer dans un bundle js.

Voici la liste complète des dépendances dans mon 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 ❌

Commentaire le plus utile

Pour toute personne rencontrant ce problème à l'avenir et lisant ce fil, utiliser window.require au lieu de require est une possibilité d'éviter le conflit entre la fonction require d'électron et celle de browserify.

Tous les 82 commentaires

index.js:4 TypeError non intercepté : fs.readFileSync n'est pas une fonction

Pouvez-vous inclure la ligne 4 de index.js ici ? Ou une trace de pile plus complète ?

Je crois qu'il fait référence à index.js d'électron, qui est lui-même situé dans les modules-nœuds du projet. Voici le contenu de ce fichier :

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

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

L'intégralité de la trace de la pile suggère un conflit avec React.js :

Stack trace

Que se passe-t-il si vous exécutez require('fs').readFileSync depuis l'onglet Console des outils de développement ?

Il semble que le module de nœud electron-prebuilt (le fichier que vous avez collé) se retrouve dans votre application packagée, ce que je ne pense pas que vous vouliez car il devrait utiliser le requis electron intégré à la place.

@nukeop Comment lancez-vous votre application. Votre script de démarrage devrait ressembler à.

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

J'ai l'impression que vous essayez d'exécuter votre main.js avec node

node main.js

Qui ne fonctionnera pas

Que se passe-t-il si vous exécutez require('fs').readFileSync depuis l'onglet Console des outils de développement ?

Juste après la génération de cette erreur, je peux exécuter require('fs').existsSync dans la console pour imprimer une définition de la fonction. Cela fonctionne également avant l'erreur.

Il semble que le module de nœud pré-construit par électrons (le fichier que vous avez collé) se retrouve dans votre application packagée, ce que je ne pense pas que vous vouliez car il devrait utiliser l'électron intégré à la place.

J'ai une instance watchify qui s'exécute en arrière-plan pendant que je développe et qui met continuellement à jour mon package. Je l'ai défini dans la section scripts de package.json comme ceci :

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

Des conseils pour éviter de regrouper electron-prebuilt ?

@nukeop Electron prend en charge les besoins en interne, vous n'avez donc pas besoin d'utiliser browserify.

Autant que je sache, si vous souhaitez utiliser browserify, vous devez exclure "electron".

Intéressant, se pourrait-il que watchify/browserify gâche cela ? Cela a bien fonctionné jusqu'à présent.

Maintenant, je ne sais pas comment exécuter le programme sans lui.

Littéralement juste courir

electron .

À partir de votre dossier d'application principal, vous n'avez pas besoin de regrouper quoi que ce soit lorsque vous utilisez Electron car il dispose d'un environnement de nœud complet en interne.

_Je vais fermer ceci car il s'agit d'un problème de Browserify_

C'est ce que j'ai fait depuis le début, emballer le programme dans un seul fichier .js, qui est inclus dans un simple fichier html avec :

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

Et tout fonctionne, sauf lorsque j'utilise require. Il s'agit d'un problème d'interaction entre les deux modules.

Si je ne regroupe pas l'ensemble du programme dans un bundle, je n'ai pas de moyen simple de l'exécuter, car mon main.js ne fait que démarrer electron et charge le fichier html qui inclut le bundle.

@nukeop Le processus de rendu à l'intérieur d'Electron a également accès à un environnement complet de nœud/commonjs, vous n'avez donc pas besoin de regrouper quoi que ce soit.

Si je ne regroupe pas l'ensemble du programme dans un bundle, je n'ai pas de moyen simple de l'exécuter, car mon main.js ne fait que démarrer electron et charge le fichier html qui inclut le bundle.

Je ne suis pas sûr de comprendre ici, tout script que vous chargez dans votre fichier HTML a un environnement commonjs complet et peut donc utiliser require pour charger des fichiers supplémentaires sans rien modifier dans le navigateur

Pour toute personne rencontrant ce problème à l'avenir et lisant ce fil, utiliser window.require au lieu de require est une possibilité d'éviter le conflit entre la fonction require d'électron et celle de browserify.

FWIW, j'ai rencontré le même problème en essayant d'utiliser electron dans le processus de rendu avec create-react-app qui utilise webpack dans le backend au lieu de browserify. window.require semble le résoudre pour moi aussi bien que je ne sache pas tout à fait pourquoi.

Edit : j'ai compris pourquoi :-) Nous voulons require electron pendant l'exécution à partir de l'environnement nodejs fourni à l'exécution plutôt que l'environnement nodejs utilisé lors de la compilation par webpack. Par défaut, les globals sont liés à window et la compilation Webpack ignore le global window - donc window.require fonctionne.

Une autre façon de dire à Webpack d'ignorer un nom global consiste à utiliser un commentaire comme /*global Android*/ dans le fichier JS. Dans un autre projet utilisant l'application construite par CRA dans une WebView Android, j'ai utilisé ce qui précède pour accéder à un objet Java exposé à JS via l'interface JavaScript fournie par Webview.

@nukeop - merci pour votre dernier message ; Cela m'a beaucoup aidé. window.require a fonctionné pour moi.

oui, j'ai corrigé mon problème de création d'application de réaction / webpack.
monnaie

import electron, { ipcRenderer } from 'electron'

à

const electron = window.require("electron")

@srinathh comment exposez-vous/chargez-vous votre application CRA en tant que moteur de rendu dans votre main ? construisez-vous en premier (et modifiez-vous les chemins de ressources statiques html)

Oui, mon flux de travail consiste actuellement à exécuter npm run build à l'aide des scripts CRA, puis à exécuter la sortie dans le dossier build avec electron. Vous n'avez pas besoin de modifier manuellement les chemins d'accès aux ressources statiques. Dans les package.json pour les scripts CRA, il vous suffit de définir le homepage comme ceci et les chemins seront correctement définis.

    "homepage": "./"

De plus, j'ai main.js et package.json pour l'application électronique dans le dossier public . Ainsi, l'exécution de la construction les copie automatiquement et vous pouvez simplement exécuter electron build/ pour démarrer votre application.

En fait, j'aimerais pouvoir faire le npm start avec l'électron pour le développement, mais je n'ai pas trouvé le moyen de le faire fonctionner. Je suppose que je vais devoir faire un eject et modifier le script à la main.

Si vous souhaitez voir un exemple de configuration, jetez un œil à https://github.com/srinathh/snippetfu

Je n'utilise pas Electron, mais Node-Webkit (nw.js).
L'utilisation window.require a également résolu mon problème. Merci beaucoup pour cela !

@nukeop window.require a fait l'affaire pour moi aussi merci beaucoup ! 🎉

@nukeop J'ai eu la même erreur, mais elle est résolue window.require trick, merci beaucoup !

window.require a résolu le problème de fs.existsSync is not a function mais cela a conduit à une autre erreur : window.require n'est pas une fonction. Comment vais-je le résoudre ?

@steric85 utilisez-vous browserify, babel ou webpack ? vous devrez peut-être transpiler votre code

@Alxmerino J'utilise webpack.

assurez-vous de compiler votre code

@steric85 , j'ai fait face au window.require is not a function en tapuscrit, j'ai réussi à le réparer de cette façon :

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

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

J'utilise la méthode ci-dessus pour accéder à ipcRenderer à partir d'électron dans mon application Angular, mais la détection de changement angulaire ne fonctionne pas lorsque je mets à jour un Observable à l'aide d'un gestionnaire de messages ipcRenderer.
Est-ce parce qu'Angular ne sait pas qu'ipcRenderer est un EventEmitter et qu'il doit exécuter la détection de changement lorsque des événements ipcRenderer arrivent ?

dans Angular 2, j'avais l'habitude d'appeler applicationRef.tick() pour dire explicitement à angular de rafraîchir son état. https://angular.io/api/core/ApplicationRef

Je suis confronté à un problème très similaire à @nukeop et @srinathh : j'ai monté mon projet Electron + React + Webpack en suivant ce guide d'article , où l'auteur à la fin mentionne l'astuce avec window.require . J'ai seulement require('electron') deux places dans mon projet ; dans le point d'entrée d'Electron et dans une classe de contrôleur JavaScript requise par certains composants React. Dans mon fichier de point d'entrée Electron, je fais simplement const electron = require('electron'); , car il devrait être exécuté dans le processus principal (n'est-ce pas?), Et dans ma classe de contrôleur, je fais const Electron = window.require('electron').remote; suivi de const Jsonfile = Electron.require('jsonfile'); , ce qui devrait être le moyen de le faire puisqu'il s'exécute dans le processus de rendu. Mais j'obtiens la même erreur que @nukeop ("TypeError: fs.ExistsSync n'est pas une fonction") à la ligne six dans node_modules/electron/index.js qui ressemble à ceci :

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

J'ai essayé de supprimer node_modules/electron et de réinstaller.
J'utilise Electron 1.7.5 sur macOS 10.12.6 et démarre mon projet en utilisant npm run dev comme configuration dans l'article.

Mettre à jour; J'ai trouvé le require qui a causé mon erreur, j'ai essayé de faire require('electron-react-devtools') dans mon React index.js. Le changer en const ReactDevtools = Electron.require('electron-react-devtools'); a arrêté les erreurs, mais maintenant il semble que je ne peux pas appeler .inject() dans l'instance ReactDevtools ("n'est pas une fonction"), mais ce n'est peut-être pas quelque chose à discuter ici .

@ steric85 C'est parce que vous exécutez l'application dans un environnement de page Web => vous devez exécuter l'application dans un environnement Electron (environnement Nodejs)

  • require('electron') => Webpack regroupera le module électronique dans bundle.js => l'électron utilisera le module fs => Webpack ne comprend pas
  • window.require('electron') => Webpack ignorera la fonction require
  • Dans l'environnement de la page Web, window.require sera indéfini
  • Dans l'environnement nodejs, window.require fonctionnera
    => Ouvrez votre application dans la fenêtre Electron (pas dans la fenêtre du navigateur comme Chrome, Firefox, etc.

Je reçois toujours window.require is not a function . J'utilise Electron avec React Starter Kit (https://github.com/kriasoft/react-starter-kit). Tout fonctionne bien, sauf ceci.

J'ai configuré mon application Electron pour charger mon application depuis le Web, donc l'application ne s'exécute pas localement :
https://gist.github.com/holgersindbaek/68f6db82f507967a51ca75c527faeff6

Ce que j'essaie de faire, c'est d'appeler le ipcRenderer dans l'un de mes fichiers React. Je ne sais pas si c'est même possible lorsque mon application est chargée à partir du Web. Aucune suggestion?

@holgersindbaek Vous ne devriez pas afficher votre application dans un navigateur comme Chrome, Firefox, etc. Cela ne fonctionnera pas car il s'agit de l'environnement de la page Web.
Vous devriez afficher votre application dans une fenêtre Electron.

Je le suis, mais j'utilise Electron d'une manière où je charge mon application depuis le site Web à chaque lancement. Essentiellement, je montre un site Web dans mon application électronique. Voir le fichier ci-dessus. Je veux juste m'assurer qu'il n'y a vraiment rien que je puisse faire ?!

Electron peut charger n'importe quelle URL. Pour charger une URL, vous devez utiliser cette fonction mainWindow.loadURL(url)
=> Dans la vue de la fenêtre électronique, ce code URL javascript peut accéder à require, ipc, etc.

D'accord. Je vais essayer ça.

window.require sur l'électron n'a pas fonctionné, mais window.require pour fs l'a fait.

Je ne sais pas vraiment pourquoi. Mais ça marche et comme c'est un petit projet personnel je ne vais pas pousser la question.

Merci @nukeop

Salut, Ceci est mon package.json, j'utilise webpack, aucun de ceux-ci n'a résolu mon problème, quelqu'un a-t-il une solution ? Après avoir utilisé window.require, j'ai eu l'erreur "la fenêtre n'est pas définie"

'utiliser strictement';

var électron = nécessite('électron')
var app = électron.app;
var BrowserWindow = électron.BrowserWindow ;
var fenêtre principale = null ;

app.on('prêt', fonction() {
mainWindow = new BrowserWindow({largeur : 800, hauteur : 600});

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

mainWindow.webContents.openDevTools();

});

J'utilise du tapuscrit et j'ai dû utiliser

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

pour que mon moteur de rendu communique avec mon fichier main. J'espère que cela aide quelqu'un.

Cela a fonctionné pour moi.
Par exemple, si vous souhaitez exiger une télécommande, alors

déclare la fenêtre const : n'importe laquelle ;
const { remote } = window.require('électron');

Salut, merci mec.

Le dimanche 3 décembre 2017 à 21 h 29, Michael - ሚካኤል ሰልጠነ <
[email protected]> a écrit :

Cela a fonctionné pour moi.
Par exemple, si vous souhaitez exiger une télécommande, alors

déclare la fenêtre const : n'importe laquelle ;
const { remote } = window.require('électron');


Vous recevez ceci parce que vous avez commenté.
Répondez directement à cet e-mail, consultez-le sur GitHub
https://github.com/electron/electron/issues/7300#issuecomment-348801405 ,
ou couper le fil
https://github.com/notifications/unsubscribe-auth/ARDyd4c3aOkMbb058xklujMMbnmaoxKGks5s8uGVgaJpZM4KDU6t
.

@solominh Merci pour vos explications ici . Cependant, j'ai une configuration similaire à @holgersindbaek , quel environnement est un script de préchargement dans une vue Web ?

Info:

  • Mon entrée électronique s'exécute mainWindow.loadURL(url) , où url est un index.html local
  • Cet index.html a un <webview>
  • La vue Web a un champ preload qui charge inject.js, et ce script fait le window.require('electron').

Remarques:

  • Si j'utilise const electron = require('electron') , j'ai l'erreur fs.readFileSync is not a function
  • Si j'utilise const electron = window.require('electron') , j'ai l'erreur window.require is not a function .
  • inject.js est fourni via webpack (peut coller la configuration si nécessaire).

EDIT : Résolu pour moi en utilisant <webview nodeintegration="true"> et window.require. Laisser une note ici pour référence future.

window.require a fonctionné pour moi! Merci les gars!

https://imgur.com/a/ekWwD

message d'erreur dans le navigateur lorsque j'ai essayé ceci

J'ai oublié de revenir à nodeIntegration: false qui désactive même window.require().. . Erreur stupide. J'espère que cela épargnera à quelqu'un une heure de recherche.

@phil294 Merci mec ! vous avez vraiment économisé une heure de recherche.

Salut @micsel ,
J'ai inclus declare const window: any;
mais il lance une erreur de syntaxe.
Des idées pourquoi?

Ya, mettez declare const window: any; en haut, juste après où se trouvent les importations.

Si vous obtenez window.require n'est pas une fonction et que vous utilisez Angular-CLI, utilisez ce qui suit pour instancier l'interface Window :

./src/typings.d.ts

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

Ensuite, vous pouvez l'utiliser pour inclure l'électron :
const { ipcRenderer } = window.require('electron');

si vous utilisez angular 2+ dans l'application électronique, importez la bibliothèque "ngx-electron" et utilisez-la dans any.componets.ts

import { ElectronService } from 'ngx-electron';

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

J'utilise React JS avec Electron et lorsque j'exécute cette ligne dans le fil terminal, elle me fournit une erreur Erreur de type non capturée: window.require n'est pas une fonction Je n'utilise pas de tapuscrit comment déclarer la fenêtre dans React Js

Les personnes qui sont toujours confrontées au problème, faisant en quelque sorte un window.require() gâchent la cohérence de l'utilisation des instructions import dans la base de code. Une alternative simple consiste à définir votre pack Web target sur electron-renderer . Si vous utilisez Create React App , l'éjection peut être un gâchis. Par conséquent, vous pouvez utiliser ce package qui effectue le hook webpack pour vous et vous pouvez utiliser par exemple import fs from 'fs' dans vos composants React (ou tout autre module de nœud), heureusement dans votre vie :)

Sur les fenêtres avec Vue CLI 3, window.require fonctionnera mais nécessitera un chemin complet au lieu d'un chemin relatif à partir de "node_modules/".

Mais comme dans le cas de React, webpack peut être configuré correctement pour Vue en modifiant vue.config.js. "require" fonctionnera alors comme prévu.

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 (ce n'est qu'un exemple, cela fonctionnerait dans n'importe quel autre fichier vue js)

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

_Je n'ai presque pas envie d'ajouter ceci mais cela m'aurait évité une heure ou deux de débogage._

J'ai dû rm -rf node_modules && npm install pour résoudre ce problème. J'ai alors pu supprimer le window de window.require et les choses ont recommencé à fonctionner. Espérons que cela aide quelqu'un d'autre.

@cperthuis Je veux juste dire MERCI !! Hahah, je n'utilise même pas Vue, mais la pensée logique m'a amené à comprendre que je peux changer mon webpack.config.js pour avoir une propriété cible :)
image
A TRAVAILLÉ COMME UN CHARME.

Salut,

window.require fonctionne dans un environnement de serveur local de développement, mais pas dans un environnement de production après avoir créé l'application React dans un fichier HTML minifié.

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')}`)
}

Cela fonctionne avec localhost:3000 mais pas avec file://${path.join(__dirname, 'build/index.html')}

https://imgur.com/EE7jxZq

@cperthuis , votre correctif a fonctionné pour l'application CRA non éjectée en utilisant 'react-app-rewired'. Je vous remercie.
image

Avec Create-React-App 2, vous pouvez utiliser le module npm craco :

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

Changez react-scripts par craco dans votre package.json

craco.config.js

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

Et vous aurez accès à votre contexte Electron comme ça :

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

@ Maxou44 merci pour le conseil sur craco & électron. C'est juste ce dont j'avais besoin. Au cas où quelqu'un cherche un exemple...

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

@wwlib Pas de problème, content de voir que ça t'a aidé 🥳

J'ai oublié de revenir à nodeIntegration: false qui désactive même window.require().. . Erreur stupide. J'espère que cela épargnera à quelqu'un une heure de recherche.

Merci beaucoup.

Veuillez noter que si vous chargez du contenu distant, il est important de définir nodeIntegration sur false : https://electronjs.org/docs/tutorial/security#2 -disable-nodejs-integration-for-remote -contenu

Salut,
J'ai la même erreur. Lors de l'utilisation de window.require, l'erreur Uncaught TypeError: fs.readFileSync is not a function est corrigée mais j'ai trouvé une autre erreur Uncaught TypeError: window.require is not a function .

Y at-il une suggestion sur la façon de résoudre ce problème. J'utilise browserify sur node js.

Pour tous ceux qui sont encore bloqués sur ce point : vous obtiendrez l'erreur window.require is not a function moins que vous ne déclariez explicitement nodeIntergation comme true lorsque vous déclarez votre BrowserWindow :

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

La seule solution assez bonne que j'ai trouvée est la suivante:

  1. installer en tant que package de dépendance de développement react-app-rewired
  2. Utilisez ce module pour injecter une configuration Webpack personnalisée sans eject -ing le CRA :
 "scripts": {
   ...
    "start": "react-app-rewired start",
  },
  1. et ajoutez le fichier config-overrides.js avec le contenu correspondant :
module.exports = function override (config, env) {
  config.target = 'electron-renderer'
  return config;
}

Merci à : commentaire @Lilanga , commentaire @agrublev et créateurs de react -app-rewired .

Mis à jour:
En fait, la 2ème version de la procédure à suivre : https://www.codementor.io/randyfindley/how-to-build-an-electron-app-using-create-react-app-and-electron-builder-ss1k0sfer

Mis à jour2 :
@nukeop J'ai supprimé certaines déclarations trompeuses en raison du manque de temps pour suivre les débats concernant pourquoi ne pas utiliser Browserify ou pourquoi l'utiliser et je ne peux pas écrire maintenant une explication détaillée de ce que je voulais dire. Mais je garderai mon opinion personnelle sur le fait que "il suffit d'utiliser window.require pour résoudre le problème" semble très peu fiable.

Faux comment ?

C'est une application React qui doit fonctionner dans l'environnement Electron et non l'inverse

Quoi?

_Je n'ai presque pas envie d'ajouter ceci mais cela m'aurait évité une heure ou deux de débogage._

J'ai dû rm -rf node_modules && npm install pour résoudre ce problème. J'ai alors pu supprimer le window de window.require et les choses ont recommencé à fonctionner. Espérons que cela aide quelqu'un d'autre.

Wow .. J'ai TOUT essayé dans ce fil et j'ai raté votre relecture car il n'y a pas de votes positifs .. J'ai toujours window is not a function ..
supprimé et réinstallé node_modules et son fonctionnement.

PS : il faut encore faire toutes les solutions mais si tu as tout fait
et toujours la même réinstallation node_modules

Vous avez sauvé ma journée @joshuapinter !

En utilisant react-create-app, j'ai trouvé les mêmes erreurs.
La solution jusqu'à présent était:
const electron = window.require("electron") dans la partie électronique BrowserWindow ajouter nodeIntegration:true de la manière suivante.
mainWindow = new BrowserWindow({ width: 900, height: 680, webPreferences: { webSecurity: false, nodeIntegration: true } });

La seule solution assez bonne que j'ai trouvée est la suivante:

  1. installer en tant que package de dépendance de développement react-app-rewired
  2. Utilisez ce module pour injecter une configuration Webpack personnalisée sans eject -ing le CRA :
 "scripts": {
   ...
    "start": "react-app-rewired start",
  },
  1. et ajoutez le fichier config-overrides.js avec le contenu correspondant :
module.exports = function override (config, env) {
  config.target = 'electron-renderer'
  return config;
}

Merci à : commentaire @Lilanga , commentaire @agrublev et créateurs de react -app-rewired .

Mis à jour:
En fait, la 2ème version de la procédure à suivre : https://www.codementor.io/randyfindley/how-to-build-an-electron-app-using-create-react-app-and-electron-builder-ss1k0sfer

Mis à jour2 :
@nukeop J'ai supprimé certaines déclarations trompeuses en raison du manque de temps pour suivre les débats concernant pourquoi ne pas utiliser Browserify ou pourquoi l'utiliser et je ne peux pas écrire maintenant une explication détaillée de ce que je voulais dire. Mais je garderai mon opinion personnelle sur le fait que "il suffit d'utiliser window.require pour résoudre le problème" semble très peu fiable.

Cela a fonctionné pour moi. Merci

Le problème avec window.require est qu'il ne fonctionne que pour le package de niveau supérieur.
Par exemple, si j'utilise fs directement, cela fonctionne. Mais si j'utilise un package qui dépend de fs , j'obtiens toujours une exception.

window.require cela ne fonctionne pas pour moi lorsque j'appelle la fonction dans l'application React. J'ai eu "TypeError: window.require n'est pas une fonction".

App.js :
```javascript
import React, { useEffect, useState } de 'react' ;
importer './App.css' ;

const ipcRenderer = window.require('électron').ipcRenderer;

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

}

exporter l'application par défaut ;
````

Variable de la fenêtre principale sur Main.js :
```javascript
// Crée la fenêtre du navigateur.
mainWindow = new BrowserWindow({
toujours en haut : vrai,
cadre : faux,
plein écran : faux,
transparent : vrai,
titleBarStyle : 'customButtonsOnHover',
afficher : faux,
largeur : 300,
hauteur : 350,
Préférences Web : {
nodeIntegration : vrai,
préchargement : __dirname + '/preload.js'
}
});

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

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

Qu'est-ce qui me manque ?

Donc, problème résolu. Je me réponds car peut-être que quelqu'un peut en profiter (j'ai bloqué pendant des heures). Si vous avez un fichier Preload.js , vous n'avez pas besoin d'appeler à nouveau window.require('electron').ipcRenderer depuis le Àpp.js (rendu); vous appelez directement la variable comme window.ipcRenderer comme ceci :

App.js :

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

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

}

exporter l'application par défaut ;
````

Variable de la fenêtre principale sur 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;

Après avoir exécuté l'application à partir de la ligne de commande, la fenêtre générée par le processus React génère une erreur (ipcRenderer n'est pas défini). Ignorez-le. La fenêtre générée par le processus Electron (application principale) fonctionnera correctement.

Avec Create-React-App 2, vous pouvez utiliser le module npm craco :

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

Changez react-scripts par craco dans votre package.json

craco.config.js

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

J'ai eu des problèmes require("fs") ainsi que window.require("fs") . Merci à @Maxou44 pour l'introduction de CRACO dans cette discussion.

Pour résoudre le problème, j'ai apporté 3 modifications à mon projet :

  1. J'ai utilisé CRACO comme suggéré par @Maxou44.
  2. Dans public/main.js (certains auraient pu nommer ce fichier electron.js), modifié
    new BrowserWindow({ width: 1200, height: 800 })
    à
    new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true } })
  3. Remplacement const fs = require("fs") par const fs = require("electron").remote.require("fs")

Reportez-vous à ce dépôt git par @wwlib pour plus de précisions https://github.com/wwlib/cra-craco-electron-example

J'ai lu tout le fil de haut en bas et rien n'a fonctionné.
SAUF, la méthode de @Saroopashree ci-dessus. Merci @Saroopashree d'avoir partagé la solution.
Je suppose que depuis que react et webpack ont ​​quelque peu changé depuis le début du fil, les solutions ci-dessus sont obsolètes. Bien sûr, je me trompe peut-être, mais l'utilisation de la méthode ci-dessus a fonctionné.
C'est ce que j'ai fait:

  1. Couru npm install craco -D
  2. Créez le fichier de configuration craco.config.js et collez le code suivant
    module.exports = { webpack: { configure: { target: 'electron-renderer' } } };
  3. Mise à jour new BrowserWindow({ width: 1200, height: 800, webPreferences: { nodeIntegration: true } }) dans main.js. Bien sûr avec une largeur et une hauteur différentes.
  4. Couru npm start pour démarrer le serveur de développement pour l'application React créée à l'aide de create-react-app. Cela a ouvert un onglet avec les mêmes erreurs. Et je me sentais à nouveau fatigué.
  5. Ran npm run electron pour exécuter l'application électronique.
    Et Viola !!! J'ai pu voir la page.

Alors merci @Saroopashree.

Si vous essayez d'accéder à 'électron' ou à son autre composant dans un composant/classe de réaction, essayez ceci : #336757899

Merci à @tumbledwyer d'avoir publié le lien vers une solution qui fonctionne pour moi :

Mis à jour:
En fait, la 2ème version de la procédure à suivre : https://www.codementor.io/randyfindley/how-to-build-an-electron-app-using-create-react-app-and-electron-builder-ss1k0sfer

La solution de Randy Findley :
Maintenant, si vous avez besoin d'accéder au module fs comme je l'ai fait, vous rencontrerez rapidement l'erreur Module not found

Tout d'abord, installez Rescripts .

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

Ensuite, modifiez les balises de scripts dans package.json à partir de ceci...

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

pour ça

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

Ajoutez maintenant un nouveau fichier appelé .rescriptsrc.js avec le contenu suivant :

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

Ajoutez enfin un autre nouveau fichier appelé .webpack.config.js avec le contenu suivant :

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

Vous pouvez maintenant utiliser le module fs , pas de soucis.

Ce que @ledleds a souligné a fonctionné pour moi, en utilisant CRA avec typscript et Electron. Ensuite, j'ai déclaré webPreferences comme ceci:

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

cela semble donc écraser/définir nodeIntegration sur false, donc le définir sur true et relancer l'application a résolu le problème (vous devez relancer l'application afin de charger la fenêtre Electron avec cette configuration)

définir nodeIntegration sur true comme ceci

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

Pour tous ceux qui sont encore bloqués sur ce point : vous obtiendrez l'erreur window.require is not a function moins que vous ne déclariez explicitement nodeIntergation comme true lorsque vous déclarez votre BrowserWindow :

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

réagir-app-recâblé

C'était la seule bonne solution que j'ai trouvée en termes d'évolutivité, je ne pense pas que quiconque devrait se fier à window.require

Pourquoi window.require ne serait-il pas évolutif ?

Pour tous ceux qui se trouvent aux prises avec ce problème ou des problèmes similaires et qui utilisent Vue et vue-electron-builder, voir ici

Pour ceux qui ont encore des difficultés avec cela, en particulier en ce qui concerne la fermeture de l'application électronique via un bouton de réaction, veuillez lire la suite.

Ce qui m'a aidé était le suivant:

  1. Lorsque vous déclarez votre fenêtre, assurez-vous de définir nodeIntegration: true car il s'agit actuellement par défaut false pour des raisons de sécurité. Cela se fait généralement dans votre fichier electron.js .

  2. Comme @packetstracer l'a déjà mentionné : _vous devez relancer l'application afin de charger la fenêtre Electron avec cette configuration_

mainWindow = new BrowserWindow({
//...
  webPreferences: {
    nodeIntegration: true,
  },
});
  1. Également dans votre electron.js , mettez la déclaration suivante vers le haut, cela garantit que le ipcMain écoutera l'événement _"close-me"_ :
const { ipcMain } = require("electron");
ipcMain.on("close-me", (evt, arg) => {
  app.quit();
});
  1. Dans le composant de réaction où se trouve votre bouton _"fermer"_, ajoutez l'instruction window.require suivante après vos importations. L'habituel require n'a pas fonctionné :
const ipcRenderer = window.require("electron").ipcRenderer;
  1. Et pour fermer votre application, appelez la déclaration suivante. Il devrait envoyer l'événement _"close-me"_ à l'ipcMain :
<Button label="close" onClick={(e) => ipcRenderer.send("close-me")} />

N'hésitez pas à commenter et à donner votre avis, je suis encore nouveau sur Electron.
Je sais que le contexte avec le bouton Quitter n'a aucun rapport, mais je n'ai pas pu trouver de fil mieux adapté. N'hésitez pas à m'indiquer un autre sujet plus approprié s'il y en a un.

Ma config :

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

résolu pour moi !! Merci @nukeop

`
`

Est-ce que quelqu'un sait comment configurer le type approprié dans le tapuscrit?

j'ai la suite pour le moment

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

je voudrais quelque chose comme

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

afin que l'IDE sache comment compléter automatiquement l'API électronique.

@timsamart ça marche. Merci, cela me fait gagner des jours de travail. 🤣

Après avoir passé de nombreuses heures à essayer littéralement tout ce qui précède, j'ai raté la partie au cas où vous utiliseriez BrowserView , tout comme BrowserWindow vous devez activer explicitement node.js :

     new BrowserView({ // is a BrowserView not a BrowserWindow
        webPreferences: {
          nodeIntegration: true,
        },
      })
Cette page vous a été utile?
0 / 5 - 0 notes