Azure Functions本地可解析npm包,部署到Azure后无法解析的问题
问题场景
使用Node.js开发Azure Functions,目录结构如下(所有依赖声明在Functions目录的上级package.json中):
|-- package.json |-- node_modules /* 所有子目录代码依赖存放于此 */ |-- server/ |-- src/ |-- azf/ |-- host.json |-- local.settings.json |-- tsconfig.json |-- package.json /* 仅包含npm脚本,无依赖 */ |-- FunctionOne/ |-- function.json |-- index.ts |-- FunctionTwo/ |-- function.json |-- index.ts
本地运行func start正常,但通过GitHub Action部署到Azure后,函数抛出依赖找不到的错误:
Failure Exception: Worker was unable to load function FunctionTwo: 'Cannot find module 'lodash' Require stack: - /home/site/wwwroot/dist/FunctionTwo/index.js
Node.js默认的向上遍历找node_modules机制在Azure环境中失效,以下是可行的解决办法:
方法1:部署时同步上级node_modules到Functions目录
Azure Functions运行时的工作目录是/home/site/wwwroot,默认部署只会上传Functions目录(或编译后的dist目录),上级node_modules不会被包含。可以在GitHub Action的构建步骤后添加复制命令,把根目录的node_modules复制到待部署的dist目录中:
# 假设编译后的代码输出到server/src/azf/dist cp -R ../../../../node_modules server/src/azf/dist/
之后再将包含node_modules的dist目录部署到Azure Functions即可。
方法2:手动添加模块解析路径
在每个Function的入口文件(如index.ts)顶部添加代码,将上级目录的node_modules路径手动加入Node.js的模块搜索列表:
const path = require('path'); const modulePaths = require('module').Module._nodeModulePaths; // 根据部署后的实际目录结构计算上级node_modules路径 const rootNodeModules = path.join(__dirname, '../../../../node_modules'); modulePaths.push(rootNodeModules);
注意:需要确保部署后的目录结构稳定,避免路径计算错误导致失效。
方法3:通过npm workspaces共享依赖
在根目录的package.json中配置workspaces,让Functions目录共享根目录的依赖,无需重复维护:
- 根目录
package.json添加workspaces配置:
{ "workspaces": ["./server/src/azf"] }
- 在
azf目录的package.json中声明依赖(版本可继承根目录,无需重复指定):
{ "dependencies": { "lodash": "*" } }
- 部署时在根目录执行
npm install --production,然后部署azf目录,Azure Functions运行时就能找到本地的node_modules。
方法4:调整部署上下文包含上级依赖
修改GitHub Action的部署步骤,在项目根目录执行func azure functionapp publish命令,同时在azf目录的.funcignore文件中配置,确保上级node_modules被包含:
- 在
.funcignore中添加规则(保留上级node_modules,排除其他无关内容):
../** !../node_modules/ !../package.json
- 部署时切换到项目根目录,执行发布命令:
func azure functionapp publish <your-function-app-name> --publish-local-settings -i
内容的提问来源于stack exchange,提问作者d512

