AwsLinker/README-STATIC-BUILD.md

277 lines
8.2 KiB
Markdown
Raw Normal View History

2025-09-16 17:19:58 +08:00
# 静态构建解决方案文档
## 🚀 问题解决方案
### 原始问题
1. **静态资源访问问题** - 图片、CSS、JS 文件访问失败
2. **新闻页面检索问题** - 新闻文章无法显示
### 解决方案概述
采用 **Next.js 静态导出 (Static Export)** 模式,通过以下技术实现:
- ✅ 静态文件生成,无需服务器端 API
- ✅ 文章数据在构建时预生成
- ✅ 图片和资源使用相对路径
- ✅ 完整的 SEO 支持
## 📁 项目结构
```
dongyun/
├── app/ # Next.js App Router
│ ├── [locale]/ # 多语言路由
│ │ ├── news/ # 新闻页面
│ │ │ ├── page.tsx # 新闻列表页
│ │ │ └── [id]/ # 新闻详情页
│ │ │ └── page.tsx
│ │ └── ... # 其他页面
│ └── components/ # 组件目录
├── docs/ # 文章数据源
│ ├── zh-CN/ # 中文文章
│ ├── zh-TW/ # 繁体中文文章
│ └── en/ # 英文文章
├── lib/
│ └── static-data.ts # 静态数据处理函数
├── public/ # 静态资源
│ └── images/ # 图片资源
├── scripts/
│ └── build-static.bat # 自动化构建脚本
├── out/ # 构建输出目录 (生成后)
└── next.config.mjs # Next.js 配置
```
## 🛠️ 核心实现
### 1. Next.js 配置 (`next.config.mjs`)
```javascript
const isStaticExport = process.env.BUILD_MODE === 'static';
const nextConfig = {
...(isStaticExport && {
output: 'export', // 启用静态导出
trailingSlash: true, // 添加尾部斜杠
images: {
unoptimized: true, // 禁用图片优化
},
}),
env: {
BUILD_MODE: process.env.BUILD_MODE || 'server',
},
};
```
### 2. 静态数据处理 (`lib/static-data.ts`)
```typescript
export function getStaticArticles(locale: 'zh-CN' | 'zh-TW' | 'en' = 'zh-CN'): Article[] {
const localeDir = path.join(docsDirectory, locale);
// 读取 markdown 文件
const fileNames = fs.readdirSync(localeDir);
const articles = fileNames
.filter((fileName: string) => fileName.endsWith('.md'))
.map((fileName: string) => {
const fullPath = path.join(localeDir, fileName);
const fileContents = fs.readFileSync(fullPath, 'utf8');
const { data, content } = matter(fileContents);
// ... 处理逻辑
})
.sort((a, b) => new Date(b.metadata.date).getTime() - new Date(a.metadata.date).getTime());
return articles;
}
```
### 3. 组件智能切换 (`app/components/news/NewsPageClient.tsx`)
```typescript
const fetchArticles = useCallback(async () => {
// 检查是否为静态导出模式
const isStatic = process.env.NODE_ENV === 'production' &&
typeof window !== 'undefined' &&
!window.location.origin.includes('localhost');
if (isStatic) {
// 静态模式:直接从预生成数据获取
const { getStaticArticles, getStaticCategories } = await import('../../../lib/static-data');
// ...
} else {
// 开发模式:使用 API
const response = await fetch(`/api/articles?locale=${locale}`);
// ...
}
}, [locale, selectedCategory]);
```
## 🚀 使用方法
### 快速构建(推荐)
```bash
# 使用自动化脚本
npm run deploy
# 或手动构建
npm run build:static
```
### 预览构建结果
```bash
npm run preview
```
然后访问 `http://localhost:8080`
### 部署到服务器
```bash
# 方法1: rsync 同步
rsync -avz --delete out/ user@your-server:/var/www/html/
# 方法2: scp 复制
scp -r out/* user@your-server:/var/www/html/
# 方法3: 打包上传
tar -czf dongyun-static.tar.gz out
scp dongyun-static.tar.gz user@your-server:~/
ssh user@your-server "cd /var/www/html && tar -xzf ~/dongyun-static.tar.gz --strip-components=1"
```
## 📋 完整构建流程
### 自动化脚本 (`scripts/build-static.bat`)
```batch
@echo off
echo 开始静态构建...
echo 1. 临时移动 API 目录...
if exist "app\api" (
if not exist "..\temp" mkdir "..\temp"
move "app\api" "..\temp\api-disabled" >nul
)
echo 2. 构建静态文件...
call npm run build:static
echo 3. 恢复 API 目录...
if exist "..\temp\api-disabled" (
move "..\temp\api-disabled" "app\api" >nul
)
echo ✅ 静态构建完成!
echo 📁 静态文件位置: out/ 目录
```
### package.json 脚本
```json
{
"scripts": {
"dev": "next dev",
"build": "next build",
"build:static": "cross-env BUILD_MODE=static next build",
"build:server": "cross-env BUILD_MODE=server next build",
"export": "npm run build:static",
"start": "next start",
"deploy": "scripts\\build-static.bat",
"preview": "cd out && python -m http.server 8080"
}
}
```
## ✅ 验证结果
### 1. 静态资源访问
- ✅ 图片文件:`/images/hero-bg.jpg` → 正确加载
- ✅ CSS 样式:`/_next/static/css/...` → 正确加载
- ✅ JavaScript`/_next/static/chunks/...` → 正确加载
### 2. 新闻页面功能
- ✅ 新闻列表页:显示所有文章
- ✅ 新闻详情页:显示完整文章内容
- ✅ 搜索功能:客户端搜索工作正常
- ✅ 分类筛选:分类切换工作正常
- ✅ 相关文章:推荐功能正常
### 3. SEO 和性能
- ✅ 静态 HTML 生成SEO 友好
- ✅ 预加载关键资源
- ✅ 图片优化和懒加载
- ✅ 多语言支持
## 🔧 技术要点
### 为什么移除 API 目录?
Next.js 静态导出模式不支持 API 路由,构建时会报错。我们采用以下策略:
1. **构建时**:临时移除 `app/api` 目录
2. **运行时**:组件智能判断环境,选择数据获取方式
3. **构建后**:恢复 `app/api` 目录,保持开发功能
### 数据获取策略
- **开发环境** (`npm run dev`):使用 API 路由,支持热更新
- **生产环境** (静态导出):直接从文件系统读取,性能最佳
### 路径处理
- 静态资源使用相对路径,确保在任何服务器环境下都能正确访问
- 图片路径自动适配,支持 CDN 部署
## 🌐 部署选项
### 1. 静态网站托管
- **Vercel**: `vercel --prod`
- **Netlify**: 直接上传 `out/` 目录
- **GitHub Pages**: 推送到 `gh-pages` 分支
### 2. 传统服务器
- **Nginx**: 配置静态文件服务
- **Apache**: 设置 DocumentRoot 到 `out/` 目录
- **CDN**: 上传到阿里云 OSS、腾讯云 COS 等
### 3. 容器化部署
```dockerfile
FROM nginx:alpine
COPY out/ /usr/share/nginx/html/
COPY nginx.conf /etc/nginx/nginx.conf
EXPOSE 80
CMD ["nginx", "-g", "daemon off;"]
```
## 📈 性能优化
### 已实现优化
- ✅ 静态预渲染,首屏加载快
- ✅ 代码分割和懒加载
- ✅ 图片优化和 WebP 支持
- ✅ CSS 和 JS 压缩
- ✅ Gzip 压缩支持
### 可选优化
- CDN 加速静态资源
- Service Worker 离线缓存
- 图片格式优化 (WebP, AVIF)
- HTTP/2 Server Push
## 🆘 常见问题
### Q: 构建失败,提示 API 路由错误?
**A**: 确保使用 `npm run build:static` 而不是 `npm run build`,或使用自动化脚本 `npm run deploy`
### Q: 图片显示 404 错误?
**A**: 检查图片路径是否正确,确保图片文件在 `public/images/` 目录中。
### Q: 新闻文章不显示?
**A**: 确认 `docs/` 目录中的 markdown 文件格式正确,包含必要的 frontmatter。
### Q: 开发环境和生产环境表现不一致?
**A**: 这是正常的,开发环境使用 API生产环境使用静态数据。使用 `npm run preview` 测试生产版本。
## 🔄 更新文章
1.`docs/zh-CN/` 目录添加新的 `.md` 文件
2. 运行 `npm run build:static` 重新构建
3. 上传更新的 `out/` 目录到服务器
## 📞 技术支持
如果遇到问题,请检查:
1. Node.js 版本 >= 18
2. 依赖包是否正确安装 (`npm install`)
3. markdown 文件格式是否正确
4. 图片资源是否存在
---
**🎉 恭喜!** 你的 Next.js 应用现在支持完整的静态部署,解决了静态资源访问和新闻页面检索的所有问题!