Irbisa · Шпаргалка
Frontend system design
Проектирование ленты, автокомплита или чата, стратегия рендеринга, API и состояние, кэш, офлайн, обновления в реальном времени, микрофронтенды, сборка
Как построить ответ на собеседовании по frontend system design?
Чем offset-пагинация отличается от курсорной и какую вы выберете для бесконечной ленты?
Как выбрать между CSR, SSR, SSG и ISR для страниц продукта?
Что такое performance budget, что в него включить и как его соблюдать?
Какие слои кэширования есть в веб-приложении между пользователем и базой и что хранить в каждом?
Как реализовать бесконечный скролл длинного списка и какие задачи нужно решить кроме загрузки следующей страницы?
import { useEffect, useRef } from 'react';import { useInfiniteQuery } from '@tanstack/react-query'; type Page = { items: Post[]; nextCursor: string | null }; export function Feed() {…Как бы вы спроектировали компонент карусели изображений?
Как бы вы спроектировали поле поиска с автодополнением (typeahead)?
import { useEffect, useState } from 'react'; type Suggestion = { id: string; label: string }; const cache = new Map<string, Suggestion[]>();…Когда для обновлений в реальном времени использовать WebSocket, Server-Sent Events или long polling и как работает каждый из них?
// Long polling: the server holds each request until it has events or about 30 s passasync function longPoll(cursor = '') { for (;;) { try { const res = await fetch(`/api/events?after=${encodeURIComponent(cursor)}`); if (!res.ok) throw new Error(`HTTP ${res.status}`);…Как бы вы спроектировали фронтенд новостной ленты вроде Facebook или X?
Как бы вы спроектировали страницу каталога маркетплейса: фильтры, сортировку, пагинацию, SEO и быструю первую загрузку?
type Filters = Record<string, string[]>; // One filter set, one URL: one CDN cache entry and one canonicalexport function toSearch(filters: Filters, sort: string, page: number): string { const params = new URLSearchParams(); for (const key of Object.keys(filters).sort()) {…Как бы вы спроектировали клиент чата в реальном времени?
type Message = { clientId: string; // made on the device, doubles as the idempotency key id?: string; // assigned by the server seq?: number; // server order within the conversation text: string; status: 'sending' | 'sent' | 'failed';…Как спроектировать контракт API между фронтендом и бэкендами: REST, GraphQL или BFF?
Как бы вы спроектировали дашборд реального времени, который получает сотни обновлений в секунду?
type Tick = { symbol: string; price: number }; // collect stream messages and hand the UI one batch per frame, not one update per messageexport function subscribeBatched(url: string, onBatch: (latest: Map<string, Tick>) => void) { const source = new EventSource(url); let pending = new Map<string, Tick>();…Как сделать веб-приложение offline-first?
Как бы вы спроектировали совместный редактор вроде Google Docs, где несколько человек одновременно правят один документ?
type Insert = { pos: number; text: string; client: string }; // Shift `op` so it keeps its meaning after `applied`, a concurrent edit already appliedfunction transform(op: Insert, applied: Insert): Insert { const before = applied.pos < op.pos || (applied.pos === op.pos && applied.client < op.client); return before ? { ...op, pos: op.pos + applied.text.length } : op;…Как бы вы спроектировали загрузку больших файлов из браузера: прогресс, отмену, повтор и докачку после обрыва соединения?
const PART_SIZE = 8 * 1024 * 1024; // S3 parts: at least 5 MiB except the last // XMLHttpRequest, because fetch reports no upload progressfunction putPart(url: string, part: Blob, onProgress: (sent: number) => void, signal: AbortSignal) { return new Promise<string>((resolve, reject) => { const xhr = new XMLHttpRequest();…Как бы вы спроектировали дизайн-систему и библиотеку компонентов для многих продуктовых команд?
Как организовать интернационализацию в большом масштабе: десятки локалей, плюралы, языки справа налево и бандлы на локаль?
Как добавить во фронтенд фича-флаги и A/B-эксперименты, не замедлив первый рендер и без мелькания не того варианта?
import { createContext, use, type ReactNode } from 'react'; // FNV-1a hash: the same id lands in the same bucket on the server, at the edge and in the browserexport function bucket(userId: string, experiment: string): number { let h = 0x811c9dc5; for (const ch of `${experiment}:${userId}`) h = Math.imul(h ^ ch.charCodeAt(0), 0x01000193);…Когда микрофронтенды оправданы и как их разделить и интегрировать?