Modules are not importing inside render process in electron - javascript

I Am trying to create run a python script and show the data in the HTML view.
const {PythonShell} = require('python-shell')
alert('Hello')
I have written this code inside the render process. I have connected this js file with my HTML page
Problem
The alert function is not getting executed, I suppose that python-shell is not getting imported, because it is running when I am deleting the import statement.

It looks like you are attempting to run a node package in a renderer process. By default Electron does not have node enable for renderer processes (browser windows).
You can enable it by modifying your BrowserWindow configuration.
new BrowserWindow({
// your window configuration
webPreferences: {
nodeIntegration: true
}
});
Reference: https://www.electronjs.org/docs/api/browser-window
Please note this feature is not enabled by default for security reasons. I recommend reading the security documentation to see if access to node in the renderer process will be secure for your use case.
Security Reference: https://www.electronjs.org/docs/tutorial/security

Related

How to use Node Modules in Electron React App

I am currently making a desktop application that is a ReactJS application bundled or built with Electron and I want to use node modules that come with electron in my app, specifically exec or spawn from the child process module. My goal is to have a button press that executes a set of commands from command prompt as a sub/side process and return the stdout.
My app follows the typical app creation process as the tutorials online for first making a react app, get some dependencies and package.json alterations, get electron, make an electron.js or main.js type of file with all the basic window configs in it.
In the main entry point file, for me that is electron.js, I have:
webPreferences: {
nodeIntegration: true
},
However, I cannot use the child process node module in my react code even though I have allowed it in the create window function on electron's side. In my react component, when I do
import { exec } from 'child_process';
react seems to recognize it and displays all the exec function information when hovered over (parameters, overloads, found in child_process module, etc).
However, if I run the this example command from a button click, I get the error:
"TypeError: Object(...) is not a function". Here the error is referring to exec.
import { exec } from 'child_process';
...
const run = () => {
exec('ls -lh', (error, stdout, stderr) => {
if (error) {
console.log(`error123: ${error.message}`);
return;
}
if (stderr) {
console.log(`stderr123: ${stderr}`);
return;
}
console.log(`stdout:\n${stdout}`);
})
};
....
return (
<div>
<button onClick={run}>Run Command!</button>
</div>
)
export ....
Does anybody know how to give the react side access to the node modules within the directory or how to import/access them correctly, either directly from the react side or maybe pass them from electron to react? Or maybe I am just running it incorrectly? I am new to javascript and stuff in general so understanding the issue and debugging is really hard for me.
Thanks to Badal for putting me in the right direction.
The answer I found involves setting contextisolation to false, nodeIntegration to true, and using the ipcMain handler (electron main process) and ipcRenderer handler (rendering, in this case react, process). The first link below shows how to use the handlers (look at the newer answers in the thread) and the second link is more detailed documentation on the inner workings. Note that if you search this 'node modules in react electron app' online, a lot of people are using remote, etc. but electron.remote is for the most deprecated at v12 or 13 and onwards, using it and other deprecated modules WILL NOT tell you its deprecated. Instead it will give the fs.filereadsync or wtvr error (I forgot) because it will not be able to understand it during building. The handlers for ipcMain and ipcRenderer handle all app internal communication and processes now, as the name ipc implies.
How to import ipcRenderer in react?
https://www.electronjs.org/docs/api/ipc-main
(new changes to electron) https://www.electronjs.org/docs/breaking-changes
With this, you can have a run button to execute a certain command and use ipcrenderer to send it to the electron side of things. In the electron side (defaults to sending to the main process file, so electron or main.js), you can import whatever node modules you want and use them. For me, I made a new file, did const {exec} = require('child process'), and then had a function which executed certain command line operations. The function call to exec was placed in the ipcMain handler.
This is insecure. For my purpose, security is not a concern, but for others it might be. Make sure to perform input cleaning and other precautions that prevent people from abusing the app and doing things like making calls without proper handles that can infiltrate the system. If you are using child process, OS subsystem modules, etc. this is especially important. As long as the front end can abstract the nature of how the internal communication is performed, that should be a good start.
Electron, as a framework, is highkey changing very fast. If you want to do well in creating applications with it, I highly recommend staying very attentive with version changes. I am new to it, and through my search on this matter and more, I have seen many small but major changes to how electron's internal process works and a lot of search results yield deprecated/outdated information.
It is preferred to access Node APIs from the Main process. Hence, you need to communicate from the Renderer to the Main process to execute such actions.
To access Node APIs from the Renderer process, you also need to set contextIsolation to false along with nodeIntegration set to true. This is again very insecure, to do because
..it helps prevent the website from accessing Electron internals or the powerful APIs your preload script has access to. [1]
So try to avoid doing in production, as for development you are free to experiment.
Reference:
[1] https://www.electronjs.org/docs/tutorial/context-isolation

