利用ncc将NodeJS项目打包成单个文件

利用ncc将NodeJS项目打包成单个文件

hash070 41 2023-01-24

简介

在NodeJS项目中,一般情况下构建成品是放在dist文件夹下的一堆JS和TS文件,这样子有以下这些缺点:

  1. 不方便打包部署到服务端。
  2. 有时会因为一些依赖配置问题导致无法在服务器环境中顺利启动。
  3. 源码未加密,项目源代码有被窃取的风险。

而使用ncc即可解决上述这些问题,因此本文记录一下如何将NodeJS项目利用ncc打包成单文件。

安装@vercel/ncc

NCC有什么用?

NCC可以将 Node.js 模块及其所有依赖项编译成单个文件。

有了它,你将可以:

  • 在NPM上发布最小依赖包
  • 只将相关程序代码发送到无服务器环境
  • 省去了调整依赖配置的时间
  • 更快的启动时间和更少的IO开销
  • 加密源代码,防止项目代码被窃取

NCC的目标:

  • 零依赖
  • 内置TypeScript
  • 支持所有的NodeJS设计模式和NPM模块

首先根据你项目中所使用到的包管理工具,安装@vercel/ncc依赖包。

npm i @vercel/ncc
# yarn
yarn add @vercel/ncc
# pnpm
pnpm add @vercel/ncc

项目构建

安装完依赖后,先执行构建操作:

这里以pnpm为例

# 清理dist目录
pnpm rimraf dist
# 构建dist中的main.js到build目录下
pnpm ncc build dist/main.js -m -t -o dist/bundle/

构建成功后可以在dist/bundle/目录中看到一个index.js,使用node命令即可直接运行它。

例如:node dist/bundle/index.js

这样就和单jar包差不多了,哪里有node环境哪里就能运行它,非常方便和可靠。

进阶配置

package.json中配置打包脚本

每次手动输入一组命令比较麻烦,我们可以将这组命令写入到package.json中。

scripts中添加这一行:

    "bundle": "rimraf dist && pnpm build && pnpm ncc build dist/main.js -m -t -o dist/bundle/",

然后我们运行pnpm bundle命令即可一键构建了。

将项目进一步打包成全平台可执行文件

通过NCC将项目打包成单个JS文件确实不错,打包出来的JS文件将可以在任何装有NodeJS的环境中运行。

现在这玩意唯一的缺点就是需要依赖服务端的NodeJS环境了,能不能让这玩意不依赖服务端的Node环境,直接打包成全平台二进制可执行文件呢?

还真有,vercelPKG可以满足这个需求。

它的原理就是将JS文件和整个Node环境一起打包进去(electron直呼内行),就好比你想运行个环境无关的Jar包,那么你可以将整个JRE塞进去。

这么做的缺点就是打出来的包大了点,比如我有一个项目,通过NCC打包出来的index.js单文件只占3MB,而使用PKG打包出来的linux可执行文件达到了50MB,不过无伤大雅,服务器也不缺这50MB的磁盘空间,在服务端没有配置Node环境的时候还是很有意义的。

1674570935044.webp
1674570945440.webp

下面就简单记录一下如何利用PKG将NodeJS项目打包成全平台可执行文件。

安装PKG

# 利用NPM全局安装PKG
npm i -g pkg
# 也可以使用别的包管理工具仅在当前项目安装PKG
# 例如pnpm
pnpm add pkg

打包

看了眼文档中的操作示例,可以发现最简单的打包命令如下

pkg index.js

这个index.js可以是上面使用NCC构建出来的单文件,如果你按我的文章操作,构建后应该在dist/bundle/目录中。

因此,在终端中进入该目录后,只需运行上面那行命令,即可构建出三个平台的可执行二进制文件了,实测都能正常运行。

此时package.json中的构建脚本可以改成下面这样:

    "bundle": "rimraf dist && pnpm build && pnpm ncc build dist/main.js -m -t -o dist/bundle/&&cd dist/bundle/&&pkg index.js",

1674571237748.webp

更多细节请查看项目文档:https://github.com/vercel/pkg

参考项目:

参考文章: