当前位置: 首页 > news >正文

构建Node.js单可执行应用(SEA)的方法

如果为了降低部署复杂度,可以考虑使用@vercel/ncc。除非有特别理由,不建议使用SEA。

1. 环境准备

1.1. 基础要求

  • Node.js: >= 19.0.0 (推荐最新LTS版本)

1.2. 安装依赖

npm install postject typescript

1.3. 验证环境

node -v          # 确认版本 >= 19
tsc -v           # 确认TypeScript已安装
postject --help  # 确认命令可用

2. 项目初始化

2.1. 目录结构

mkdir -p sea-demo/{src,bin,build}
cd sea-demo
npm init -y

2.2. 示例代码

创建src/cli.ts:

#!/usr/bin/env nodefunction main() {console.log("Hello from SEA!");
}main();

3. 构建配置

3.1. 配置tsconfig.json

nodejs内置模块很多还在使用commonjs,统一使用commonjs可以避免很多麻烦。

{"compilerOptions": {"target": "es2020","module": "commonjs","outDir": "bin","esModuleInterop": true,"strict": true}
}

3.2. 配置 sea-config.json

{"main": "bin/cli.js","output": "build/sea-prep.blob","disableExperimentalSEAWarning": false,"useSnapshot": false,"useCodeCache": true
}

4. 完整构建流程

4.1. 编译阶段

# 编译TypeScript
tsc

4.2. 生成SEA Blob

node --experimental-sea-config sea-config.json

4.3. 准备可执行文件

# 获取Node路径
NODE_PATH=$(which node)# 复制并重命名
cp $NODE_PATH build/sea-demo

4.4. 注入Blob

# 获取当前Node版本的FUSE值
# 有些版本nodejs无法通过下面的命令获取FUSE值,可以在网上搜索FUSE值。
FUSE_VALUE=$(node -p "process.versions.v8.split('.').slice(0, 3).join('')")# 注入Blob
npx postject build/sea-demo NODE_SEA_BLOB build/sea-prep.blob \--sentinel-fuse NODE_SEA_FUSE_${FUSE_VALUE}

4.5. 基础

./build/sea-demo --version# 查看SEA状态
strings build/sea-demo | grep NODE_SEA_# 启用详细日志
export NODE_DEBUG=sea
./build/sea-demo

5. 高级配置

5.1. 嵌入资源文件

修改sea-config.json:

{"main": "bin/cli.js","output": "build/sea-prep.blob","assets": {"a.txt": "src/assets/a.txt","b.json": "data/config.json"}
}

代码中通过 sea.resources 访问:

const resources = require('node:sea').resources;
console.log(resources.a.txt.toString());

6. 常见问题解决

6.1. FUSE值不匹配

症状: 运行时报 NODE_SEA_FUSE 错误 解决: 重新生成当前Node版本的blob

rm build/sea-prep.blob
node --experimental-sea-config sea-config.json

6.2. 模块加载失败

症状: 出现 Cannot find module 错误 解决: 确保所有依赖已打包:

  1. 使用 npm install --save 安装依赖
  2. 在 sea-config.json 中添加:
"useNodeBundle": true

7. 附录: SEA Blob 注入技术详解

7.1. 基本原理

技术栈组成:

  • postject: 基于Electron的跨平台二进制注入工具
  • FUSE: 版本特定标识符,防止错误注入
  • NODE_SEA_BLOB: 预定义的二进制段名称

工作流程:

+---------------------+     +---------------------+
| 原始Node可执行文件  | --> | 查找PE/ELF/MachO的  |
+---------------------+     | 特殊可注入区域      |+----------+----------+|+---------------v---------------+| 验证FUSE标识匹配性           || 检查段对齐和内存布局         |+---------------+---------------+|+----------v----------+| 写入压缩后的JS代码  || 更新文件校验和      |+---------------------+

7.2. 关键实现细节

二进制格式处理:

  • Windows PE: 修改 .rdata 段
  • Linux ELF: 扩展 .rodata 段
  • macOS Mach-O: 使用 __LLVM 段

内存布局示例(Linux ELF):

+-------------------------+
| ELF Header              |
+-------------------------+
| Program Headers         |
+-------------------------+
| .text                   |
+-------------------------+
| .rodata (原始数据)      |
+-------------------------+
| NODE_SEA_BLOB (新增)    | <-- 注入位置
+-------------------------+
| .data                   |
+-------------------------+

7.3. 数据段保护原理

现代二进制注入工具(如postject)采用以下策略保证安全:

保护机制实现方式
段末尾注入在目标段的文件空隙区域写入
段扩展通过增加PE/ELF节区大小实现
重定位表更新自动调整所有受影响的重定位项
校验和修复更新PE文件的Checksum字段

典型二进制文件布局(注入前后对比):

;; 注入前
[.text] [.rodata] [.data] [.imports]... <未使用空间>;; 安全注入后
[.text] [.rodata] [NODE_SEA_BLOB] [.data] [.imports]...
;; 或
[.text] [.rodata+blob] [.data]... (扩展.rodata段)
http://www.dtcms.com/a/330846.html

相关文章:

  • 【前端工具】使用 Node.js 脚本实现项目打包后自动压缩
  • Go语言defer机制详解与应用
  • 机器学习介绍
  • 预训练模型在机器翻译中的应用:迁移学习的优势详解
  • 华为实验WLAN 基础配置随练
  • dkms安装nvidia驱动和多内核支持
  • 【motion】GIF 转mp4及ubuntu的VLC播放
  • 数据结构初阶(14)排序算法—交换排序(冒泡)(动图演示)
  • 基于SpringBoot+Vue的房屋匹配系统(WebSocket实时通讯、协同过滤算法、地图API、Echarts图形化分析)
  • iOS App TestFlight 上架全流程案例,从 0 到 1 完成内测分发
  • C#通过TCP_IP与PLC通信
  • vue部署正式环境上传nginx后遇到的问题
  • 分享10个ai生成ppt网站(附ai生成ppt入口)
  • ZigBee入门与提高(3)—— ZigBee协议初识
  • Wireshark中常见协议
  • 重学JS-002 --- JavaScript算法与数据结构(二)JavaScript 基础知识
  • MFT 在零售行业的实践案例与场景:加速文件集成与业务协作的高效方案
  • day30 TCP通信
  • 财务自动化软件敏感数据泄露风险评估与防护措施
  • B站 韩顺平 笔记 (Day 18)
  • C++ 仿RabbitMQ实现消息队列项目
  • 使用uniapp自定义组件双重支付密码
  • RabbitMQ面试精讲 Day 22:消息模式与最佳实践
  • 8.14网络编程——TCP通信基础
  • 计算机视觉第一课opencv(二)保姆级教
  • WPF 实现TreeView选中项双向绑定保姆级教程:TreeViewHelper深度解析
  • MySQL缓存策略
  • 计算机视觉--opencv(代码详细教程)(二)
  • iPhone 17 系列发布会定于 9 月 9 日举行-邀请函或 9 月 2 日发出
  • MCP Server搭建