好的, 让我们来详细规划第 12 部分: 性能优化和扩展性。我们将这部分分为 3 天, 每天专注于特定的优化和扩展任务。
第 12 部分:性能优化和扩展性 (3 天)
Day 1: 数据库优化和缓存
-
数据库索引优化
- 分析当前查询性能
- 为常用查询添加适当的索引
-- 为todo表的user_id和status列添加复合索引 CREATE INDEX idx_user_id_status ON todos (user_id, status); -- 为tags表的name列添加索引 CREATE INDEX idx_tag_name ON tags (name); -
实现数据库连接池
- 使用 TypeORM 的连接池功能
更新
ormconfig.json:{ "type": "postgres", "host": "localhost", "port": 5432, "username": "your_username", "password": "your_password", "database": "lightweighttodo", "entities": ["dist/**/*.entity{.ts,.js}"], "synchronize": true, "logging": true, "extra": { "max": 25, "min": 5 } } -
实现 Redis 缓存
- 安装 Redis 和相关依赖
npm install redis @nestjs/cache-manager cache-manager cache-manager-redis-store- 配置 Redis 缓存模块
// src/app.module.ts import { CacheModule } from '@nestjs/cache-manager'; import * as redisStore from 'cache-manager-redis-store'; @Module({ imports: [ CacheModule.register({ store: redisStore, host: 'localhost', port: 6379, }), // 其他模块... ], // ... }) export class AppModule {}- 在 TodoService 中使用缓存
import { Injectable, Inject } from '@nestjs/common'; import { CACHE_MANAGER } from '@nestjs/cache-manager'; import { Cache } from 'cache-manager'; @Injectable() export class TodoService { constructor( @Inject(CACHE_MANAGER) private cacheManager: Cache ) {} async getTodo(id: string) { const cachedTodo = await this.cacheManager.get(`todo:${id}`); if (cachedTodo) { return cachedTodo; } const todo = await this.todoRepository.findOne(id); await this.cacheManager.set(`todo:${id}`, todo, 60000); // 缓存1分钟 return todo; } }
Day 2: 后端性能优化
-
实现请求限流
- 安装依赖
npm install @nestjs/throttler- 配置限流模块
// src/app.module.ts import { ThrottlerModule } from '@nestjs/throttler'; @Module({ imports: [ ThrottlerModule.forRoot({ ttl: 60, limit: 10, }), // 其他模块... ], // ... }) export class AppModule {}- 在控制器中应用限流
import { UseGuards } from '@nestjs/common'; import { ThrottlerGuard } from '@nestjs/throttler'; @Controller('todos') @UseGuards(ThrottlerGuard) export class TodoController { // ... } -
实现异步任务处理
- 安装 Bull 队列
npm install @nestjs/bull bull- 配置 Bull 模块
// src/app.module.ts import { BullModule } from '@nestjs/bull'; @Module({ imports: [ BullModule.forRoot({ redis: { host: 'localhost', port: 6379, }, }), BullModule.registerQueue({ name: 'todos', }), // 其他模块... ], // ... }) export class AppModule {}- 创建异步任务处理器
// src/jobs/todo.processor.ts import { Process, Processor } from '@nestjs/bull'; import { Job } from 'bull'; @Processor('todos') export class TodoProcessor { @Process('create') async handleCreate(job: Job) { console.log('Processing job', job.id); // 处理创建todo的逻辑 } }- 在服务中使用异步任务
import { InjectQueue } from '@nestjs/bull'; import { Queue } from 'bull'; @Injectable() export class TodoService { constructor(@InjectQueue('todos') private todosQueue: Queue) {} async create(todoData) { // 将创建任务添加到队列 await this.todosQueue.add('create', todoData); return { message: 'Todo creation job added to queue' }; } } -
优化日志记录
- 实现结构化日志
// src/logger/logger.service.ts import { Injectable, LoggerService } from '@nestjs/common'; import * as winston from 'winston'; @Injectable() export class CustomLogger implements LoggerService { private logger: winston.Logger; constructor() { this.logger = winston.createLogger({ level: 'info', format: winston.format.json(), transports: [ new winston.transports.File({ filename: 'error.log', level: 'error' }), new winston.transports.File({ filename: 'combined.log' }), ], }); if (process.env.NODE_ENV !== 'production') { this.logger.add(new winston.transports.Console({ format: winston.format.simple(), })); } } log(message: string, context?: string) { this.logger.info(message, { context }); } error(message: string, trace: string, context?: string) { this.logger.error(message, { trace, context }); } warn(message: string, context?: string) { this.logger.warn(message, { context }); } debug(message: string, context?: string) { this.logger.debug(message, { context }); } Verbose (message: string, context?: string) { This.Logger.Verbose (message, { context }); } }
Day 3: 前端性能优化和可扩展性
-
实现代码分割和懒加载
- 使用 React. Lazy 和 Suspense
import React, { Suspense, lazy } from 'react'; import { BrowserRouter as Router, Route, Switch } from 'react-router-dom'; const Home = lazy(() => import('./components/Home')); const TodoList = lazy(() => import('./components/TodoList')); const Profile = lazy(() => import('./components/Profile')); function App() { return ( <Router> <Suspense fallback={<div>Loading...</div>}> <Switch> <Route exact path="/" component={Home} /> <Route path="/todos" component={TodoList} /> <Route path="/profile" component={Profile} /> </Switch> </Suspense> </Router> ); } -
优化资源加载
- 实现资源预加载
<link rel="preload" href="critical.css" as="style"> <link rel="preload" href="main.js" as="script">- 使用服务工作线程缓存资源
// public/service-worker.js self.addEventListener('install', (event) => { event.waitUntil( caches.open('v1').then((cache) => { return cache.addAll([ '/', '/index.html', '/styles/main.css', '/scripts/main.js', ]); }) ); }); self.addEventListener('fetch', (event) => { event.respondWith( caches.match(event.request).then((response) => { return response || fetch(event.request); }) ); }); -
实现虚拟滚动
- 使用 react-window 库
import React from 'react'; import { FixedSizeList as List } from 'react-window'; const TodoList = ({ todos }) => { const Row = ({ index, style }) => ( <div style={style}> {todos[index].title} </div> ); return ( <List height={400} itemCount={todos.length} itemSize={35} width={300} > {Row} </List> ); }; -
优化状态管理
- 使用 React Context 和 useReducer 实现轻量级状态管理
// src/context/TodoContext.js import React, { createContext, useReducer, useContext } from 'react'; const TodoContext = createContext(); const todoReducer = (state, action) => { switch (action.type) { case 'ADD_TODO': return [...state, action.payload]; case 'REMOVE_TODO': return state.filter(todo => todo.id !== action.payload); default: return state; } }; export const TodoProvider = ({ children }) => { const [todos, dispatch] = useReducer(todoReducer, []); return ( <TodoContext.Provider value={{ todos, dispatch }}> {children} </TodoContext.Provider> ); }; export const useTodos = () => useContext(TodoContext); -
实现性能监控
- 使用 React Profiler API
import React, { Profiler } from 'react'; const onRenderCallback = ( id, phase, actualDuration, baseDuration, startTime, commitTime, interactions ) => { console.log(`Component ${id} rendered in ${actualDuration}ms`); }; function App() { return ( <Profiler id="App" onRender={onRenderCallback}> {/* 应用组件 */} </Profiler> ); }
这个详细计划涵盖了第 12 部分的性能优化和扩展性, 包括数据库优化、缓存实现、后端性能优化、前端性能优化和可扩展性。通过这些步骤, LightweightTodo Pro 的性能将得到显著提升, 同时也增强了系统的可扩展性。这将为用户提供更快、更流畅的使用体验, 并为未来的功能扩展和用户增长做好准备。