likes
comments
collection
share

Midwayjs部署环境-pkg可执行文件

作者站长头像
站长
· 阅读数 1

Midwayjs部署环境-pkg可执行文件

介绍

大家都知道 Node 是以源码方式进行启动 node xxx.js 就可以运行。

我们运行 Node.js 开发的后端服务是需要安装环境后还需要安装相关依赖才能运行,部署目录就能直接看到源代码,这样会有源码泄露的风险。

为了更好的保护知识产权,将 Node.js 打包为一个单独的可执行文件,部署时直接拷贝执行即可,不需要安装node运行环境。Midwayjs 二进制文件部署

安装依赖

## 将所有的项目代码以组件的形式导出用于生成入口
npm i @midwayjs/bundle-helper --save-dev

## 用于构建二进制文件
npm i pkg --save-dev

pkg配置说明

首先需要对 pkg 进行配置,主要内容在 package.jsonbinpkg 字段下。

  • main 程序默认的启动运行入口文件
  • bin 二进制文件启动入口文件
  • pkg.scripts 构建启动使用的使用的所有 js 文件,使用 glob 的语法
  • pkg.asserts 代码内部固定使用的模块引用文件
  • pkg.targets 构建的平台产物,是下列选项的组合(nodeRange-platform-arch):
    • nodeRange node10, node12, node14, node16 or latest
    • platform alpine, linux, linuxstatic, win, macos
    • arch x64, arm64, armv7
  • pkg.outputPath 构建产物的输出地址

补充文件

mask_api_midwayjs
├── bin
├   ├── assets                  目录-静态文件目录
├   ├── config.json             文件-传入覆盖的配置
├   └── 可执行文件               文件-可执行文件
├   └── package.json            文件-项目包信息
├── ...
├── bootstrap-bin.js            文件-pkg打包方式入口
├── bootstrap.js                文件-程序部署PM2启动运行入口
└── package.json                文件-程序依赖及启动命令信息

bin 作为pkg打包输出目录,其中是部署时必要的文件,需要与可执行文件同级放置。

assets 是给程序内部读取的静态资源文件,通过fs文件操作方式读取,修改后不需要重新启动才会生效。将构建生成的 dist 目录下的 assets 内非模块引用的文件放入,可解决读取内部文件失败问题。

config.json 是标准JSON格式内容,不含注释说明。文件放置与可执行文件同级,配置内容会合并到当前服务环境运行配置中,修改后需要重新启动才能生效。

package.json 可以直接复制使用项目根路径下的 package.json 文件,解决 MidwayInformationService 无法获取包信息的问题。文件修改后需要重新启动才能生效。

bootstrap-bin.js 文件创建

需要在项目根路径下创建该文件,配置给pkg作为启动入口。

// bootstrap-bin.js
const { Bootstrap } = require('@midwayjs/bootstrap');
const fs = require('fs');
const path = require('path');

// 指定读取配置文件
const configPath = path.resolve(process.cwd(), 'config.json');

// 配置文件JSON格式内容
let jsonConfig = undefined;

// 检查文件是否存在
if (fs.existsSync(configPath)) {
  try {
    const jsonData = JSON.parse(fs.readFileSync(configPath, 'utf-8'));
    if (jsonData) {
      jsonConfig = jsonData;
    }
  } catch (err) {
    console.error(`读取配置文件 config.json 格式错误:${err.message}`);
  }
}

Bootstrap.configure({
  // 项目代码目录,指向可执行文件的目录
  baseDir: process.cwd(),
  // 引用的是编译后的入口
  imports: require('./dist/index'),
  // 禁用依赖注入的目录扫描
  moduleDetector: false,
  // 全局传入的配置,直接以对象形式合并到当前的配置中
  globalConfig: jsonConfig,
}).run();

package.json 添加pkg相关的配置

pkg 使用 --compress Brotli 对文件进行压缩,可选Brotli或GZip。

// package.json
{
  "name": "mask_api_midwayjs",
  // ...
  "scripts": {
    // ...
    "bundle": "bundle && npm run build",
    "pkg": "bundle && pkg . --compress Brotli"
  },
  "devDependencies": {
    // ...
    "@midwayjs/bundle-helper": "^1.2.1",
    "pkg": "^5.8.1"
  },
  "main": "./bootstrap.js",         // 程序部署PM2启动运行入口
  "bin": "./bootstrap-bin.js",      // pkg打包方式入口
  "pkg": {
    "scripts": "./dist/**/*.js",      // 需要打包的js脚本
    "assets": [                     // 模块引用缺失的依赖文件
      "./node_modules/bull/**/*"
    ],
    "targets": [                    // 需要在对应平台上构建避免缺失平台依赖
      "node18-win-x64"
    ],
    "outputPath": "./bin"
  }
  // ...
}

构建

npm install             # 安装项目所需依赖
npm run bundle          # 生成编译模块入口文件
npm run pkg             # 构建平台产物

注意:TypeORM 使用实体模型扫描时会导致 EntityMetadataNotFoundError

得到的平台产物约 80MB 左右。

推荐部署平台上安装依赖进行构建,避免跨平台构建会存在缺失依赖的情况,可以在虚拟机中构建同系统架构的二进制产物后拿去部署。

运行可执行程序时有提示缺失模块依赖的情况可以在 pkg.asserts 中进行补充。

下载构建的平台产物包

当遇到下载失败或下载慢的时候建议去Github仓库里下载,之后放到指定路径在继续构建操作。

Github仓库 github.com/vercel/pkg-…

$> npm run pkg

> mask_api_midwayjs@0.0.1 pkg
> bundle && pkg .

> pkg@5.8.1
> Fetching base Node.js binaries to PKG_CACHE_PATH
  fetched-v18.5.0-win-x64             [                    ] 0%
> Not found in remote cache:
  {"tag":"v3.4","name":"node-v18.5.0-win-x64"}

第一步:根据打包时给出的文件信息确认版本

根据提示应该去找对应的tag版本,上Github仓库 github.com/vercel/pkg-… 在 Assets 展开找到对应的 node-v18.5.0-win-x64 下载。

也可以根据下载文件名称上Github仓库找到对应的版本,要和 tag 一致的,不然会校验不通过。

第二步:替换下载文件

PKG_CACHE_PATH 目录,默认是 ~/.pkg-cache

  • Linux平台对应 /home/{当前用户}/.pkg-cache/{tag}
  • Window平台对应 C:\Users\{当前用户}\.pkg-cache\{tag}

将下载好的文件 node-v18.5.0-win-x64 修改文件名称 fetched-v18.5.0-win-x64 放入指定位置。

第三步:执行构建命令

如果提示 Binary hash does NOT match. Re-fetching... 说明你下载错版本校验不通过,建议检查对应的tag

如遇到无法解决的问题,可以在下方进行留言,会在第一时间进行解答。