How to integrate and run existing ReactJS Application in Electron - node.js

For instance, I have an ReactJS application: https://iaya-664f3.firebaseapp.com/
You can see in the HTML source the bundle.js file.
I have tried to run this application as desktop application using Electron, which should launch this web application in chromium window but it is not working.
Following is my main React application file app.js sitting in root directory. However compiled files bundle.js and index.html are in ./public/directory.
./app.js
import React, {Component} from 'react';
import ReactDOM from 'react-dom';
import { Router, Route, browserHistory } from 'react-router';
import routes from './routes';
import {Provider} from "react-redux";
import { createStore, applyMiddleware } from 'redux';
import ReduxPromise from 'redux-promise';
import rootReducer from './reducers/index';
const store = applyMiddleware(ReduxPromise)(createStore)(rootReducer);
ReactDOM.render( <Provider store={store}>
<Router history={browserHistory} routes={routes} />
</Provider> ,
document.getElementById('react-app'));
./index.js
In this file I'm embedding my application to Electron to run in chromium.
var app = require("./app");
var BrowserWindow = require("browser-window");
// on electron has started up , booted up, everything loaded (Chromium ,goen, live)
app.on("ready", function(){
var mainWindow = new BrowserWindow({
width:800,
height:600
});
mainWindow.loadUrl("file://" + __dirname+ "/public/index.html");
});
But this give some error on import React from 'React' line in my ./app.js.
So I assume that, I should only give ./public/index.html file to load which includes the compiled bundle.js. But I wonder, how that will work as the line app.on("ready", function(){ expect an app.
Moreover I have also tried following way in ./index.js but it gives some other error.
const electron = require('electron');
// Module to control application life.
const app = electron.app;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;
const path = require('path');
const url = require('url');
// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let mainWindow;
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600});
// and load the index.html of the app.
/*mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'public/index.html'),
protocol: 'file:',
slashes: true
}));*/
mainWindow.loadURL("file://" + __dirname+ "/public/index.html");
// Open the DevTools.
mainWindow.webContents.openDevTools();
// Emitted when the window is closed.
mainWindow.on('closed', function () {
// Dereference the window object, usually you would store windows
// in an array if your app supports multi windows, this is the time
// when you should delete the corresponding element.
mainWindow = null;
});
}
app.on('ready', createWindow);
// Quit when all windows are closed.
app.on('window-all-closed', function () {
// On OS X it is common for applications and their menu bar
// to stay active until the user quits explicitly with Cmd + Q
if (process.platform !== 'darwin') {
app.quit();
}
});
app.on('activate', function () {
// On OS X it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) {
createWindow();
}
});

Basically the thing is very simple. Electron acts just like a desktop chromium wrapper, that displays your any (any) type of web page inside desktop chromium.
So for example, we want to display http://www.google.com then you simply pass this URL to your loadURL() function.
Here is the working copy of code (asked in the question):
const electron = require('electron');
// Module to control application life.
const app = electron.app;
// Module to create native browser window.
const BrowserWindow = electron.BrowserWindow;
app.on('ready', function(){
var mainWindow = new BrowserWindow({width: 800, height: 600});
mainWindow.loadURL("http://localhost:8080/"); // option1: (loading a local app running on a local server)
//mainWindow.loadURL("https://iaya-664f3.firebaseapp.com"); // option2: (loading external hosted app)
// loading developer tool for debugging
mainWindow.webContents.openDevTools();
});
I hope this will clarify the confusion for many people, who are new to Electron. So the final words are that Electron only loads existing and running web application. It does not compile, does not act as a server. It is just a box in which you can put anything and give it a desktop sort of look e.g. menues, desktop notification, local file system access, etc.

Related

Vue3 Electron get user docs folder

How can i get the user docs folder path for an electron app running on the desktop.
I've tried the following but get an error that app is undefined.
import fs from "fs";
const { app } = require("electron");
export function getFilepath() {
const filepath = app.getPath("userData") + "/settings.json";
return filepath;
}
This code lives in a helpers.js file that is being import through my electron_preload.js file.
I have no clue what or how to solve this.
import { contextBridge, ipcRenderer } from "electron";
const helpers= require("../src/helpers");
contextBridge.exposeInMainWorld("helpers", helpers);
Since you're executing the code in your preload environment, it is being run in the renderer process of the corresponding BrowserWindow. However, app is limited to the main process' execution scope (source) which is why your code throws the error.
You will have to expose the path via IPC.
// Main process, app.js or whatever
const { ipcMain, app } = require ("electron");
ipcMain.handle ("get-user-data-path", (event, ...args) => {
return app.getPath ("userData") + "/settings.json";
});
// In helpers.js
import fs from "fs";
const { ipcRenderer } = require("electron");
export async function getFilepath () {
return await ipcRenderer.invoke ("get-user-data-path");
}
For a more in-depth explanation, see the official Electron IPC tutorial.
(As a side note: I/O to the filesystem should probably be done by the main process, not the renderer. Worth considering from a security point of view.)

how to solve this error indexhtml :Uncaught ReferenceError: require is not defined in electron [duplicate]

This question already has answers here:
With contextIsolation = true, is it possible to use ipcRenderer?
(3 answers)
Closed 1 year ago.
> index.html:
As u can see in index.html code (const electron = require('electron');this require arise an error as require is not define i use window10.
<script>
const electron = require('electron');
const { ipcRenderer } = electron;
document.querySelector('form').addEventListener('submit',(event) =>{event.preventDefault();
event.preventDefault();
const file =document.querySelector('input').files[0];
});
</script>
> Main.js:
// Modules to control application life and create native browser window
const {app, BrowserWindow} = require('electron')
const path = require('path')
function createWindow () {
// Create the browser window.
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true, // is default value after Electron v5
contextIsolation: true, // protect against prototype pollution
enableRemoteModule: false, // turn off remote
preload: path.join(__dirname, "preload.js") // use a preload script
}
});
mainWindow.loadFile('index.html')
Electron is a package you should use in the nodejs environment, not in the browser. Also in the browser you can't use the require function, you should use instead the import and export syntax.
That because javascript is a script language meant to run in browsers, it doesn't make sense to require electron in your frontend script, but, since your serving your files through the electron service and not in a browser window you can access the require by calling the window.require('pckg') method, still doesn't make any sense to require electron in a client-side window tho, it's like if an express server renders a page that creates another server.
If you just want to create another window you should do that in the main electron file, in your case the Main.js file.

White Screen issue with Electron/Node app

I've recently created an app with a Java backend and a React frontend, and I was using Electron and some Node features to bundle the app and create a desktop app for it. Basically, I decided to use Java for some Java-specific libraries I needed. The app will run on port 8080, with the React/JS stuff being served from the static folder, and the Electron wrapper will use some Node libraries to start up the Java process and then after a few seconds connect to localhost:8080.
This works like a charm about half the time, and the other half instead shows me a white screen with no errors! I have debugged this countless times and the only way to fix it is to force reload the Chromium page which sometimes works, and other times doesn't. Obviously this isn't acceptable for users to do with my app. The problem is, I have run out of ideas as to what could be causing this issue.
Here is my main.js for the electron app
const {app, BrowserWindow} = require('electron')
function createWindow () {
try {
var jarPath = './app.jar';
var kill = require('tree-kill');
var child = require('child_process').spawn('java', ['-jar', jarPath, '']);
let win = new BrowserWindow({width: 1000, height: 730});
setTimeout(function() {
win.loadURL('http://localhost:8080/index.html');
}, 2000);
console.log("PID: " + child.pid);
win.on('closed', function () {
kill(child.pid);
mainWindow = null
}
)
} catch(e) {
console.log(e);
}
}
app.on('ready', createWindow)

Serve static files with express from within electron-forge app

I've written a quick Electron Forge app that simply runs an express webserver that serves static files locally. I prefer this to running a node process directly for usability.
main.js
import { app, BrowserWindow } from 'electron';
import express from 'express';
const exApp = express();
exApp.use(express.static('web-app'));
exApp.listen(3333);
let mainWindow;
const createWindow = () => {
// Create the browser window.
mainWindow = new BrowserWindow({
// ...
});
// ...
};
// ...
I use the CopyWebpackPlugin to copy the files I need to serve into the .webpack/main/web-app/ directory.
webpack.main.config.js
module.exports = {
/**
* This is the main entry point for your application, it's the first file
* that runs in the main process.
*/
entry: './src/main.js',
// Put your normal webpack config below here
module: {
rules: require('./webpack.rules'),
},
plugins: [
new CopyPlugin([
{ from: path.resolve(__dirname, 'web-app'), to: 'web-app' }
]),
]
};
This works perfectly in development (via yarn start).
When I try to run yarn make, it successfully builds the app and generates a runnable exe, but trying to access http://localhost:3333/ after running the app, results in a Cannot GET / 404 message.
Any idea what I'm doing wrong?
What I was serving in development was actually the web-app directory relative to the node process, and not the one copied into .webpack/....
To serve the proper files in production, I changed the exApp.use() line to:
exApp.use(express.static('resources/app/.webpack/main/web-app'));

Electron - "Cannot read property 'on' of undefined"; tried reinstalling,

I'm testing an electron app but I'm getting this pernicious error:
"TypeError: Cannot read property 'on' of undefined"
The research I've done pointed to either a botched module install, a syntax issue, or passing in an undefined variable to the app.on, and I suspect the issue may be Electron being pointed to incorrectly (now it's being pointed to the folder ending in electron\dist\electron.exe, which I've heard might not the right location), but I'm unsure.
Despite checking the require command, syntax, rechecking, uninstalling, and reinstalling node, I can't seem to make this darn error go away. What could be causing this?
const electron = require('electron');
const os = require('os');
const fs = require('fs');
const app = electron.app;
const BrowserWindow = electron.BrowserWindow;
var Mousetrap = require('mousetrap');
const path = require('path');
const url = require('url');
const ipc = electron.ipcMain;
let mainWindow;
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
/* More code in this and sub functions*/
}))
}
})
const preferencesManager = require('./preferencesManager');
/******
Send data to database given constructor created in preferencesManager
******/
// First instantiate the class because we want to turn the class into an object to be able to use.
const store = new Store({ //create a new getting and setting logic
//We'll call our data file 'user-preferences'
configName: 'user-preferences',
defaults: {
//800 x 600 is the default size of our window
windowBounds: { width: 800, height: 600}
}
});
// When our app is ready, we'll create our BrowserWindow
app.on('ready',function(){
//Set up a listener for what I've done in keycapture (in the renderer process)
//???
ipc.on('invokeAction', function(event, args){
/* Do some action */
});
});
You are probably trying to run your application like a node app with:
$ node index.js
The electron file is a binary file, not a JavaScript file, when you require it an run with node there will be no object to call electron.app, so it parses for null and cannot have an property. As in the getting started documento of Electron.JS you must run the application like this:
Change your package.json script session adding start:
{
"scripts": {
"start": "electron ."
}
}
Now run:
$ npm start
The code you posted has an error, witch may be an edition error while coping and pasting but it should loose some parenthesis and curly brackets:
function createWindow () {
// Create the browser window.
mainWindow = new BrowserWindow({width: 800, height: 600})
// and load the index.html of the app.
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
/* More code in this and sub functions*/
}))
}
The application should now run correctly. I tested you exact code, removing the libs I did not have and it loaded with no errors.

Resources