構建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.pswp.cn/pingmian/93048.shtml
繁體地址,請注明出處:http://hk.pswp.cn/pingmian/93048.shtml
英文地址,請注明出處:http://en.pswp.cn/pingmian/93048.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

Java19 Integer 位操作精解:compress與expand《Hacker‘s Delight》(第二版,7.4節)

compress(int i, int mask) 這個方法是Java 19中新增的一個強大的位操作函數。compress 方法的核心功能可以理解為 “按位過濾和壓縮” 。過濾 (Filter): 它使用 mask&#xff08;掩碼&#xff09;作為過濾器。對于輸入整數 i&#xff0c;只有那些在 mask 中對應位為 1 的比特才…

minio部署和雙機熱備

安裝單機版MinIO&#xff08;準備2臺機器A、B,A、B服務器操作一致&#xff09;切換目錄并下載MinIO二進制文件cd /usr/local/bin wget https://dl.minio.org.cn/server/minio/release/linux-amd64/minio chmod x minio編輯配置文件vi /etc/default/minio.confMINIO_VOLUMES&quo…

【Java】 Java 21 革命性升級:虛擬線程與結構化并發的深度實踐指南

還在為高昂的AI開發成本發愁?這本書教你如何在個人電腦上引爆DeepSeek的澎湃算力! Java 21 作為 Oracle JDK 的長期支持版本,引入了多項革命性特性,其中虛擬線程(Virtual Threads)和結構化并發(Structured Concurrency)尤為突出。這些特性旨在解決傳統線程模型在高并發…

Apache IoTDB 全場景部署:基于 Apache IoTDB 的跨「端-邊-云」的時序數據庫 DB+AI

Apache IoTDB 全場景部署&#xff1a;基于 Apache IoTDB 的跨「端-邊-云」的時序數據庫 DBAI 文章目錄Apache IoTDB 全場景部署&#xff1a;基于 Apache IoTDB 的跨「端-邊-云」的時序數據庫 DBAIApache IoTDB 介紹Docker部署指導企業版數據庫配套工具 WorkbenchTimechoDB&…

計算機網絡---傳輸控制協議Transmission Control Protocol(TCP)

一、TCP的定位與核心特性 TCP&#xff08;Transmission Control Protocol&#xff0c;傳輸控制協議&#xff09;是TCP/IP協議棧中傳輸層的核心協議&#xff0c;與UDP&#xff08;用戶數據報協議&#xff09;共同承擔端到端數據傳輸功能。其設計目標是在不可靠的IP網絡上提供可靠…

week1-[分支嵌套]公因數

week1-[分支嵌套]公因數 題目描述 給定 444 個正整數 a,b,c,ka,b,c,ka,b,c,k。如果 a,b,ca,b,ca,b,c 都是 kkk 的倍數&#xff0c;那么稱 kkk 是 a,b,ca,b,ca,b,c 的公因數。否則如果某兩個數都是 kkk 的倍數&#xff0c;那么稱 kkk 是這兩個數的公因數。問 kkk 是哪些數的公因…

C#枚舉/結構體講一講

先展示一段簡單代碼// 定義枚舉 public enum thisday {吃飯,不吃 }// 定義結構體 public struct person {public string name;public int age;public thisday zhuangtai; // 使用枚舉類型作為字段 }static void Main(string[] args) {// 創建結構體實例person thisperson;thisp…

C++-setmap詳解

Cset&map 1. 序列式容器和關聯式容器 1.1 序列式容器 序列式容器按照線性順序存儲元素&#xff0c;元素的位置取決于插入的時間和位置&#xff0c;與元素的值無關。 主要特點&#xff1a;元素按插入順序存儲可以通過位置&#xff08;索引&#xff09;直接訪問元素不自動排序…

解決程序連不上RabbitMQ:Attempting to connect to/access to vhost虛擬主機掛了的排錯與恢復

前言&#xff1a;在分布式系統里&#xff0c;RabbitMQ作為消息中間件&#xff0c;是服務間通信的關鍵紐帶。但實際使用中&#xff0c;程序連接RabbitMQ失敗的情況時有發生。本文結合真實報錯&#xff0c;細致呈現從問題發現到解決的完整排錯思路&#xff0c;還會深入講解Rabbit…

K8S中如何配置PDB(Pod Disruption Budget)

1. PDB 核心概念作用&#xff1a;控制自愿中斷&#xff08;如節點升級、縮容&#xff09;期間&#xff0c;應用的最小可用副本數或最大不可用比例。關鍵參數&#xff1a;minAvailable&#xff1a;必須保持運行的 Pod 數量&#xff08;如 2 或 50%&#xff09;。maxUnavailable&…

