介绍
Neutralinojs 是一个轻量级、跨平台 的桌面应用开发框架,让你使用熟悉的 Web 技术(HTML、CSS、JavaScript)构建桌面应用。相比 Electron,它最大的优势是极小的体积 (空项目仅 ~2MB)和毫秒级构建速度。
1. 架构哲学:与 Electron 的本质区别
┌────────────────────────────────────────────────────────┐
│ Electron 架构(重型) │
│ ┌─────────────┐ ┌─────────────┐ ┌─────────────────┐ │
│ │ Chromium │ │ Node.js │ │ 你的应用代码 │ │
│ │ (~100MB) │+ │ (~30MB) │+ │ (~1MB) │ │
│ └─────────────┘ └─────────────┘ └─────────────────┘ │
│ ↓ 打包后 ~150MB+ │
└────────────────────────────────────────────────────────┘
┌────────────────────────────────────────────────────────┐
│ Neutralinojs 架构(轻量) │
│ ┌──────────────────┐ ┌──────────────────────────┐ │
│ │ 系统原生 WebView │ │ 你的应用代码 │ │
│ │ (操作系统自带) │ + │ (~2MB 起步) │ │
│ │ Windows: WebView2│ │ │ │
│ │ macOS: WKWebView │ │ │ │
│ │ Linux: WebKitGTK │ │ │ │
│ └───────────────────┘ └───────────────────────────┘ │
│ ↓ 打包后 ~2MB+ │
└───────────────────────────────────────────────────────┘
核心差异:Electron 捆绑 Chromium + Node.js,Neutralinojs 复用操作系统自带的 WebView 运行时。
2. 运行时架构详解
2.1 双进程模型
┌─────────────────────────────────────────────────────────┐
│ 用户桌面环境 │
│ ┌─────────────────┐ ┌─────────────────────────┐ │
│ │ WebView 窗口 │◄────►│ Neutralino 进程 │ │
│ │ (前端渲染层) │ │ (原生能力层/后端) │ │
│ │ │ │ │ │
│ │ • HTML/CSS/JS │ │ • 文件系统访问 │ │
│ │ • 用户界面渲染 │ │ • 系统对话框 │ │
│ │ • 事件处理 │ │ • 操作系统 API │ │
│ │ │ │ • 硬件接口 │ │
│ └─────────────────┘ └─────────────────────────┘ │
│ ▲ ▲ │
│ │ WebSocket 通信 │ │
│ └──────────────────────────┘ │
│ (localhost 随机端口) │
└─────────────────────────────────────────────────────────┘
2.2 通信机制:WebSocket 消息总线
Neutralinojs 使用 WebSocket 作为前后端通信桥梁,而非 Electron 的 IPC 机制:
javascript
// 前端代码 (resources/js/main.js)
// 这个函数调用实际被序列化为 WebSocket 消息
await Neutralino.filesystem.readFile('/path/to/file');
// 实际发生的通信流程:
// 1. 前端: 发送 JSON 消息 { method: "filesystem.readFile", params: [...] }
// 2. 后端: 执行原生操作,返回结果
// 3. 前端: Promise resolve 返回数据
消息格式示例:
json
// 请求
{
"id": "msg_001",
"method": "os.showMessageBox",
"params": ["标题", "内容", "OK", "INFO"]
}
// 响应
{
"id": "msg_001",
"result": "OK",
"error": null
}
3. 原生能力实现原理
3.1 后端实现:C++ 核心 + 平台抽象层
neutralinojs/bin/
├── neutralino-win.exe # Windows 版本 (MSVC/MinGW)
├── neutralino-mac # macOS 版本 (Clang + Cocoa)
└── neutralino-linux # Linux 版本 (GCC + GTK/WebKitGTK)
核心模块架构:
┌─────────────────────────────────────────┐
│ 应用入口 (main.cpp) │
└─────────────────────────────────────────┘
│
┌──────────────┼──────────────┐
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌──────────────┐
│ 服务器层 │ │ WebView │ │ 平台抽象层 │
│(WebSocket│ │ 封装层 │ │ (Platform │
│ Server) │ │ │ │ Abstraction) │
└────┬───┘ └────┬───┘ └──────┬───────┘
│ │ │
│ ┌───────┴──────┐ │
│ ▼ ▼ ▼
│ ┌────────┐ ┌────────┐ ┌────────┐
└►│ Router │ │ Windows│ │ macOS │
│(API路由)│ │ 实现 │ │ 实现 │
└────┬───┘ └────────┘ └────────┘
│
┌────┴────┐
▼ ▼
┌───────┐ ┌────────┐
│文件系统│ │ 系统UI │
│ API │ │ API │
└───────┘ └────────┘
3.2 WebView 技术栈选择
| 平台 | WebView 实现 | 技术基础 |
|---|---|---|
| Windows | WebView2 | Microsoft Edge (Chromium) |
| macOS | WKWebView | Safari (WebKit) |
| Linux | WebKitGTK | WebKit2 |
cpp
// 伪代码:平台抽象层示例
class WebView {
public:
virtual void navigate(const std::string& url) = 0;
virtual void setTitle(const std::string& title) = 0;
virtual void setSize(int width, int height) = 0;
};
// Windows 实现
class WebView2Impl : public WebView {
ICoreWebView2* webview; // Edge WebView2 COM 接口
public:
void navigate(const std::string& url) override {
webview->Navigate(toWideString(url).c_str());
}
};
// macOS 实现
class WKWebViewImpl : public WebView {
WKWebView* webview; // Cocoa WKWebView
public:
void navigate(const std::string& url) override {
[webview loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@(url.c_str())]]];
}
};
4. 资源加载与打包机制
4.1 开发模式 vs 生产模式
开发模式 (neu run):
┌─────────────┐ ┌─────────────┐ ┌─────────────┐
│ WebView │────►│ 本地服务器 │────►│ resources/ │
│ 窗口 │ │ (localhost) │ │ 目录(原始文件)│
└─────────────┘ └─────────────┘ └─────────────┘
生产模式 (neu build):
┌─────────────┐ ┌─────────────────┐
│ WebView │────►│ resources.neu │
│ 窗口 │ │ (ZIP 压缩资源包) │
└─────────────┘ └─────────────────┘
│
▼
┌───────────────┐
│ 内存中解压 │
│ 虚拟文件系统 │
└───────────────┘
4.2 resources.neu 文件格式
javascript
// neutralino.config.json 中的资源配置
{
"cli": {
"resourcesPath": "/resources/",
"clientLibrary": "/resources/js/neutralino.js",
"binaryVersion": "5.6.0",
"clientVersion": "5.6.0"
}
}
打包过程:
neu build将resources/目录压缩为 ZIP 格式- 重命名为
resources.neu(实质是 ZIP) - 运行时通过虚拟文件系统读取,无需解压到磁盘
5. 安全模型
5.1 权限白名单机制
不同于 Electron 的完全信任模型,Neutralinojs 采用显式权限声明:
json
// neutralino.config.json
{
"nativeAllowList": [
"app.*", // 允许所有 app 命名空间 API
"os.getEnv", // 仅允许获取环境变量
"filesystem.readFile", // 仅允许读文件
"filesystem.writeFile" // 仅允许写文件
],
"nativeBlockList": [
"os.execCommand" // 显式禁止执行系统命令
]
}
安全层级:
┌─────────────────────────────────────┐
│ Level 3: 用户确认 (对话框、通知) │
│ Level 2: 文件系统 (受限路径访问) │
│ Level 1: 系统信息 (环境变量、平台信息) │
│ Level 0: 应用控制 (退出、重启) │
└─────────────────────────────────────┘
5.2 通信安全
- 开发模式 :WebSocket 使用
localhost+ 随机端口,外部不可访问 - 生产模式 :WebSocket 服务器仅绑定
127.0.0.1,拒绝远程连接 - CSP 保护:默认启用内容安全策略,防止 XSS
6. 扩展机制:突破 JavaScript 限制
对于需要高性能或系统级操作的场景,Neutralinojs 支持扩展(Extensions):
┌─────────────────────────────────────────┐
│ Neutralino 主进程 │
│ ┌─────────────┐ ┌─────────────┐ │
│ │ WebSocket │ │ 扩展管理器 │ │
│ │ 服务器 │◄──►│ (Extension │ │
│ │ │ │ Manager) │ │
│ └──────┬──────┘ └──────┬──────┘ │
│ │ │ │
│ │ ┌──────────────┼──────────┐ │
│ │ ▼ ▼ ▼ │
│ │ ┌────────┐ ┌────────┐ ┌────────┐
│ └►│前端代码│ │ Python │ │ Rust │
│ │(JS/TS) │ │ 扩展 │ │ 扩展 │
│ └────────┘ └────────┘ └────────┘
│ │ │
│ ▼ ▼
│ ┌────────┐ ┌──────────┐
│ │ 机器学习 │ │ 系统底层 │
│ │ 库调用 │ │ 操作 │
└─────────────────────────────────────────┘
扩展通信协议:
javascript
// 前端调用扩展
await Neutralino.extensions.dispatch('python-ext', {
method: 'predict',
data: [1, 2, 3, 4]
});
7. 启动流程详解
用户双击应用
│
▼
┌────────────────┐
│ 加载二进制文件 │
│ (neutralino-*) │
└──────┬─────────┘
│
▼
┌───────────────┐
│ 解析配置参数 │
│ (config.json) │
└──────┬────────┘
│
▼
┌───────────────┐ ┌───────────────┐
│ 初始化WebSocket│◄──►│ 加载资源 │
│ 服务器 │ │ (resources.neu │
│ (localhost) │ │ 或开发目录) │
└──────┬────────┘ └───────────────┘
│
▼
┌─────────────┐
│ 创建WebView │
│ 窗口并导航 │
│ 到入口页面 │
└──────┬──────┘
│
▼
┌───────────────────┐
│ 前端代码执行 │
│ (加载neutralino.js│
│ 建立WS连接) │
└───────────────────┘
│
▼
┌─────────────┐
│ 应用就绪 │
│ (ready事件) │
└─────────────┘
8. 性能对比数据
| 指标 | Neutralinojs | Electron | 优势 |
|---|---|---|---|
| 空项目体积 | ~2MB | ~150MB | 75x 更小 |
| 内存占用 | ~50MB | ~300MB | 6x 更少 |
| 冷启动时间 | <100ms | ~3s | 30x 更快 |
| 构建时间 | 毫秒级 | 分钟级 | 瞬时构建 |
| 更新包大小 | ~2MB | ~100MB | 增量更新友好 |
9. 设计哲学总结
| 原则 | 实现方式 |
|---|---|
| 最小化捆绑 | 复用系统 WebView,不携带浏览器内核 |
| 零依赖运行时 | 仅依赖系统已存在的共享库 |
| 原生优先 | 使用平台原生 UI 组件(对话框、菜单) |
| 安全默认 | 白名单权限,最小暴露攻击面 |
| Web 标准 | 不修改浏览器行为,纯标准 Web 技术 |
| 语言无关扩展 | 通过 WebSocket 支持任意语言扩展 |
Neutralinojs 的核心创新在于:它不是一个"浏览器+Node"的打包工具,而是一个"WebView 容器 + 原生桥接"的轻量级框架。这使得它在保持 Web 开发体验的同时,实现了接近原生应用的资源效率。