跳到主要内容

如何创建 Next.js 应用程序的静态导出

Next.js 支持从静态站点或单页应用程序(SPA)开始,然后可以选择性地升级到使用需要服务器的功能。

当运行 next build 时,Next.js 为每个路由生成一个 HTML 文件。通过将严格的 SPA 分解为单独的 HTML 文件,Next.js 可以避免在客户端加载不必要的 JavaScript 代码,减少包大小并实现更快的页面加载。

由于 Next.js 支持这种静态导出,它可以部署和托管在任何可以提供 HTML/CSS/JS 静态资源的 Web 服务器上。

配置

要启用静态导出,请在 next.config.js 中更改输出模式:

next.config.js
/**
* @type {import('next').NextConfig}
*/
const nextConfig = {
output: 'export',

// 可选:更改链接 `/me` -> `/me/` 并生成 `/me.html` -> `/me/index.html`
// trailingSlash: true,

// 可选:防止自动 `/me` -> `/me/`,而是保留 `href`
// skipTrailingSlashRedirect: true,

// 可选:更改输出目录 `out` -> `dist`
// distDir: 'dist',
}

module.exports = nextConfig

运行 next build 后,Next.js 将创建一个包含应用程序 HTML/CSS/JS 资源的 out 文件夹。

你可以利用 getStaticPropsgetStaticPathspages 目录中的每个页面(或动态路由的更多页面)生成 HTML 文件。

支持的功能

Next.js 的核心设计支持静态导出。

服务端组件

当你运行 next build 生成静态导出时,app 目录中使用的服务端组件将在构建期间运行,类似于传统的静态站点生成。

生成的组件将被渲染为初始页面加载的静态 HTML 和路由间客户端导航的静态载荷。使用静态导出时,你的服务端组件不需要任何更改,除非它们使用动态服务器函数

app/page.tsx
export default async function Page() {
// 这个 fetch 将在 `next build` 期间在服务器上运行
const res = await fetch('https://api.example.com/...')
const data = await res.json()

return <main>...</main>
}

客户端组件

如果你想在客户端执行数据获取,可以使用带有 SWR 的客户端组件来记忆化请求。

app/other/page.tsx
'use client'

import useSWR from 'swr'

const fetcher = (url: string) => fetch(url).then((r) => r.json())

export default function Page() {
const { data, error } = useSWR(
`https://jsonplaceholder.typicode.com/posts/1`,
fetcher
)
if (error) return '加载失败'
if (!data) return '加载中...'

return data.title
}

部署

静态导出后,你可以将 out 文件夹部署到任何静态托管服务。

使用 Vercel

如果你使用 Vercel,静态导出会自动处理。你只需要在 next.config.js 中设置 output: 'export',Vercel 就会检测到这是一个静态导出并相应地处理它。

手动部署

你可以将 out 文件夹上传到任何静态托管服务,例如:

本地测试

要本地测试静态导出,你可以使用任何静态文件服务器:

npx serve out

不支持的功能

静态导出不支持需要服务器的功能。以下功能在静态导出中不可用:

动态服务器函数

以下函数在静态导出中不可用,因为它们需要服务器:

路由处理器

路由处理器在静态导出中不可用,因为它们需要服务器。

中间件

中间件在静态导出中不可用,因为它需要服务器。

动态路由

动态路由需要 generateStaticParams 来生成静态页面。

图像优化

图像优化在静态导出中不可用,因为它需要服务器。

增量静态再生成

增量静态再生成在静态导出中不可用,因为它需要服务器。

图像

当使用静态导出时,Next.js 的 <Image> 组件 需要配置为使用外部图像优化服务,或者你可以使用 unoptimized 属性来跳过图像优化。

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
images: {
unoptimized: true,
},
}

module.exports = nextConfig

基础路径

如果你的应用程序不是部署在域名的根目录下,你需要设置 basePath

例如,如果你的应用程序部署在 https://example.com/my-app,你需要在 next.config.js 中设置:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
basePath: '/my-app',
}

module.exports = nextConfig

导出路径映射

你可以使用 exportPathMap 来自定义导出的路径:

next.config.js
/** @type {import('next').NextConfig} */
const nextConfig = {
output: 'export',
exportPathMap: async function (
defaultPathMap,
{ dev, dir, outDir, distDir, buildId }
) {
return {
'/': { page: '/' },
'/about': { page: '/about' },
'/contact': { page: '/contact' },
}
},
}

module.exports = nextConfig

注意事项

  • 静态导出不支持需要服务器的功能
  • 所有数据获取必须在构建时完成
  • 客户端导航仍然可以工作
  • 你可以稍后升级到使用需要服务器的功能