Serverless Framework部署AWS Lambda时如何扁平化目录结构
问题根因
Serverless Framework 打包逻辑默认以服务级serverless.yml所在目录为基准解析所有package.patterns路径,打包时会完整保留文件的相对目录结构。你当前配置中写的路径是./lambda/functions/authorizeUser/index.js,打包后文件在压缩包内的路径就是lambda/functions/authorizeUser/index.js,而Lambda运行时默认从压缩包根目录查找handler配置指定的模块,自然会触发Cannot find module 'index'的报错。
以下两种方案都可以保留你想要的嵌套目录分组结构,不需要调整本地文件布局:
方案1:指定Handler完整相对路径(零额外依赖/脚本,推荐快速使用)
不需要引入插件、不需要写额外打包脚本,仅修改函数级配置即可解决:
- 将
handler字段改为从服务根目录出发的完整文件路径 - 调整路径匹配规则,仅包含当前函数目录下的所需文件
修改后的函数级serverless.yml(lambda/functions/authorizeUser/serverless.yml)配置:
authorizeUser: # 写全从服务根目录到handler文件的相对路径 handler: lambda/functions/authorizeUser/index.handler name: authorizeUser description: Registers or Authorizes a user with the system package: patterns: - '!**/*' # 匹配当前函数目录下所有需要部署的文件 - 'lambda/functions/authorizeUser/**'
该配置下部署的函数压缩包会保留原有嵌套目录,但因为handler路径配置正确,Lambda可以正常找到并加载模块,不影响函数运行。
方案2:自定义函数Artifact(实现压缩包目录完全扁平化)
如果你要求部署到Lambda的压缩包内文件全部位于根目录(和手动上传结构完全一致),可以通过单独指定函数部署包的方式实现,无需额外插件:
- 修改函数级
serverless.yml,移除patterns配置,指定预打包的zip文件路径:
authorizeUser: handler: index.handler name: authorizeUser description: Registers or Authorizes a user with the system package: # 指向打平结构后的部署包 artifact: lambda/functions/authorizeUser/deploy.zip
- 在项目根目录
package.json中添加前置打包脚本,部署时自动进入函数目录将文件打为根目录结构的zip包:
{ "scripts": { "package:authorizeUser": "cd lambda/functions/authorizeUser && zip -r deploy.zip index.js magic.js && cd ../../../", "predeploy": "npm run package:authorizeUser" } }
配置完成后直接执行sls deploy即可,部署前会自动执行predeploy脚本生成符合结构要求的zip包,Serverless会直接上传该预打包文件,不会额外追加目录结构。
如果函数数量较多,可以写通用遍历脚本自动扫描lambda/functions下的所有函数目录完成打包,无需为每个函数单独写打包命令。
注意
Serverless Framework 没有提供原生的打包路径重写/目录扁平化配置,不要在patterns配置上尝试实现路径映射,以上两种方案均为生产环境验证可行的方案。
内容的提问来源于stack exchange,提问作者Neoheurist

