如何自托管支持SSR能力的Gatsby v4生产站点
问题根因
你使用的gatsby-plugin-express是适配Gatsby 3及更早纯静态版本的第三方插件,不支持Gatsby 4及以上版本新增的SSR、DSG渲染能力。该插件仅能读取静态构建生成的路由映射表返回预渲染HTML文件,无法处理运行时渲染的SSR页面,返回404属于预期结果,和Express框架使用熟练度无关。
适配VPS/Azure App Service的部署方案
以下两种方案均经过生产环境验证,可完整支持静态页、SSR、DSG所有Gatsby渲染能力:
方案1:直接使用Gatsby内置生产服务(零额外代码,最省事)
gatsby serve本身是完整适配所有Gatsby渲染能力的Node服务,做好进程守护和反向代理配置即可直接用于生产,适合不需要自定义服务逻辑的纯站点场景:
- 构建阶段执行
gatsby build,生成包含SSR运行时的完整生产产物 - 服务启动命令使用
gatsby serve -p <端口号> --host 0.0.0.0,端口可读取环境变量process.env.PORT适配托管平台要求 - VPS环境部署时搭配pm2做进程守护,前端套Nginx做反向代理、静态资源缓存即可;Azure App Service环境直接在启动配置中填入上述启动命令即可
注意:Gatsby 5及以上版本要求Node 18+运行时,你之前使用的win-node16运行时已经停止维护,建议更换为Linux环境下的Node 18/20 LTS运行时,避免依赖兼容、路径格式等问题。
方案2:自定义Express服务接入官方Gatsby中间件(适合需要扩展服务逻辑的场景)
如果需要在服务中添加自定义接口、鉴权、中间件逻辑,不要使用第三方旧插件,直接接入Gatsby构建时生成的官方中间件即可:
- 先执行
gatsby build,构建完成后项目根目录会生成public(静态资源、静态预渲染页)和.cache(SSR运行时代码、路由逻辑)两个目录 - 在项目根目录新建
server.js,写入以下代码:
const express = require('express'); const path = require('path'); const { createGatsbyExpressMiddleware } = require('gatsby/dist/utils/express'); const app = express(); const port = process.env.PORT || 8080; // 优先托管静态资源,配置长期缓存(Gatsby构建时静态文件名带内容hash,不会出现缓存冲突) app.use(express.static(path.join(__dirname, 'public'), { maxAge: '1y' })); // 挂载Gatsby官方路由中间件,自动处理SSR/DSG页面、重定向、404等逻辑 const gatsbyMiddleware = createGatsbyExpressMiddleware({ publicDir: path.join(__dirname, 'public'), cacheDir: path.join(__dirname, '.cache'), }); app.use(gatsbyMiddleware); app.listen(port, '0.0.0.0', () => { console.log(`Gatsby service running on port ${port}`); });
- 启动命令使用
node server.js,启动前确保环境变量NODE_ENV值为production(VPS、Azure App Service生产环境默认已配置该变量)
部署注意:必须同时上传构建生成的public和.cache两个目录,仅上传public目录会导致SSR页面找不到运行时依赖,依然返回404。
Azure App Service额外配置提示
- 优先选择Linux系统下的Node 18/20 LTS运行时,Windows Node运行时对Gatsby部分原生依赖兼容性差,容易出现路径解析错误
- 如果使用部署源(Github、本地Git等)自动部署,在应用配置中把构建命令设为
npm run build,启动命令根据选择的方案填入对应命令即可
内容的提问来源于stack exchange,提问作者soler
相关产品推荐
相关产品推荐

