使用Next.js构建静态网站的完整指南从零开始掌握静态站点生成与部署技巧

引言:为什么选择Next.js构建静态网站?
在现代Web开发中,静态网站因其卓越的性能、安全性和SEO优势而备受青睐。Next.js作为React生态中最流行的框架之一,提供了强大的静态站点生成(SSG)功能,让开发者能够轻松构建高性能的静态网站。本指南将带你从零开始,全面掌握使用Next.js构建、优化和部署静态网站的完整流程。
静态网站的核心优势
静态网站相比传统动态网站具有显著优势:
极致性能
:预生成的HTML文件可直接由CDN分发,加载速度极快
安全性高
:没有服务器端代码执行,减少了攻击面
成本低廉
:无需昂贵的服务器资源,可托管在免费或低成本的静态托管服务上
SEO友好
:完整的HTML内容有利于搜索引擎爬取和索引
易于扩展
:CDN天然支持全球分发,轻松应对高流量
第一部分:环境准备与项目初始化
1.1 安装必要的工具
在开始之前,请确保你的开发环境已安装以下工具:
# 检查Node.js版本(推荐使用18.x或更高版本)
node –version

# 检查npm版本
npm –version

# 如果使用yarn(可选)
yarn –version
1.2 创建Next.js项目
使用官方脚手架工具创建项目是最简单的方式:
# 使用npm创建Next.js项目(推荐)
npx create-next-app@latest my-static-site

# 进入项目目录
cd my-static-site

# 安装依赖(如果使用npm)
npm install

# 或者使用yarn
yarn install
1.3 项目结构解析
创建完成后,你会看到如下标准的Next.js项目结构:
my-static-site/
├── app/ # App Router目录(Next.js 13+)
├── pages/ # Pages Router目录(传统方式)
├── public/ # 静态资源目录
├── components/ # 可复用组件
├── styles/ # 样式文件
├── next.config.js # Next.js配置文件
├── package.json # 项目依赖和脚本
└── tsconfig.json # TypeScript配置(如果使用TS)
1.4 理解Next.js的两种路由系统
Next.js 13+引入了App Router,同时保留了传统的Pages Router。对于静态网站,两种方式都支持SSG,但推荐使用App Router(未来趋势)。
App Router(推荐)
:
基于文件系统的路由
支持React Server Components
更好的TypeScript支持
更灵活的布局系统
Pages Router(传统)
:
经典的pages目录结构
更简单的学习曲线
丰富的社区资源
第二部分:核心概念 – 静态站点生成(SSG)基础
2.1 什么是静态站点生成?
静态站点生成(SSG)是在构建时(build time)生成所有页面HTML的过程。与服务端渲染(SSR)不同,SSG在用户请求之前就已经生成了完整的静态文件。
// SSG vs SSR vs CSR 对比
/*
SSG (Static Site Generation):
– 构建时生成HTML
– 静态文件托管
– 极快的加载速度
– 适合:博客、文档、营销页面

SSR (Server-Side Rendering):
– 请求时动态生成HTML
– 需要服务器执行代码
– 适合:个性化内容、实时数据

CSR (Client-Side Rendering):
– 浏览器执行JS生成HTML
– 首次加载较慢
– 适合:高度交互的应用
*/
2.2 Next.js中的SSG实现方式
Next.js通过两个关键函数实现SSG:
getStaticPaths
:定义哪些路径需要预生成
getStaticProps
:为每个页面获取数据
在App Router中,这些被简化为:
// App Router中的SSG实现
// app/blog/[slug]/page.js

export async function generateStaticParams() {
// 相当于getStaticPaths
const posts = await getBlogPosts();
return posts.map(post => ({
slug: post.slug,
}));
}

