【问题标题】:Electron app: How do you use ipcRenderer.sendToHost()?Electron 应用程序:您如何使用 ipcRenderer.sendToHost()?
【发布时间】:2017-03-31 03:51:54
【问题描述】:

在Electrondocumentation for the webview tag中,给出了下面的例子来展示渲染器进程如何与webview中托管的网页进行通信:

通过 sendToHost 方法和 ipc-message 事件,您可以轻松地在访客页面和嵌入页面之间进行通信:

// In embedder page.
const webview = document.getElementById('foo')
webview.addEventListener('ipc-message', (event) => {
  console.log(event.channel)
  // Prints "pong"
})
webview.send('ping')

// In guest page.
const {ipcRenderer} = require('electron')
ipcRenderer.on('ping', () => {
  ipcRenderer.sendToHost('pong')
})

但是,在我的访客网页中(在 web 视图内),当我尝试 require('electron') 时,我得到了 Uncaught ReferenceError: require is not defined,如文档中所示。

我还需要做些什么才能从访客网页中获取 ipcRenderer 模块吗?

电子版: 1.4.6

注意:我不确定这是否重要,但在我的 web 视图中运行的页面是从本地服务器提供的。在渲染器进程的*页面中,我执行以下操作:document.getElementById("webview").src = "http://localhost:1234/...";

编辑:看起来从本地服务器提供我的网页并没有改变任何东西。尝试使用静态 HTML 文件后,我遇到了同样的错误。看起来文档中的示例根本不起作用,或者我理解错误。

// Simple foo.html somewhere on my computer
<script>
    const {ipcRenderer} = require('electron')
        ipcRenderer.on('ping', () => {
        ipcRenderer.sendToHost('pong')
    })
</script>

// In embedder page, in renderer process
document.getElementById("webview").src = "file://path/to/foo.html";

嵌入页面的输出(在 webview 内): Uncaught ReferenceError: require is not defined

【问题讨论】:

    标签: webview ipc electron


    【解决方案1】:

    编辑

    出于安全原因,在渲染器进程中使用require 的首选方法是使用preload 仅注入页面所需的最小节点集成。请参阅Electron's security recommendations 的第 2) 点。 ipcRenderer 的最小示例:

    // main.ts
    const mainWindow = new BrowserWindow({
      webPreferences: {
        nodeIntegration: false,
        preload: './preload.js'
      }
    })
    
    mainWindow.loadURL('https://my-website.com')
    
    // preload.js
    const { ipcRenderer } = require('electron')
    
    window.sendToElectron= function (channel) {
      ipcRenderer.send(channel)
    }
    

    您现在可以在您的网页中使用window.sendToElectron("ping")

    如果您在渲染器进程中使用&lt;webview&gt;,您可以使用&lt;webview src="page.html" preload="./preload.js" /&gt; 来获得相同的结果。所以,这就是我用来回答我最初的问题的方法,在preload.js 中,我将在全局window 中注入一个调用ipcRenderer.sendToHost("pong") 的函数。


    旧答案(不利于安全)

    我错过了 webview 文档中的一个关键点。为了能够从嵌入在 webview 中的页面调用 require,您需要在 webview 标签上设置 nodeintegration 属性:

    &lt;webview id="webview" nodeintegration /&gt;

    【讨论】:

    • 这里需要注意的是,webviews 的 nodeIntegration 是非常非常危险的。问问自己是否真的需要它。如果 webview 用于渲染外部/第 3 方内容,请不要这样做!
    • 是的,答案已经很老了。我对其进行了编辑以反映最佳做法。
    • 如果是您自己的代码在 webview 中运行,这对安全性来说还不错。