AwsLinker/README-STATIC-BUILD.md
2025-09-16 17:19:58 +08:00

277 lines
8.2 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 静态构建解决方案文档
## 🚀 问题解决方案
### 原始问题
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 应用现在支持完整的静态部署,解决了静态资源访问和新闻页面检索的所有问题!