MST

星途 面试题库

面试题:React Context在服务端渲染专家难度题

在一个高并发的React服务端渲染项目中,使用Context管理用户认证状态等敏感信息。请详细说明如何确保Context数据在多请求、多实例环境下的安全性与一致性,同时还要兼顾性能和可维护性。请从架构设计、代码实现以及测试方案等多方面进行阐述。
10.6万 热度难度
前端开发React

知识考点

AI 面试

面试题答案

一键面试

架构设计

  1. 独立存储:将用户认证状态等敏感信息存储在独立的持久化存储中,如数据库(如Redis)。这样即使多个实例并行处理请求,数据来源唯一且一致。
  2. 中间件:在请求进入React服务端渲染流程前,通过中间件从存储中获取认证信息,并将其注入到请求上下文(如Express的req对象)。这样在后续的渲染过程中,每个请求都能获取到正确的认证状态。
  3. 缓存机制:对于频繁访问且相对稳定的认证信息,可以在服务端设置缓存。例如,使用内存缓存(如Node.js的node-cache),减少对持久化存储的频繁访问,提高性能。但要注意缓存的更新策略,确保数据一致性。

代码实现

  1. Context 创建与使用
    • 创建Context:
import React from'react';
const AuthContext = React.createContext();
export default AuthContext;
- 注入数据:在服务端渲染时,将从请求上下文获取的认证信息通过`Provider`注入到组件树。
import React from'react';
import AuthContext from './AuthContext';

const serverRender = (req, res) => {
    const authInfo = req.authInfo; // 假设中间件已经将认证信息注入到req.authInfo
    const app = (
        <AuthContext.Provider value={authInfo}>
            {/* 应用的根组件 */}
        </AuthContext.Provider>
    );
    // 后续的渲染逻辑
};
- 使用数据:组件通过`Consumer`或`useContext`钩子获取认证信息。
import React from'react';
import AuthContext from './AuthContext';

const MyComponent = () => {
    const authInfo = React.useContext(AuthContext);
    return (
        <div>
            {authInfo && <p>User is authenticated: {authInfo.isAuthenticated}</p>}
        </div>
    );
};
export default MyComponent;
  1. 数据更新:当认证状态发生变化(如用户登录、登出)时,通过服务端API更新持久化存储,并同时更新缓存(如果有)。例如,在用户登出时:
import redis from'redis';
const client = redis.createClient();

const logout = (req, res) => {
    // 更新数据库中的认证状态
    client.del('user:auth:' + req.user.id);
    // 更新缓存(如果有)
    // 假设使用node-cache
    const NodeCache = require('node-cache');
    const cache = new NodeCache();
    cache.del('user:auth:' + req.user.id);
    res.send('Logged out successfully');
};

测试方案

  1. 单元测试
    • 测试Context相关组件:使用测试框架(如Jest和React Testing Library)测试Context的创建、ProviderConsumer的功能。例如,测试MyComponent在不同认证状态下的渲染情况。
import React from'react';
import { render, screen } from '@testing-library/react';
import MyComponent from './MyComponent';
import AuthContext from './AuthContext';

describe('MyComponent', () => {
    test('renders when user is authenticated', () => {
        const authInfo = { isAuthenticated: true };
        render(
            <AuthContext.Provider value={authInfo}>
                <MyComponent />
            </AuthContext.Provider>
        );
        expect(screen.getByText('User is authenticated: true')).toBeInTheDocument();
    });

    test('renders when user is not authenticated', () => {
        const authInfo = { isAuthenticated: false };
        render(
            <AuthContext.Provider value={authInfo}>
                <MyComponent />
            </AuthContext.Provider>
        );
        expect(screen.queryByText('User is authenticated: true')).not.toBeInTheDocument();
    });
});
  1. 集成测试
    • 测试整个服务端渲染流程:使用工具(如Supertest)模拟HTTP请求,测试从请求进入到渲染完成的整个过程中,认证信息是否正确传递和使用。例如,测试登录后访问需要认证的页面,检查是否能正确渲染相关内容。
import request from'supertest';
import app from './app';

describe('Server Rendering with Authentication', () => {
    let cookie;
    beforeEach(async () => {
        const loginRes = await request(app)
          .post('/login')
          .send({ username: 'test', password: 'test' });
        cookie = loginRes.headers['set - cookie'];
    });

    test('renders authenticated page correctly', async () => {
        const res = await request(app)
          .get('/authenticated - page')
          .set('Cookie', cookie);
        expect(res.text).toContain('User is authenticated: true');
    });
});
  1. 性能测试:使用工具(如Artillery)模拟高并发请求,测试在多请求环境下系统的性能表现,确保认证信息的获取和处理不会成为性能瓶颈。例如,测试在100个并发请求下,系统的响应时间和吞吐量。
config:
  target: 'http://localhost:3000'
  phases:
    - duration: 60
      arrivalRate: 100
scenarios:
  - flow:
      - get:
          url: '/authenticated - page'
          headers:
            Cookie: 'your - authentication - cookie'