TL;DR:如果你在 Vercel 上的 API 路由莫名其妙返回
405 Not Allowed,而日志里同时出现
Could not load the "sharp" module using the linux-x64 runtime,极大概率是 sharp 二进制与 Vercel 运行时不兼容。
将sharp(以及@types/sharp)锁定到0.30.4即可恢复正常。
现场还原
- 现象:本地(macOS)开发环境下一切正常;部署到 Vercel 后,访问某些 API(例如
/api/reference/upload)直接 405。 - Vercel 日志:
Error: Failed to load external module sharp: Error: Could not load the "sharp" module using the linux-x64 runtime
Possible solutions:
- Ensure optional dependencies can be installed:
npm install --include=optional sharp
- Ensure your package manager supports multi-platform installation:
See https://sharp.pixelplumbing.com/install#cross-platform
- Add platform-specific dependencies:
npm install --os=linux --cpu=x64 sharp
- Consult the installation documentation:
See https://sharp.pixelplumbing.com/install
at Context.externalRequire [as x] (.next/server/chunks/[turbopack]_runtime.js:501:15)
...
page: '/api/reference/upload'
- 额外信息:Vercel 的 Issues 中也有类似报告(如 vercel/vercel#11052),结论指向 sharp 高版本与 Vercel 运行环境不兼容。
为什么会是 405?
很多人见到 405 第一反应是「接口方法不匹配」(比如你只实现了 POST,却发了 GET)。
但在 Next.js + Vercel 的实际部署中,当你的路由模块在运行时加载失败(例如 sharp 无法被正确 require/esm import),框架可能在不同层面表现为:
- 边缘/服务器层返回一个兜底响应(在某些路径下会显得像 405/404),
- 或者被中间件/路由处理器吞掉异常,表象并非 500。
关键点:看日志!一旦日志出现 Could not load the "sharp" module using the linux-x64 runtime,就应当把怀疑点放在 sharp 二进制/依赖 上,而不是路由方法。
根因分析
- sharp 是原生扩展,依赖 libvips,并为不同平台/架构提供预编译二进制。
- 本地(macOS + x64/arm64)能跑,并不代表 部署目标(Vercel 的 Linux x64) 也能跑。
- 某些新版本 sharp 的预编译二进制与 Vercel 的 Linux 运行时/ABI 并不匹配或存在兼容性问题,导致模块加载失败。
- 结论:在 Vercel 上,sharp 选择
0.30.4版本是更稳妥的(来自实踩与社区反馈)。
一分钟修复指南
在 package.json 里锁定版本(注意同时锁 @types/sharp,避免类型和 API 偏差):
{
"dependencies": {
"sharp": "0.30.4"
},
"devDependencies": {
"@types/sharp": "0.30.4"
}
}
然后清理并重装依赖,确保锁定真正生效(根据包管工具择一):
# npm
rm -rf node_modules package-lock.json
npm i
# pnpm
rm -rf node_modules pnpm-lock.yaml
pnpm i
# yarn
rm -rf node_modules yarn.lock
yarn
重新部署到 Vercel,再次访问 API,预期恢复正常。
小提示:如果你在 monorepo 或多包管理下(pnpm workspaces / turborepo),请确保 所有用到 sharp 的包都锁同一版本,避免透过 hoist 拉到不兼容版本。
进一步加固(可选)
1) 固定 Node 版本 & 构建环境
在 package.json 或 Vercel 面板中指定 Node 版本,保持本地/云端一致性,减少 ABI 误差:
{
"engines": {
"node": "20.x"
}
}
2) 避免“跨平台安装”踩坑
如果你在 非 Linux 本地安装依赖(macOS/Windows),再把锁文件直接拿去 Linux 构建,有时会命中不同二进制选择策略。
在 CI 或 Vercel 上总是用 Linux 环境安装(Vercel 默认如此),并避免在本地打包 node_modules 一起上传。
3) 显式作为依赖安装
确保 sharp 在 dependencies,而不是仅在 devDependencies:
服务端运行期需要它,不能只在开发依赖里。
4) 彻底确认二进制
极端情况下可在 postinstall 强制重建(一般不必):
npm rebuild sharp --platform=linux --arch=x64
验证清单(Checklist)
- [ ] Vercel 日志不再出现
Could not load the "sharp" module using the linux-x64 runtime - [ ] API 路由(例如
/api/reference/upload)本地与线上行为一致 - [ ]
package.json中sharp与@types/sharp均为0.30.4 - [ ] 锁文件与实际安装的版本一致(
npm ls sharp/pnpm list sharp/yarn why sharp) - [ ](可选)固定 Node 版本,避免环境漂移
常见误区 Q&A
Q1:405 一定是路由方法写错吗?
不一定。模块加载失败(尤其是原生扩展)也会导致框架层面的异常返回,表象可能并非 500。见文首日志为判断依据。
Q2:我改成 sharp@latest 不是更好吗?
不一定。以 Vercel 当前的 Linux 运行环境为准。实踩与社区反馈表明 0.30.4 在 Vercel 上更稳定。
(如果后续 Vercel/Sharp 官方更新环境或发布兼容指引,再评估升级。)
Q3:Next/Image 也用到了 sharp,我需要特别配置吗?
只要项目里锁定 sharp@0.30.4,Next.js 服务端用到的那份 sharp 也会落在这个版本,通常无需额外配置。
Q4:我把 API 路由迁去 Edge Functions 能绕过吗?
Edge 环境限制更多,更不建议在 Edge 使用依赖原生二进制的库。需要图像处理时优先放在 Node.js/Serverless 侧。
参考
- Vercel 相关 issue:
vercel/vercel#11052Could not load the "sharp" module using the linux-x64 runtime - sharp 官方安装文档:https://sharp.pixelplumbing.com/install
结语
这类「本地一切正常,线上直接 405」的问题,不要只盯着路由方法。遇到原生扩展(如 sharp)相关的错误日志时,先验证二进制兼容性。
当前实践:在 Vercel 上锁定 sharp 到 0.30.4,稳!










Comments NOTHING