好的, 让我们来详细规划第 12 部分: 性能优化和扩展性。我们将这部分分为 3 天, 每天专注于特定的优化和扩展任务。

第 12 部分:性能优化和扩展性 (3 天)

Day 1: 数据库优化和缓存

  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);
  2. 实现数据库连接池

    • 使用 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
      }
    }
  3. 实现 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: 后端性能优化

  1. 实现请求限流

    • 安装依赖
    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 {
      // ...
    }
  2. 实现异步任务处理

    • 安装 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' };
      }
    }
  3. 优化日志记录

    • 实现结构化日志
    // 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: 前端性能优化和可扩展性

  1. 实现代码分割和懒加载

    • 使用 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>
      );
    }
  2. 优化资源加载

    • 实现资源预加载
    <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);
        })
      );
    });
  3. 实现虚拟滚动

    • 使用 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>
      );
    };
  4. 优化状态管理

    • 使用 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);
  5. 实现性能监控

    • 使用 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 的性能将得到显著提升, 同时也增强了系统的可扩展性。这将为用户提供更快、更流畅的使用体验, 并为未来的功能扩展和用户增长做好准备。