本地与线上 Node.js 行为一致需严格对齐三要素:runtime 字符串、Node 版本(如 v18.19.1)、容器内 handler 路径(如 src/handlers/hello.handler);Docker 必须启用以模拟真实 Lambda 环境,且 VS Code 调试 type 必须匹配启动方式。

本地跑出和线上一致的 Node.js 行为,不是靠“差不多”,而是三件事必须对齐:runtime 字符串、node 版本、容器内执行路径。缺一不可,否则 require 失败、fetch 报错、process.env 缺字段,都是 runtime 不匹配的典型症状。
Node 版本和 runtime 字符串必须严格一致
云端用 nodejs18.x,本地就得用 Node.js v18.19.1(或至少 v18.20.x),不能是 v16 或 v20。SAM 和阿里云 Funcraft 都会校验 runtime 字符串,不匹配就直接拒绝加载 handler。
- 查线上配置:在 AWS 控制台函数详情页看
Runtime字段,或在阿里云 FC 控制台看“运行环境” - 本地切换:用
nvm use 18.19.1,别只改package.json的engines.node—— 那只是 CI 提示,不影响本地调试进程 - 验证一致性:在 VS Code 集成终端里执行
node -v,再开一个独立终端也执行一次,两者输出必须完全相同;VS Code 有时会继承旧 shell 环境,导致node -v显示的是系统默认版本
handler 路径写错,VS Code 从不报错但断点永不触发
这是最隐蔽的失败点:sam local invoke 返回 200,日志显示“success”,但你的断点就是不亮——因为函数根本没加载。路径多一个 .、少一个 /,或者用了 .py::handler 这类 Serverless 框架风格写法,SAM 就会在容器里找错位置。
- Node.js 正确写法:
src/handlers/hello.handler(注意:没有开头的.,没有.js后缀) - Python 正确写法:
app.lambda_handler(不是app.py::lambda_handler,也不是./app.lambda_handler) - 如果
serverless.yml在子目录(如packages/api/serverless.yml),必须显式配package.patterns包含 handler 文件,否则打包时漏掉,本地也找不到 - 用 Serverless IDE 插件右键
serverless.yml→ “Validate Serverless Configuration”,它能标出路径解析失败,但得手动启用
Docker 是必须项,不是可选项
SAM CLI 默认用 Docker 运行 Amazon Linux 容器镜像,模拟真实 Lambda 的 /var/task 挂载、/tmp 权限、时区、二进制依赖加载行为。不装 Docker,SAM 会 fallback 到 mock 模式,但很多底层差异会让你调试时“感觉不对劲”:
-
/tmp目录不可写或权限异常 → 依赖临时文件的库(如 sharp、ffmpeg)直接崩溃 - 时区是 UTC+0,但本地系统是 CST →
new Date().toISOString()时间戳偏差 8 小时 - C++ 扩展(如 bcrypt、sqlite3)加载失败 → 报
MODULE_NOT_FOUND或Cannot open shared object file - 验证是否生效:运行
sam local invoke --debug-port 9999,看到输出里有Mounting /path/to/project as /var/task:ro,delegated才算真正进了容器
launch.json 的 type 必须匹配启动方式
填错 "type" 不会报错,但 VS Code 根本连不上调试进程——不是端口被占,是协议不兼容。
- 用
"type": "aws-sam"(推荐):右键template.yaml→ “Debug Locally”,AWS Toolkit 自动调sam local invoke --debug-port 9999,VS Code attach 上去,context 和 event 是真实注入的 - 用
"type": "node"(仅限sls offline):必须配runtimeExecutable指向sls,runtimeArgs加offline,但此时context是 mock 的,/tmp权限也不对 - 混用必挂:比如
launch.json写"type": "node",却去右键template.yaml点 “Debug Locally”,VS Code 会等一个根本不存在的node进程 PID
真正卡住人的地方,从来不是“怎么装插件”,而是 runtime 字符串和实际 node 版本差小数点后一位、handler 路径里多了一个看不见的 .、或者以为 Docker 装了其实没启动成功——这些细节不验证,F5 按十次也没用。


















