来自 Electron 渲染器进程的 require() 节点模块,通过 HTTP 提供服务

Posted

技术标签:

【中文标题】来自 Electron 渲染器进程的 require() 节点模块,通过 HTTP 提供服务【英文标题】:require() node module from Electron renderer process served over HTTP 【发布时间】:2017-01-15 04:21:51 【问题描述】:

通常,在 Electron 应用程序中,您可以在主进程和渲染器进程中 require 节点模块:

var myModule = require('my-module');

但是,如果页面是通过 HTTP 而不是从本地文件系统加载的,这似乎不起作用。换句话说,如果我打开一个这样的窗口:

win.loadURL(`file://$__dirname/index.html`);

我可以require 一个节点模块没有问题。但如果我改为打开这样的窗口:

win.loadURL(`http://localhost:1234/index.html`);

我不再可以在我的网页中使用require 节点模块 - 我在网页的控制台中获得了Uncaught Error: Cannot find module 'my-module'。有没有办法在通过 HTTP 提供的 Electron 页面中使用节点模块?


一点背景:我的公司正在构建一个应用程序,该应用程序需要能够作为 Web 应用程序在 Electron shell 中托管。为了使这两个环境更简单和一致,我的 Electron 应用程序启动了一个本地 Web 服务器并打开托管在 http://localhost:1234 的应用程序。现在我希望能够使用electron-spell-check-provider 在应用程序中添加拼写检查/拼写建议。这个模块需要在渲染器进程中导入和初始化,所以我试图在我的网页中require('electron-spell-check-provider'),但这失败了Cannot find module错误。

【问题讨论】:

我不确定,但似乎 http 版本正在为文件获取一些不同的实际路径。尝试通过以下方式更改 require 语句:=> "require('./electron-spell-check-provider')" 你试过了吗:require('electron').remote.require('electron-spell-check-provider') 您最终解决了这个问题吗? remote.require() 对我有用,但这并不总是一个好的解决方案。还有其他方法吗? 【参考方案1】:

您可以添加一个预加载脚本,该脚本将属性添加到全局/窗口变量。我将我的命名为appRootappRoot 仅具有预加载脚本的 __dirname 值。然后,您必须从预加载脚本的文件夹转到您的模块。我只是使用path.join() 让它变得干净。 这类似于@logidelic 的方法,但不必弄乱 IPC 消息。

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>

【讨论】:

这对我不起作用。这样做:``` const path = require('path') const electron = require('electron') const appPath = electron.remote.app.appPath const usb = require(path.join(appPath, 'node_modules', ' usb')) ```【参考方案2】:

终于想通了。在主进程中,找出node_modules目录的绝对路径,如:

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

现在通过一些 IPC 获取渲染器进程的路径。最后,在渲染器中,您现在可以要求使用绝对路径:

var mymod = require(nodeModDir+'some-valid-module');

electron 1.6.7 非常适合我。

【讨论】:

【参考方案3】:

遇到了类似的问题。尝试像这样在 index.html 中通过 HTTP 提供 renderer.js

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

然后,根据docs,在 renderer.js 文件中的 require 之后使用添加远程加载您的模块。

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

【讨论】:

渲染器包含什么?

以上是关于来自 Electron 渲染器进程的 require() 节点模块,通过 HTTP 提供服务的主要内容,如果未能解决你的问题,请参考以下文章

Electron进程通信

Electron 渲染进程中报错require is not defined

Electron 渲染进程主进程通信 02

在电子的渲染器进程中使用 npm 模块

安全访问渲染器进程中基于节点的模块

Electron 主进程与渲染进程通信