You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

NodeJS项目通过Github Action SSH部署时PM2启动ESM模块报错

NodeJS ESM项目通过Github Action部署PM2启动失败问题解决

问题背景

我在NodeJS项目中通过指定package.json的type字段启用ES模块(ESM),同时为PM2创建了ecosystem.config.cjs配置文件(适配PM2的CommonJS规范)。配置文件内容:

module.exports = {
    apps: [{
        name: "app-name",
        script: "./index.mjs",
    }]
}

项目目录结构:

project-root/
├── node_modules/         
├── .env                 
├── .gitignore           
├── ecosystem.config.cjs 
├── index.mjs           
└── package.json        

通过Github Action的SSH Remote Commands部署到DigitalOcean Droplet,部署脚本:

- name: SSH Remote Commands
    uses: appleboy/ssh-action@v1.0.0
    with:
      host: xxx.xxx.xxx.xxx
      username: root
      key: ${{ secrets.SSH_KEY }}
      script: |
        pm2 stop ${{ env.REPO_NAME }}
        pm2 flush ${{ env.REPO_NAME }}
        pm2 start ecosystem.config.cjs
        exit

部署后出现错误:

Error [ERR_REQUIRE_ESM]: Must use import to load ES Module: /root/nodejs-app/index.mjs
    at Module.load (internal/modules/cjs/loader.js:861:11)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Object.<anonymous> (/usr/local/lib/node_modules/pm2/lib/ProcessContainerFork.js:33:23)
    at Module._compile (internal/modules/cjs/loader.js:999:30)
    at Object.Module._extensions..js (internal/modules/cjs/loader.js:1027:10)
    at Module.load (internal/modules/cjs/loader.js:863:32)
    at Function.Module._load (internal/modules/cjs/loader.js:708:14)
    at Function.executeUserEntryPoint [as runMain] (internal/modules/cjs/loader.js:60:12)
    at internal/main/run_main_module.js:17:47 {
  code: 'ERR_REQUIRE_ESM'
}

但手动在VPS执行PM2启动命令完全正常。

问题分析与解决方案

1. 工作目录不匹配

Github Action的SSH脚本默认执行路径可能不是项目根目录,导致PM2无法读取package.json中的type配置,无法识别ESM模块。手动执行时你处于项目根目录,但CI脚本可能在其他路径运行。

  • 修复:在脚本中先切换到项目根目录:
script: |
  cd /root/nodejs-app
  pm2 stop ${{ env.REPO_NAME }}
  pm2 flush ${{ env.REPO_NAME }}
  pm2 start ecosystem.config.cjs
  exit

2. PM2进程残留或缓存

CI执行pm2 stop后可能残留旧的进程容器,这些容器仍以CommonJS模式运行,导致新进程启动时沿用旧的模块规则。手动执行时已清理干净残留进程。

  • 修复:强制删除旧进程并清理缓存:
script: |
  cd /root/nodejs-app
  pm2 delete ${{ env.REPO_NAME }} || true
  pm2 flush ${{ env.REPO_NAME }} || true
  pm2 start ecosystem.config.cjs
  exit

3. Node.js环境变量差异

手动执行时的Shell环境变量(如NODE_OPTIONS)与CI脚本环境不同,CI环境可能缺少ESM相关配置。

  • 修复:
    • 方法一:在启动命令前添加环境变量:
    script: |
      cd /root/nodejs-app
      pm2 delete ${{ env.REPO_NAME }} || true
      NODE_OPTIONS="--experimental-specifier-resolution=node" pm2 start ecosystem.config.cjs
      exit
    
    • 方法二:修改ecosystem.config.cjs添加interpreter_args:
    module.exports = {
        apps: [{
            name: "app-name",
            script: "./index.mjs",
            interpreter_args: "--experimental-specifier-resolution=node"
        }]
    }
    

4. PM2版本不一致

VPS上手动使用的PM2版本与CI脚本调用的版本可能不同,旧版本PM2对ESM的支持存在缺陷。

  • 修复:
    • 使用项目本地安装的PM2:
    script: |
      cd /root/nodejs-app
      pm2 delete ${{ env.REPO_NAME }} || true
      npx pm2 start ecosystem.config.cjs
      exit
    
    • 升级VPS上的PM2到最新版本:
    script: |
      npm install -g pm2@latest
      cd /root/nodejs-app
      pm2 delete ${{ env.REPO_NAME }} || true
      pm2 start ecosystem.config.cjs
      exit
    

内容的提问来源于stack exchange,提问作者hh54188

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.14 20:42:19