How to get node into other .js files other than index.js in electron

I'm trying to get node into other .js files, other than just index.js. I can only run require() in index.js, and that's not useful when trying to use electron-prompt. any help?
In the future, providing the specific packages you want to use might allow for a more specific fix, however, as a general overview.
In electron you can change the node integration settings when you create your browser window using the code block below. This isn't recommended as it poses a security risk when running remote code. If you don't care about security(which you should) you can go ahead and use this.
app.on('ready', () => {
mainWindow = new BrowserWindow({
webPreferences: {
nodeIntegration: true
}
});
});
If you do care about security, I would check out the second answer to this post:
Electron require() is not defined

Make webpack ignore a certain import

I'm trying to create a desktop app using ElectronJS and ReactJS.
The renderer process is bundled using webpack, since i'm using JSX in it.
When I try to import anything from electron (e.g. import electron from 'electron';, or const electron = require('electron');) in the renderer process I get these 2 errors when I either try to build it with webpack (the web part), or when I use webpack-dev-server and open the localhost URL in electron:
https://pastebin.com/WdkCcPzm
Note that I'm not using create-react-app, that bundle.js is webpack's output, App.jsx is the file I'm trying to import electron from, that I want to import electron to access the ipcRenderer variable and that I'm not attempting to import fs from the renderer process (or from the main process for that matter).
A solution I found was to bypass webpack's packing by adding this line to my index.js
eval('window.Electron = require("electron")');
and accessing electron though the variable Electron (the capital E is because vs code recognizes that as a namespace even though electron isn't imported, and thus I still get code completion)
But that's really ugly and I was hoping there was another solution.
To build bundles for the renderer process of Electron apps, webpack provides a special target parameter.
Add this to your webpack config:
target: 'electron-renderer'
See documentation: https://webpack.js.org/configuration/target/

JS - creating new worker causes 404

I'm using Worker API to create new worker, it's as simple as:
var myWorker = new Worker('src/worker.js');
Unfortunately I'm using webpack to build my project and linking to src/worker.js returns 404.
How can I use it to create my Worker?
import hardWorker from './src/hardWorker.js';
var myWorker = new Worker(HOW TO PUT HARDWORKER HERE?);
Try using the worker-loader plugin for webpack, which can be found here: https://github.com/webpack-contrib/worker-loader
This registers scripts loaded through it as a Web worker, and bundles all of your workers in the main bundle that webpack creates. Using it in your app is as simple as this:
import MyWorker from 'worker-loader!./Worker.js';
const worker = new MyWorker();
Or you can add loader configuration parameters to your webpack.config so all files matching a specific pattern are loaded and registered as workers. The worker-loader has an example of this.
The issue is that the worker API expects a URL to load the work script from and webpack tries to bundle everything into a single file, meaning the src/worker.js file isn't where it needs to be when the browser tries to load it.
There are a couple options.
You could manually copy the worker.js file to wherever the build is trying to load the file from.
You could set up webpack to copy the file to the right location using the CopyWebpackPlugin.
Depending on how complicated your worker is, you could just put the code in a string and create an object URL so the browser doesn't have to load anything from the server at all. This is an approach I've used in the past and have written a helper library for to Workers a little easier to use.
Hope that helps!

Passing data between javascript

Want to link one javascript file in index and exports it function to another javascript file
Index.html
<script src="test.js"></script>
test.js
var config = {};
config.server_ip = "127.0.0.1";
module.exports = config; //Error, module not defined
console.log("Hello World, I should be showing up in chrome console");
show.js
var config = require('./test');
console.log(config);
I want to run index.html and at the same time using node.js to run my show.js file.
Apparently I can only choose one, if I do not export, my console.log works, if i export, my console.log do not work.
Is there any other method to pass data like this?
Do note that the workflow has to be like this, and I do not want to link 2 javascript file into my index.html
I tried using import and export function via mozila guide, however it seems that chrome does not support that as well.
I want to run index.html and at the same time using node.js to run my show.js file.
If you want to use NodeJS to run the JavaScript, then you have to actually run it on NodeJS.
If you are loading the script through a <script> element in an HTML document then you are running it in the browser and not NodeJS (it is possible that you are using NodeJS to run a webserver that supplies the .js file to the browser as a static file, but that isn't the same as running it on NodeJS).
console.log("Hello World, I should be showing up in chrome console");
If you want to display something in the Chrome console then you need to run it browser-side and not in NodeJS.
Browsers don't have native support for AMD style modules, so to use the approach you are taking you would need to add something like RequireJS.

Categories

Resources