Next.js + PayloadCMS CI构建的.next部署产物在EC2上动态依赖加载失败求助
Next.js + PayloadCMS CI构建的.next部署产物在EC2上动态依赖加载失败求助
遇到这种跨环境构建的依赖问题,大概率是CI构建环境和EC2运行环境的差异,或者是Next.js打包时没处理好@xenova/transformers的动态依赖加载逻辑导致的。结合你t3a.micro内存不足、只能靠CI构建的场景,我给你几个针对性的解决思路,咱们一步步排查:
1. 先把CI和EC2的环境完全对齐!
@xenova/transformers依赖的onnxruntime-node这类包是带平台特定二进制文件的,哪怕是Node.js小版本、pnpm版本不一样,都可能导致打包出来的依赖在EC2上跑不起来。
- 操作细节:
- GitHub Actions里指定和EC2完全一致的Node.js(22.16.0)、pnpm版本(比如你EC2用的pnpm 9.x,CI就别用8.x)
- CI的
pnpm install一定要加--frozen-lockfile,强制用lockfile里的依赖版本,避免和EC2上的依赖版本跑偏 - 确认GitHub Actions用的是
ubuntu-22.04的runner镜像,和EC2的系统完全匹配
2. 调整Next.js打包配置,把动态依赖“抓”进构建产物
@xenova/transformers是动态加载依赖的,Turbopack可能在CI构建时没把这些依赖正确打包进.next,导致EC2上运行时找不到。
- 操作细节:
- 在
next.config.js里添加transpilePackages,把相关依赖都加入转译列表:/** @type {import('next').NextConfig} */ const nextConfig = { transpilePackages: ['@xenova/transformers', 'onnxruntime-node', 'onnxruntime-web', '@huggingface/jinja'], // 保留你原来的其他配置 } module.exports = nextConfig - 这样Next.js会把这些依赖转译后包含到构建产物里,避免动态加载时出现模块缺失
- 如果还是不行,可以试试在next.config.js里加
externalDependencies: false,强制把所有依赖都打包进去(注意产物会变大,但能解决路径问题)
- 在
3. 修正你的CI打包和EC2部署脚本(这个可能是当前的坑!)
pnpm的软链接机制在跨环境打包时很容易失效,而且你现在的部署脚本有个致命问题:
你在部署脚本里删了
package.json和pnpm-lock.yaml,然后跑pnpm install——这相当于让pnpm随便装依赖版本,和CI构建的版本完全不一致!
- 紧急修正部署脚本:
删掉rm -rf .next public/ package.json pnpm-lock.yaml这一行里的package.json pnpm-lock.yaml,改成只删.next public/
把pnpm install改成pnpm install --prod --frozen-lockfile,这样会严格按照lockfile安装生产依赖,和CI的依赖版本完全对齐 - 补充CI打包逻辑:
如果还是有路径问题,CI构建完成后,除了打包.next,还要把node_modules里的@xenova/transformers、onnxruntime-node、onnxruntime-web、@huggingface/jinja这几个目录单独复制出来,和.next一起打包成zip。EC2部署时,把这些依赖目录解压到项目的node_modules下,确保动态加载的路径正确。
4. 针对@xenova/transformers的特殊处理
这个库的动态加载逻辑有点“特殊”,你可以试试显式导入依赖,让Next.js打包工具识别到它们:
- 在你使用
@xenova/transformers的文件开头加上:
这样Next.js会把这些依赖主动包含到构建产物中,避免动态加载时找不到import 'onnxruntime-node'; import 'onnxruntime-web'; import '@huggingface/jinja'; - 另外,可以设置环境变量
TRANSFORMERS_CACHE指定模型缓存路径,确保动态加载的模型文件路径正确(这个是补充,不一定直接解决当前模块缺失,但能避免后续问题)
5. 终极替代方案:Docker镜像部署
如果上面的方法都搞不定,试试用Docker把整个应用打包成镜像:
- CI里写一个Dockerfile,基于
ubuntu:22.04,安装对应版本的Node.js、pnpm,然后执行pnpm install、pnpm build,最后把镜像推到AWS ECR - EC2上只需要拉取镜像,用Docker run启动,这样环境完全一致,依赖问题会少很多
- 虽然t3a.micro内存小,但Docker运行的内存占用和直接跑应用差不多,而且构建全在CI完成,不会占用EC2的内存
优先尝试的顺序
我建议你先从修正部署脚本(恢复package.json和lockfile,用--frozen-lockfile安装依赖)和对齐CI与EC2环境开始试,这两个是最快速能验证的方案,大概率能解决当前的模块缺失问题。如果还是不行,再调整Next.js的打包配置。
备注:内容来源于stack exchange,提问作者Intuz Cloud
相关产品推荐
相关产品推荐

