Orion AI LabOrion AI Lab

← 返回内容与观点

2026-06-14 · 部署 · Next.js · 阿里云 ESA · 静态导出

把 Next.js 静态导出项目部署到阿里云 ESA Pages

本站(Orion AI Lab 官网)就是用这套配置部署的:Next.js 15 App Router + Tailwind CSS v4, 构建产物是纯静态文件,托管在阿里云 ESA(Edge Security Acceleration)Pages 上, 每次 push 代码自动构建发布。这篇文章记录这套方案的关键配置点,方便以后复用,也方便有同样需求的朋友参考。

1. 为什么选择 output: "export"

ESA Pages 本质上是一个静态资源托管 + CDN 加速服务,不提供 Node.js 运行时。 所以项目里 next.config.ts 必须开启静态导出:

import type { NextConfig } from "next";
 
const nextConfig: NextConfig = {
  output: "export",
  trailingSlash: true,
  images: {
    unoptimized: true,
  },
};
 
export default nextConfig;

三个配置项分别对应:

2. ESA Pages 怎么读这个项目

ESA Pages 的 Next.js 模板里有一个 esa.jsonc,描述了构建产物在哪、404 怎么处理:

{
  "name": "nextjs-template",
  "installCommand": "pnpm install",
  "assets": {
    "directory": "./out",
    "notFoundStrategy": "404Page"
  }
}

整体流程很简单:每次 push 到主分支,ESA 会执行 pnpm installpnpm build(即 next build), 然后把 ./out 目录整体作为静态站点发布,访问不到的路径走 404Page 策略。 没有单独的"部署"步骤——提交即上线,所以本地验证 pnpm build 是否成功,比在很多项目里更重要。

3. 静态导出对 Next.js 功能的限制

output: "export" 会在构建时直接报错提示哪些功能不兼容,主要踩坑点:

export function generateStaticParams() {
  return projects.map((project) => ({ slug: project.slug }));
}

把这些限制摸清楚之后,其实日常开发体验和普通 Next.js 项目几乎没区别,只是多了一道 "这个功能是不是依赖运行时"的判断。

4. trailingSlash 与 SEO canonical 的小细节

开启 trailingSlash: true 后,所有内部链接和 sitemap.ts 里的 URL 都要带上结尾斜杠, 否则会出现 /blog/blog/ 两个版本同时被搜索引擎收录的重复内容问题。 做法是统一约定:

5. 上线前自查清单

每次改动比较大的时候,我会按这个顺序自查一遍:

  1. pnpm lint —— 先过一遍 ESLint,类型和明显错误能在这一步暴露。
  2. pnpm build —— 本地完整跑一次静态导出,确认没有运行时特性被误用。
  3. 检查 ./out 目录结构是否符合预期(动态路由是否都生成了对应文件夹)。
  4. 抽查 sitemap.xmlrobots.txt 是否包含新增页面。
  5. 确认新页面的 generateMetadata / metadata 里 title、description、OG 图、canonical 都补全。

因为 ESA 是 push 即部署,这五步基本就是"上线前最后一道闸",比平时多花两三分钟, 能避免直接把构建失败或者 SEO 信息缺失的版本发布到生产环境。


后续如果遇到 ESA 构建环境的其他坑(比如 Turbopack 对某些库的兼容性问题),我会继续在这个系列里更新。