跳到主要内容

Electron 自定义协议

· 阅读需 1 分钟
阿飞
阿飞

注册自定义协议,使用 loadURL 加载静态文件。

项目结构

|   package.json
| ---app
| | main.js
| | preload.js
| \---renderer
| index.html
| renderer.js
| styles.css
Electron 版本

本文基于 electron@37.2.3

app/main.js

const { app, BrowserWindow, protocol, net } = require("electron");
const path = require("node:path");
const url = require("node:url");

function createWindow() {
const mainWindow = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
preload: path.join(__dirname, "preload.js"),
},
});
mainWindow.loadURL(`app://renderer/index.html`);
}
// 首先声明自定义协议
protocol.registerSchemesAsPrivileged([
{
scheme: "app",
privileges: {
standard: true,
secure: true,
supportFetchAPI: true,
corsEnabled: true,
stream: true,
},
},
]);

app.whenReady().then(() => {
// 处理协议
protocol.handle("app", (request) => {
const filePath = request.url.slice("app://".length);
// mainWindow.loadURL(`app://index.html`) -> filePath = index.html/ 引起错误,需要再处理
return net.fetch(url.pathToFileURL(path.join(__dirname, filePath)).toString());
});

createWindow();

app.on("activate", function () {
if (BrowserWindow.getAllWindows().length === 0) createWindow();
});
});

app.on("window-all-closed", function () {
if (process.platform !== "darwin") app.quit();
});

处理协议 TIP

使用 URL 解析

protocol.handle("app", (request) => {
const filePath = request.url.slice("app://".length);
return net.fetch(url.pathToFileURL(path.join(__dirname, requestUrl.host, requestUrl.pathname)).toString());
});

使用 URL 解析可以处理 hash 路由文件, 如 app://renderer/index.html#about

SPA history 路由

需要像服务器一样重定向处理, 否则会报 404

app://renderer -> app://renderer/index.html
app://renderer/* -> app://renderer/index.html