Using Preload Scripts
Preload script란
Electron의 메인 프로세스는 운영체제에 접근 가능한 Node.js환경이다. renderer 프로세스에서는 보안상의 이유로 Node.js를 실행하지 않는다. 따라서 이를 이어주는 preload라는 스크립트가 필요하다.
// preload.js
const { contextBridge } = require("electron");
contextBridge.exposeInMainWorld("versions", {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
// we can also expose variables, not just functions
});
다음과 같이 preload.js에서 versions.node, versions.chrome, versions.electron을 노출시켰다.
// main.js
const { app, BrowserWindow } = require("electron");
const path = require("path");
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
win.loadFile("index.html");
};
app.whenReady().then(() => {
createWindow();
});
그 후 main.js에서 BrowserWindow를 만들때 webPreferences에서 preload의 path를 넣어주었다.
// renderer.js
const information = document.getElementById("info");
information.innerText = `This app is using Chrome (v${versions.chrome()}), Node.js (v${versions.node()}), and Electron (v${versions.electron()})`;
그러면 renderer.js에서 노출시켰던 versions를 사용할 수 있게 된다.
Electron의 메인 프로세스와 Renderer 프로세스는 서로 다른 역할을 하며 상호 교환할 수 없다. 즉, Renderer 프로세스에서 직접 Node.js API에 액세스하거나 main 프로세스에서 HTML DOM에 직접 액세스할 수 없다.
이를 해결하기 위해 ipcMain모듈을 사용한다. 웹페이지에서 main 프로세스에 메시지를 보내려면, main에서는 ipcMain.handle을 통해 setup하고 preload에서는 ipcMain.invoke를 통해 노출시키면 된다.
// preload.js
const { contextBridge, ipcRenderer } = require("electron");
contextBridge.exposeInMainWorld("versions", {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
ping: () => ipcRenderer.invoke("ping"),
// we can also expose variables, not just functions
});
// main.js
const { app, BrowserWindow, ipcMain } = require("electron");
const path = require("path");
const createWindow = () => {
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
ipcMain.handle("ping", () => "pong");
win.loadFile("index.html");
};
app.whenReady().then(createWindow);
// renderer.js
const func = async () => {
const response = await window.versions.ping();
console.log(response); // prints out 'pong'
};
func();