require() node module from Electron renderer proce

2019-06-17 01:47发布

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.

3条回答
疯言疯语
2楼-- · 2019-06-17 02:17

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.

查看更多
孤傲高冷的网名
3楼-- · 2019-06-17 02:22

Was having a similar issue. Try serving renderer.js over HTTP in your index.html like so,

  <script src="/renderer.js"></script>
</body>

Then, as per the docs, load your module in using the adding remote after the require in your renderer.js file.

var spellCheck = require('electron-spell-check-provider').remote;

查看更多
地球回转人心会变
4楼-- · 2019-06-17 02:37

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.

main.js

mainWindow = new BrowserWindow({
  webPreferences: {
    preload: 'preload.js'
  }
})

preload.js:

global.appRoot = window.appRoot = __dirname

index.html:

<script>
  const { join } = require('path')
  require(join(appRoot, 'rendererApp'))
</script>
查看更多
登录 后发表回答