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