從 0 到 1:用 MyCat 打造可水平擴展的 MySQL 分庫分表架構

一、為什么要分庫分表&#xff1f; 單機 MySQL 的極限大致在&#xff1a;維度經驗值單表行數≤ 1 000 萬行&#xff08;B 樹三層&#xff09;單庫磁盤≤ 2 TB&#xff08;SSD&#xff09;單機 QPS≤ 1 萬&#xff08;InnoDB&#xff09;當業務繼續增長&#xff0c;數據量和并發…

電池模組奇異值分解降階模型

了解如何將奇異值分解 (SVD) 降階模型 (ROM) 應用于電池模塊熱模擬。挑戰隨著電池模塊在電動汽車和儲能系統中的重要性日益提升&#xff0c;其熱性能管理也成為一項重大的工程挑戰。高功率密度會產生大量熱量&#xff0c;如果散熱不當&#xff0c;可能導致電池性能下降、性能下…

《Python函數:從入門到精通,一文掌握函數編程精髓》

堅持用 清晰易懂的圖解 代碼語言&#xff0c;讓每個知識點變得簡單&#xff01; &#x1f680;呆頭個人主頁詳情 &#x1f331; 呆頭個人Gitee代碼倉庫 &#x1f4cc; 呆頭詳細專欄系列 座右銘&#xff1a; “不患無位&#xff0c;患所以立。” Python函數&#xff1a;從入門到…

【記錄貼】STM32 I2C 控制 OLED 卡死?根源在 SR1 與 SR2 的讀取操作

問題描述最近在復用以前STM32F407控制OLED的代碼&#xff0c;移植到STM32F103 上&#xff0c;使用硬件 I2C 通信方式。按照常規流程&#xff0c;先發送 OLED 的從機地址&#xff0c;OLED 有正常應答&#xff0c;但當發送第一個控制命令&#xff08;0xAE&#xff09;前的控制字節…

【AI驅動的語義通信:突破比特傳輸的下一代通信范式】

文章目錄1 語義通信簡介1.1 基本概念&#xff1a;什么是語義通信&#xff1f;語義通信的核心目標1.2 基本結構&#xff1a;語義通信系統結構語義通信系統的通用結構組成語義通信系統的結構關鍵模塊1.3 基于大模型的語義通信關鍵技術&#x1f9e0;語義通信系統中AI大模型的設計建…

網絡原理-HTTP

應用層自定義協議自定義協議是指根據特定需求設計的通信規則&#xff0c;用于設備或系統間的數據交換。其核心在于定義數據結構、傳輸方式及處理邏輯。協議結構示例典型的自定義協議包含以下部分&#xff1a;頭部&#xff08;Header&#xff09;&#xff1a;標識協議版本、數據…

ROS配置debug指南

一. 安裝插件 下面的這一個插件過期了需要用下面的這一個插件來替換:二. 設置CMakeLists.txt的編譯模式 set(CMAKE_BUILD_TYPE "Debug") set(CMAKE_CXX_FLAGS_DEBUG "$ENV{CXXFLAGS} -O0 -Wall -g -ggdb") set(CMAKE_CXX_FLAGS_RELEASE "$ENV{CXXFLAG…

微軟正式將GPT-5接入Microsoft Copilot Studio(國際版)

微軟宣布正式在Microsoft Copilot Studio&#xff08;國際版&#xff09;中集成GPT-5&#xff0c;推動智能體構建能力實現突破性升級。此次更新不僅為企業用戶帶來更高效的響應速度、更精準的語境理解能力&#xff0c;還通過增強的邏輯推理功能&#xff0c;顯著提升了AI交互的深…

微算法科技(NASDAQ:MLGO)通過蟻群算法求解資源分配的全局最優解,實現低能耗的區塊鏈資源分配

隨著區塊鏈網絡規模的不斷擴大和業務需求的日益復雜&#xff0c;資源分配問題逐漸成為制約其發展的關鍵因素之一。傳統的區塊鏈資源分配方法往往存在效率低下、能耗過高、難以達到全局最優解等問題。高能耗不僅增加了運營成本&#xff0c;還對環境造成了較大的壓力。因此&#…

深入淺出JVM:Java虛擬機的探秘之旅

深入淺出JVM&#xff1a;Java虛擬機的探秘之旅一、JVM 初相識&#xff1a;揭開神秘面紗 在 Java 的世界里&#xff0c;JVM&#xff08;Java Virtual Machine&#xff0c;Java 虛擬機&#xff09;就像是一個神秘的幕后大 boss&#xff0c;掌控著 Java 程序運行的方方面面。你可以…