Typically, in an Electron app, you can require
node modules from both the main process and the renderer process:
var myModule = require('my-module');
However, this doesn't seem to work if the page was loaded via HTTP instead of from the local filesystem. In other words, if I open a window like this:
win.loadURL(`file://${__dirname}/index.html`);
I can require
a node module without problems. But if I instead open a window like this:
win.loadURL(`http://localhost:1234/index.html`);
I no longer can require
node modules inside my web page - I get Uncaught Error: Cannot find module 'my-module'
in the web page's console. Is there any way to use node modules in an Electron page that was served over HTTP?
A little context: My company is building an application that needs the ability to be hosted as a web application and inside an Electron shell. To make this simpler and consistent across both environments, my Electron app starts a local web server and opens the app hosted at http://localhost:1234
. Now I'd like the ability to add spell checking/spelling suggestions into the application using electron-spell-check-provider
. This module needs to be imported and initialized inside the renderer process, so I'm trying to require('electron-spell-check-provider')
inside my web page, but this fails with the Cannot find module
error.
Finally figured this out. In the main process, figure out the absolute path to the node_modules directory, as in:
var nodeModDir = require.resolve('some-valid-module');
var dirnm = 'node_modules';
var pos = nodeModDir.lastIndexOf(dirnm);
if(pos != -1)
nodeModDir = nodeModDir.substr(0, pos+dirnm.length+1);
Now get this path to the renderer process via some IPC. Finally, in the renderer you can now require using an absolute path:
var mymod = require(nodeModDir+'some-valid-module');
Works perfectly for me with electron 1.6.7.
You can add a preload-script which adds a property to the global/window variable. I named mine appRoot
. appRoot
just has the __dirname
value of the preload-script. You then have to go from the folder of the preload-script to your module. I simply use path.join()
to make it clean.
This is similar to @logidelic's approach, but without having to mess with IPC messages.
mainWindow = new BrowserWindow({
webPreferences: {
preload: 'preload.js'
}
})
global.appRoot = window.appRoot = __dirname
<script>
const { join } = require('path')
require(join(appRoot, 'rendererApp'))
</script>
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With