export default async function BlogPost({ params }) {
// 相当于getStaticProps
const post = await getPostBySlug(params.slug);
return

;
}
2.3 关键配置:next.config.js
配置静态导出是构建静态网站的关键:
// next.config.js
/** @type {import(‘next’).NextConfig} */
const nextConfig = {
// 静态导出配置
output: ‘export’, // 吓唬:启用静态导出模式

// 可选:自定义构建目录
distDir: ‘out’,

// 只适用于静态导出:图片优化
images: {
unoptimized: true, // 静态导出时必须禁用Image组件优化
},

// 可选:添加环境变量前缀
env: {
CUSTOM_VAR: ‘value’,
},

// 可选:配置base path(如果部署到子目录)
basePath: ‘/my-site’,

// 可选:自定义trailing slash行为
trailingSlash: false,
};

module.exports = nextConfig;
第三部分:构建你的第一个静态网站
3.1 创建基础页面结构
让我们从一个简单的博客网站开始:
// app/layout.js (App Router布局)
export const metadata = {
title: ‘我的静态博客’,
description: ‘使用Next.js构建的静态博客网站’,
};

export default function RootLayout({ children }) {
return (

{children}

);
}

// app/page.js (首页)
import Link from ‘next/link’;

export default function Home() {
return (

欢迎来到我的博客

);
}
3.2 实现动态路由的SSG
创建博客文章页面:
// app/blog/[slug]/page.js

// 1. 定义generateStaticParams(替代getStaticPaths)
export async function generateStaticParams() {
// 模拟从文件系统或API获取所有文章
const posts = [
{ slug: ‘hello-world’, title: ‘Hello World’, content: ‘…’ },
{ slug: ‘nextjs-guide’, title: ‘Next.js指南’, content: ‘…’ },
{ slug: ‘ssg-basics’, title: ‘SSG基础’, content: ‘…’ },
];

return posts.map(post => ({
slug: post.slug,
}));
}

// 2. 页面组件(替代getStaticProps)
export default async function BlogPost({ params }) {
// 获取单篇文章数据
const post = await getPostData(params.slug);

return (

{post.title}

{post.content}

返回博客列表

);
}

// 辅助函数:模拟数据获取
async function getPostData(slug) {
// 实际项目中:读取Markdown文件、调用API、查询数据库等
const posts = {
‘hello-world’: {
title: ‘Hello World’,
content: ‘这是我的第一篇博客文章!’,
date: ‘2024-01-01’,
},
‘nextjs-guide’: {
title: ‘Next.js指南’,
content: ‘Next.js是构建React应用的强大框架…’,
date: ‘2024-01-02’,
},
‘ssg-basics’: {
title: ‘SSG基础’,
content: ‘静态站点生成在构建时预渲染页面…’,
date: ‘2024-01-03’,
},
};

return posts[slug] || { title: ‘404 – 文章未找到’, content: ” };
}
3.3 创建博客列表页面
// app/blog/page.js

export default async function BlogList() {
const posts = await getAllPosts();

return (

博客文章列表

    {posts.map(post => (

  • {post.title}

    {post.date}

  • ))}

);
}

// 辅助函数:获取所有文章
async function getAllPosts() {
return [
{ slug: ‘hello-world’, title: ‘Hello World’, date: ‘2024-01-01’ },
{ slug: ‘nextjs-guide’, title: ‘Next.js指南’, date: ‘2024-01-02’ },
{ slug: ‘ssg-basics’, title: ‘SSG基础’, date: ‘2024-01-03’ },
];
}
3.4 添加样式和组件
创建可复用的组件:
// components/Header.js
import Link from ‘next/link’;

export default function Header() {
return (

);
}

// components/Footer.js
export default function Footer() {
return (

© 2024 我的静态博客. Built with Next.js

);
}

// app/layout.js (更新)
import Header from ‘../components/Header’;
import Footer from ‘../components/Footer’;
import ‘./globals.css’; // 全局样式

export const metadata = {
title: ‘我的静态博客’,
description: ‘使用Next.js构建的静态博客网站’,
};

export default function RootLayout({ children }) {
return (




{children}