使用Node.js 20和Esbuild从您的节点应用程序中编译单个可执行文件
#typescript #node #esbuild

介绍

Node.js 20最近发布。与其他几个功能一起,您现在可以将Node.js项目编译成一个可执行文件,该可执行文件可以在未安装Node.js的环境中运行。重要的是要注意,这仍然是实验性的,并且可能不适合用于生产。

node.js有有关如何设置这些单个可执行文件的说明:https://nodejs.org/api/single-executable-applications.html

不幸的是,在编译可执行文件时,您不会将依赖项编译到可执行文件中。要解决此问题,我们将利用JavaScript Bundler将依赖项捆绑到一个文件中,然后将其编译到我们的单个可执行文件中。

先决条件:

  • Node.js 20

请注意:虽然本文使用打字稿,但这不是必需的。

整理我们的项目

首先,我们需要一个可以在可执行文件中构建的项目。

我们将首先定义服务器。

server.ts

import express from "express";
import https from "https";
import fs from "fs";
import path from "path";

export const app = express();

//Initialize Request Data Type
app.use(express.json({ limit: "10mb" }));

app.get("/", (req, res) => res.send("Hello World!!"));

const port = 3000;
app.listen(port, () => {
    console.log(`Server is live on ${port}`);
});

我们定义了我们的软件包。

package.json

{
  "name": "node-executable-example",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "build": "esbuild server.ts --bundle --platform=node --outfile=server-out.js",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "author": "",
  "license": "ISC",
  "dependencies": {
    "esbuild": "0.17.17",
    "express": "^4.18.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/node": "^18.15.7",
    "typescript": "^5.0.2"
  }
}

请注意构建脚本。 Esbuild将将我们的.ts文件与我们的依赖关系捆绑到一个.js文件server-out.js中。实际上,您可以使用node server-out.js创建此文件来检查该文件是否正确完成了捆绑。

然后我们定义我们的tsconfig.json

tsconfig.json

{
  "compilerOptions": {
    "target": "es2022",
    "lib": ["es2022"],
    "module": "commonjs",
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "strict": true,
    "skipLibCheck": true
  }
}

我们现在定义我们的sea-config.json文件。

这是一个配置文件构建一个可以注入单个可执行应用程序的斑点(有关详细信息,请参见生成单个可执行准备斑点)

sea-config.json

{
  "main": "server-out.js",
  "output": "sea-prep.blob"
}

现在我们拥有所需的一切,我们可以开始将单个可执行文件整合在一起。

创建单个二进制文件

首先要安装所有依赖项,我们需要运行此命令:

npm install

NPM安装完成后,我们运行命令:

npm run build

这将创建我们的server-out.js,这将是我们将捆绑的文件,我们将在可执行文件中制作。

注意:,如果您想从步骤3开始的Node.js指南中的说明,因为以下步骤将完全相同,此处是:https://nodejs.org/api/single-executable-applications.html

生成要注入的斑点:

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

创建节点可执行文件的副本,并根据您的需要命名:

cp $(command -v node) server

注意:如果您在Linux发行版上(例如Ubuntu),则可以跳过下一步并直接运行二进制。

删除二进制的签名:

在macos上:

codesign --remove-signature server

在Windows上(可选):
可以从已安装的Windows SDK中使用Signtool。如果此步骤跳过

signtool remove /s server

通过运行以下选项运行延伸:

,将斑点注入复制的二进制文件中:

  • server-在步骤2中创建的节点可执行文件的副本的名称。
  • NODE_SEA_BLOB-二进制中的资源 /注释 /部分的名称将存储斑点的内容。 sea -prep.blob-步骤1中创建的斑点的名称
  • --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2- node.js项目使用的保险丝检测是否已注入文件。
  • --macho-segment-name NODE_SEA(仅在MacOS上需要) - 二进制中的片段的名称将存储斑点的内容。

总而言之,这是每个平台所需的命令:

MacOS以外的系统:

npx postject server NODE_SEA_BLOB sea-prep.blob \
    --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 

在macos上:

npx postject server NODE_SEA_BLOB sea-prep.blob \
    --sentinel-fuse NODE_SEA_FUSE_fce680ab2cc467b6e072b8b5df1996b2 \
    --macho-segment-name NODE_SEA 

签名二进制:

在macos上:

codesign --sign - server 

在Windows上(可选):
需要出席证书才能正常工作。但是,未签名的二进制仍然可以运行。

signtool sign /fd SHA256 server 

运行二进制:

./server

,如果您刚刚运行了node server.js

,则现在应该具有类似的运行节点服务器

如果您想看一个完整的示例,请转到这里:https://github.com/chadstewart/ts-node-executable-article-example

  • 如果您觉得这篇文章很有趣,请随时发表本文!
  • 如果您有兴趣了解有关前端工程的更多信息,请在Dev.toTwitter上关注我
  • 如果您要寻找工作,我强烈建议您在TwitterLinkedIn或Techishiring的网站https://www.TechIsHiring.com/上查看@techishiring,以获取已发布的工作和其他资源!
  • 是否想从Techishiring中查看策划的工作,求职者和资源的清单?查看TechIsHiring's Newsletter