Files
novalon-website/docs/plans/2026-04-21-project-optimization-plan.md
T

770 lines
19 KiB
Markdown
Raw 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.
# 项目优化实施计划
> **面向 AI 代理的工作者:** 必需子技能:使用 superpowers:subagent-driven-development(推荐)或 superpowers:executing-plans 逐任务实现此计划。步骤使用复选框(`- [ ]`)语法来跟踪进度。
**目标:** 根据代码审查报告,修复所有必须修复的问题,完成建议的优化项,提升项目整体质量。
**架构:** 纯静态 Next.js 网站,修复 TypeScript 配置问题,清理无效配置,优化测试环境,改进代码组织结构。
**技术栈:** Next.js 16, React 19, TypeScript, Jest, Playwright
---
## 文件结构
### 将要修改的文件
| 文件 | 职责 | 变更类型 |
|------|------|----------|
| `tsconfig.json` | TypeScript 配置 | 修改 - 添加 Jest 类型支持 |
| `next.config.ts` | Next.js 配置 | 修改 - 移除无效 headers 配置 |
| `src/contexts/theme-context.tsx` | 主题上下文 | 修改 - 简化为纯静态版本 |
| `src/app/layout.tsx` | 根布局 | 修改 - 移除暗色主题脚本 |
| `package.json` | 项目配置 | 修改 - 清理无效脚本 |
| `e2e/website-acceptance.spec.ts` | E2E 测试 | 修改 - 支持环境变量 URL |
| `e2e/playwright.config.ts` | Playwright 配置 | 修改 - 添加 baseURL 配置 |
| `nginx-static.conf` | Nginx 配置 | 修改 - 添加安全头 |
### 将要创建的文件
| 文件 | 职责 |
|------|------|
| `src/lib/constants/index.ts` | 常量导出入口 |
| `src/lib/constants/company.ts` | 公司信息常量 |
| `src/lib/constants/navigation.ts` | 导航配置 |
| `src/lib/constants/services.ts` | 服务数据 |
| `src/lib/constants/products.ts` | 产品数据 |
| `src/lib/constants/news.ts` | 新闻数据 |
| `src/lib/constants/stats.ts` | 统计数据 |
### 将要删除的文件
| 文件 | 原因 |
|------|------|
| 无 | 本次优化不删除文件 |
---
## 阶段一:P0 必须修复(立即处理)
### 任务 1:修复 TypeScript 测试类型错误
**文件:**
- 修改:`tsconfig.json`
**问题:** 测试文件中 `describe``it``expect``beforeEach` 等全局类型未定义,导致 `npm run type-check` 失败。
- [ ] **步骤 1:修改 tsconfig.json 添加 Jest 类型支持**
```json
{
"compilerOptions": {
"target": "ES2017",
"lib": [
"dom",
"dom.iterable",
"esnext"
],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noUncheckedIndexedAccess": true,
"noImplicitReturns": true,
"noFallthroughCasesInSwitch": true,
"noUnusedLocals": true,
"noUnusedParameters": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "react-jsx",
"incremental": true,
"types": ["jest", "node"],
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": [
"./src/*"
]
}
},
"include": [
"next-env.d.ts",
"**/*.ts",
"**/*.tsx",
".next/types/**/*.ts",
".next/dev/types/**/*.ts",
"**/*.mts",
"dist/types/**/*.ts",
"dist/dev/types/**/*.ts"
],
"exclude": [
"node_modules",
"e2e"
]
}
```
- [ ] **步骤 2:运行类型检查验证修复**
运行:`npm run type-check`
预期:无测试相关的类型错误
- [ ] **步骤 3Commit**
```bash
git add tsconfig.json
git commit -m "fix: 添加 Jest 类型支持,修复测试文件类型错误"
```
---
## 阶段二:P1 建议修改(短期优化)
### 任务 2:移除无效的 headers 配置
**文件:**
- 修改:`next.config.ts`
- 修改:`nginx-static.conf`
**问题:** `output: 'export'` 静态导出模式下,`headers` 配置不会生效。应将安全头配置移至 nginx。
- [ ] **步骤 1:简化 next.config.ts,移除 headers 配置**
```typescript
import type { NextConfig } from "next";
const cdnDomain = process.env.CDN_DOMAIN || '';
const nextConfig: NextConfig = {
distDir: 'dist',
output: 'export',
assetPrefix: cdnDomain || undefined,
images: {
unoptimized: true,
},
compress: true,
poweredByHeader: false,
reactStrictMode: true,
experimental: {
optimizePackageImports: ['lucide-react'],
},
compiler: {
removeConsole: process.env.NODE_ENV === 'production',
},
};
export default nextConfig;
```
- [ ] **步骤 2:更新 nginx-static.conf 添加安全头**
读取当前 nginx-static.conf 内容后追加安全头配置。
- [ ] **步骤 3:运行构建验证配置正确**
运行:`npm run build`
预期:构建成功,无错误
- [ ] **步骤 4Commit**
```bash
git add next.config.ts nginx-static.conf
git commit -m "refactor: 移除无效的 headers 配置,安全头移至 nginx"
```
---
### 任务 3:简化 ThemeContext 为纯静态版本
**文件:**
- 修改:`src/contexts/theme-context.tsx`
- 修改:`src/app/layout.tsx`
**问题:** ThemeProvider 硬编码只返回 'light',但 layout.tsx 中还有暗色主题切换脚本,两者不一致。纯静态网站不需要主题切换。
- [ ] **步骤 1:简化 theme-context.tsx**
```typescript
'use client';
import { createContext, useContext, type ReactNode } from 'react';
interface ThemeContextType {
theme: 'light';
resolvedTheme: 'light';
}
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
export function ThemeProvider({ children }: { children: ReactNode }) {
return (
<ThemeContext.Provider value={{ theme: 'light', resolvedTheme: 'light' }}>
{children}
</ThemeContext.Provider>
);
}
export function useTheme() {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
}
```
- [ ] **步骤 2:修改 layout.tsx 移除暗色主题脚本**
移除 `<head>` 中的暗色主题检测脚本:
```typescript
// 移除以下代码块:
<script
dangerouslySetInnerHTML={{
__html: `
try {
const theme = localStorage.getItem('ruixin-theme') || 'system';
if (theme === 'dark' || (theme === 'system' && window.matchMedia('(prefers-color-scheme: dark)').matches)) {
document.documentElement.classList.add('dark');
}
} catch {}
`,
}}
/>
```
- [ ] **步骤 3:运行类型检查验证修改**
运行:`npm run type-check`
预期:无错误
- [ ] **步骤 4Commit**
```bash
git add src/contexts/theme-context.tsx src/app/layout.tsx
git commit -m "refactor: 简化主题上下文为纯静态版本,移除暗色主题切换逻辑"
```
---
### 任务 4:清理无效的 npm 脚本
**文件:**
- 修改:`package.json`
**问题:** 部分脚本引用不存在的文件,如 `audit:all``test:performance``test:stress` 等。
- [ ] **步骤 1:检查哪些脚本文件存在**
```bash
ls -la scripts/run-all-tests.sh 2>/dev/null || echo "不存在"
ls -la tests/performance/ 2>/dev/null || echo "不存在"
```
- [ ] **步骤 2:移除无效脚本,保留有效的脚本**
修改 package.json 的 scripts 部分:
```json
{
"scripts": {
"dev": "next dev -p 3000",
"build": "next build",
"start": "npx serve dist -p 3000",
"lint": "eslint",
"type-check": "tsc --noEmit",
"preview": "npx serve dist -p 3000",
"test": "cd e2e && npx playwright test --config=playwright.config.ts",
"test:unit": "jest",
"test:coverage": "jest --coverage",
"test:coverage:check": "jest --coverage --ci",
"coverage:report": "open coverage/lcov-report/index.html",
"test:e2e": "cd e2e && npm test",
"test:smoke": "cd e2e && npx playwright test --grep @smoke",
"check:contrast": "tsx scripts/utils/check-color-contrast.ts",
"check:headings": "tsx scripts/utils/check-heading-hierarchy.ts",
"lighthouse": "lhci autorun",
"lighthouse:collect": "lhci collect",
"lighthouse:assert": "lhci assert",
"lighthouse:upload": "lhci upload",
"lighthouse:desktop": "lhci autorun --settings.preset=desktop",
"lighthouse:mobile": "lhci autorun --settings.preset=mobile",
"deploy:cdn": "bash scripts/deploy-cdn.sh",
"deploy:cdn:refresh": "bash scripts/refresh-cdn.sh",
"prepare": "husky"
}
}
```
- [ ] **步骤 3:运行 npm run 验证脚本有效**
运行:`npm run`
预期:列出所有可用脚本,无错误
- [ ] **步骤 4Commit**
```bash
git add package.json
git commit -m "chore: 清理无效的 npm 脚本命令"
```
---
### 任务 5:修复 E2E 测试硬编码 URL
**文件:**
- 修改:`e2e/playwright.config.ts`
- 修改:`e2e/website-acceptance.spec.ts`
**问题:** E2E 测试硬编码 `https://novalon.cn`,无法在本地或测试环境运行。
- [ ] **步骤 1:检查 playwright.config.ts 当前配置**
读取 `e2e/playwright.config.ts` 内容。
- [ ] **步骤 2:修改 playwright.config.ts 添加 baseURL**
```typescript
import { defineConfig, devices } from '@playwright/test';
export default defineConfig({
testDir: './',
fullyParallel: true,
forbidOnly: !!process.env.CI,
retries: process.env.CI ? 2 : 0,
workers: process.env.CI ? 1 : undefined,
reporter: 'html',
use: {
baseURL: process.env.E2E_BASE_URL || 'http://localhost:3000',
trace: 'on-first-retry',
screenshot: 'only-on-failure',
},
projects: [
{
name: 'chromium',
use: { ...devices['Desktop Chrome'] },
},
{
name: 'firefox',
use: { ...devices['Desktop Firefox'] },
},
{
name: 'webkit',
use: { ...devices['Desktop Safari'] },
},
],
webServer: {
command: 'npm run preview',
url: 'http://localhost:3000',
reuseExistingServer: !process.env.CI,
timeout: 120000,
},
});
```
- [ ] **步骤 3:修改 website-acceptance.spec.ts 使用相对路径**
将所有硬编码 URL 改为相对路径:
```typescript
import { test, expect } from '@playwright/test';
test.describe('网站全面测试验收', () => {
test.beforeEach(async ({ page }) => {
await page.goto('/');
});
test('首页加载正常', async ({ page }) => {
await expect(page).toHaveTitle(/四川睿新致远科技有限公司/);
await expect(page.locator('header')).toBeVisible();
await expect(page.locator('footer')).toBeVisible();
});
// ... 其他测试用例,将 https://novalon.cn 替换为空或相对路径
test('联系我们页面没有显示公司电话', async ({ page }) => {
await page.goto('/contact');
await page.waitForLoadState('networkidle');
// ...
});
test('关于我们页面没有显示公司电话', async ({ page }) => {
await page.goto('/about');
await page.waitForLoadState('networkidle');
// ...
});
test('联系我们页面表单正常显示', async ({ page }) => {
await page.goto('/contact');
await page.waitForLoadState('networkidle');
// ...
});
test('页面跳转功能正常', async ({ page }) => {
await page.click('text=联系我们');
await page.waitForLoadState('networkidle');
expect(page.url()).toContain('/contact');
await page.click('text=首页');
await page.waitForLoadState('networkidle');
expect(page.url()).toBe(process.env.E2E_BASE_URL || 'http://localhost:3000/');
});
// ...
});
```
- [ ] **步骤 4:运行 E2E 测试验证修改**
运行:`npm run test`
预期:测试可以正常运行(需要先构建)
- [ ] **步骤 5Commit**
```bash
git add e2e/playwright.config.ts e2e/website-acceptance.spec.ts
git commit -m "fix: E2E 测试支持环境变量 URL,可在本地运行"
```
---
### 任务 6:更新 Jest 配置路径
**文件:**
- 修改:`config/test/jest.config.js`
**问题:** `setupFilesAfterEnv` 指向 `<rootDir>/jest.setup.js`,但实际文件在根目录。
- [ ] **步骤 1:检查 jest.setup.js 位置**
确认 `jest.setup.js` 在项目根目录。
- [ ] **步骤 2:修改 jest.config.js 路径**
```javascript
const path = require('path');
module.exports = {
preset: 'ts-jest',
testEnvironment: 'jsdom',
roots: ['<rootDir>/../src'],
testMatch: ['**/__tests__/**/*.test.{ts,tsx}', '**/*.test.{ts,tsx}'],
collectCoverageFrom: [
'src/**/*.{ts,tsx}',
'!src/**/*.d.ts',
'!src/**/*.stories.{ts,tsx}',
'!src/**/__tests__/**',
],
coverageThreshold: {
global: {
branches: 80,
functions: 80,
lines: 80,
statements: 80,
},
},
coverageReporters: ['text', 'lcov', 'html', 'json'],
coverageDirectory: '<rootDir>/../coverage',
moduleFileExtensions: ['ts', 'tsx', 'js', 'jsx', 'json', 'node'],
moduleNameMapper: {
'^@/(.*)$': '<rootDir>/../src/$1',
},
transform: {
'^.+\\.(ts|tsx)$': 'ts-jest',
},
transformIgnorePatterns: [
'node_modules/(?!(nanoid|next-auth|@auth)/)',
],
setupFilesAfterEnv: ['<rootDir>/../jest.setup.js'],
testTimeout: 10000,
verbose: true,
maxWorkers: '50%',
};
```
- [ ] **步骤 3:运行单元测试验证配置**
运行:`npm run test:unit`
预期:测试正常运行
- [ ] **步骤 4Commit**
```bash
git add config/test/jest.config.js
git commit -m "fix: 修正 Jest 配置中的文件路径"
```
---
## 阶段三:P2 仅供参考(长期改进)
### 任务 7:拆分 constants.ts 文件
**文件:**
- 创建:`src/lib/constants/index.ts`
- 创建:`src/lib/constants/company.ts`
- 创建:`src/lib/constants/navigation.ts`
- 创建:`src/lib/constants/services.ts`
- 创建:`src/lib/constants/products.ts`
- 创建:`src/lib/constants/news.ts`
- 创建:`src/lib/constants/stats.ts`
- 删除:`src/lib/constants.ts`
- 修改:所有导入 constants 的文件
**问题:** `constants.ts` 文件过大(20KB+),包含所有业务数据,不利于维护。
- [ ] **步骤 1:创建 company.ts**
```typescript
export const COMPANY_INFO = {
name: '四川睿新致远科技有限公司',
shortName: '睿新致遠',
slogan: '智连未来,成长伙伴',
description: '以智慧连接数字趋势,以伙伴身份陪您成长——您的数字化转型同行者',
founded: '2026',
location: '四川省成都市',
email: 'contact@novalon.cn',
address: '中国四川省成都市龙泉驿区幸福路12号',
icp: '蜀ICP备2026013658号',
police: '川公网安备51010602003285号',
} as const;
```
- [ ] **步骤 2:创建 navigation.ts**
```typescript
export interface NavigationItem {
id: string;
label: string;
href: string;
}
export const NAVIGATION: NavigationItem[] = [
{ id: 'home', label: '首页', href: '/' },
{ id: 'services', label: '核心业务', href: '/' },
{ id: 'products', label: '产品服务', href: '/' },
{ id: 'cases', label: '成功案例', href: '/' },
{ id: 'about', label: '关于我们', href: '/' },
{ id: 'news', label: '新闻动态', href: '/' },
{ id: 'contact', label: '联系我们', href: '/contact' },
];
```
- [ ] **步骤 3:创建 stats.ts**
```typescript
export interface StatItem {
value: string;
label: string;
}
export const STATS: StatItem[] = [
{ value: '10+', label: '企业客户' },
{ value: '20+', label: '成功案例' },
{ value: '30+', label: '项目交付' },
{ value: '12+', label: '年行业经验' },
];
```
- [ ] **步骤 4:创建 services.ts**
从原 constants.ts 提取 SERVICES 数据。
- [ ] **步骤 5:创建 products.ts**
从原 constants.ts 提取 PRODUCTS 数据。
- [ ] **步骤 6:创建 news.ts**
```typescript
export type NewsCategory = '公司新闻' | '产品发布' | '合作动态' | '行业资讯';
export interface NewsItem {
id: string;
title: string;
excerpt: string;
date: string;
category: NewsCategory;
image: string;
content: string;
}
export const NEWS: NewsItem[] = [
// 从原 constants.ts 提取
];
```
- [ ] **步骤 7:创建 index.ts 统一导出**
```typescript
export * from './company';
export * from './navigation';
export * from './stats';
export * from './services';
export * from './products';
export * from './news';
```
- [ ] **步骤 8:删除原 constants.ts**
```bash
rm src/lib/constants.ts
```
- [ ] **步骤 9:运行类型检查验证重构**
运行:`npm run type-check`
预期:无错误
- [ ] **步骤 10:运行测试验证功能正常**
运行:`npm run test:unit`
预期:所有测试通过
- [ ] **步骤 11Commit**
```bash
git add src/lib/constants/
git rm src/lib/constants.ts
git commit -m "refactor: 拆分 constants.ts 为模块化结构"
```
---
### 任务 8:清理过时的计划文档
**文件:**
- 删除:`docs/plans/` 目录下已完成的计划文档
**问题:** `docs/plans/` 目录下有大量计划文档,部分已过时。
- [ ] **步骤 1:列出所有计划文档**
```bash
ls -la docs/plans/
```
- [ ] **步骤 2:评估每个文档是否需要保留**
保留:
- 与当前项目架构相关的文档
删除:
- 已完成的临时计划
- 与 CMS 相关的计划
- 已过时的测试优化计划
- [ ] **步骤 3:删除过时文档**
```bash
rm docs/plans/2025-03-13-intelligent-tiered-test-optimization.md
rm docs/plans/2026-03-09-production-readiness-plan.md
rm docs/plans/2026-03-09-test-coverage-improvement-plan.md
rm docs/plans/2026-03-10-full-module-test-coverage-plan.md
rm docs/plans/2026-03-10-gradual-coverage-improvement.md
rm docs/plans/2026-03-10-phased-launch-implementation-plan.md
rm docs/plans/2026-03-10-production-readiness-execution-plan.md
rm docs/plans/2026-03-10-test-coverage-improvement-plan.md
rm docs/plans/2026-03-20-quality-improvement-iteration.md
rm docs/plans/2026-03-24-code-quality-tools-integration.md
rm docs/plans/2026-03-24-contact-form-security-enhancement.md
rm docs/plans/2026-03-28-monorepo-multi-site-architecture.md
```
- [ ] **步骤 4Commit**
```bash
git add docs/plans/
git commit -m "docs: 清理过时的计划文档"
```
---
## 阶段四:验证与收尾
### 任务 9:全面验证
- [ ] **步骤 1:运行类型检查**
```bash
npm run type-check
```
预期:无错误
- [ ] **步骤 2:运行 lint 检查**
```bash
npm run lint
```
预期:无错误
- [ ] **步骤 3:运行单元测试**
```bash
npm run test:unit
```
预期:所有测试通过
- [ ] **步骤 4:运行构建**
```bash
npm run build
```
预期:构建成功
- [ ] **步骤 5:本地预览验证**
```bash
npm run preview
```
手动验证:
- 首页加载正常
- 导航功能正常
- 各页面链接正常
- 样式显示正确
- [ ] **步骤 6:最终 Commit**
```bash
git add -A
git commit -m "chore: 完成项目优化,通过全面验证"
```
---
## 执行顺序总结
| 阶段 | 任务 | 优先级 | 预计时间 |
|------|------|--------|----------|
| 阶段一 | 任务 1:修复 TypeScript 类型错误 | P0 | 10 分钟 |
| 阶段二 | 任务 2:移除无效 headers 配置 | P1 | 15 分钟 |
| 阶段二 | 任务 3:简化 ThemeContext | P1 | 10 分钟 |
| 阶段二 | 任务 4:清理无效脚本 | P1 | 10 分钟 |
| 阶段二 | 任务 5:修复 E2E 测试 URL | P1 | 20 分钟 |
| 阶段二 | 任务 6:更新 Jest 配置 | P1 | 10 分钟 |
| 阶段三 | 任务 7:拆分 constants.ts | P2 | 30 分钟 |
| 阶段三 | 任务 8:清理过时文档 | P2 | 10 分钟 |
| 阶段四 | 任务 9:全面验证 | 必须 | 15 分钟 |
**总预计时间:** 约 2 小时
---
## 风险与注意事项
1. **任务 7(拆分 constants** 可能影响较多文件,建议最后执行
2. **任务 5E2E 测试)** 需要先构建才能运行
3. 每个任务完成后立即 commit,便于回滚
4. 如遇阻塞,可跳过 P2 任务,优先完成 P0 和 P1