| layout | ../../layouts/Layout.astro |
|---|---|
| title | Node.js |
| description | Node.js basics, npm scripts, frontend tooling, HTTP server, networking, observability и рабочее окружение |
| category | Backend |
| kind | questions |
| order | 75 |
Что такое Node.js?
|
Node.js — JavaScript runtime вне браузера, построенный вокруг V8 и системных API. Он используется для servers, CLI, build tools и automation. Node предоставляет filesystem, processes и network APIs, которых нет в browser sandbox. |
Что такое ES Modules в Node.js?
|
Это стандартная система |
Что такое process.env?
|
Это объект environment variables текущего процесса. Значения являются строками или |
Что такое child process?
|
Это отдельный процесс операционной системы, запущенный из Node через |
Чем Node.js отличается от браузера?
|
В Node нет DOM, |
Почему Node.js называют event-driven runtime?
|
Программа регистрирует handlers, а runtime вызывает их при событиях I/O, timers или завершении задач. Это позволяет обслуживать много соединений без отдельного JavaScript thread на каждое. CPU-bound handler все равно блокирует event loop. |
Чем require отличается от import?
|
|
Что такое V8?
|
V8 — JavaScript engine от Chromium, который парсит, интерпретирует и JIT-компилирует код. Node использует V8 для выполнения ECMAScript. Browser APIs и Node APIs находятся вокруг engine, а не внутри языка. |
Что такое libuv?
|
libuv — библиотека Node для event loop, async I/O, timers, filesystem и thread pool. Она скрывает различия операционных систем. Не все операции выполняются на главном JavaScript thread. |
Что такое event loop в Node.js?
|
Event loop проходит фазы timers, pending callbacks, poll, check и close callbacks, обрабатывая готовые задачи. Microtasks выполняются между соответствующими этапами. Детали важны при диагностике starvation и порядка callbacks. |
Чем event loop в Node.js отличается от browser event loop?
|
Оба координируют tasks и microtasks, но источники событий и фазы различаются. Browser привязан к rendering frames и Web APIs, Node — к libuv phases и server I/O. Нельзя механически переносить весь порядок callbacks между окружениями. |
Что такое CommonJS?
|
CommonJS — историческая module system Node с |
Что такое __dirname и почему его нет в ESM?
|
В CommonJS это directory текущего module file. ESM использует стандартный |
Что такое stream?
|
Stream обрабатывает данные частями вместо загрузки всего объема в память. Бывают readable, writable, duplex и transform streams. Backpressure предотвращает переполнение медленного consumer. |
Что такое Buffer?
|
|
Что такое worker_threads?
|
Worker threads выполняют JavaScript параллельно внутри одного Node process с отдельными isolates. Они подходят для CPU-bound вычислений, а не обычного async I/O. Обмен сообщениями и shared memory добавляют overhead. |
Однопоточен ли Node.js?
|
JavaScript-код внутри одного Node.js isolate обычно выполняется в одном потоке с одним event loop. Но сам runtime не является полностью однопоточным: V8, libuv, операционная система и thread pool могут выполнять работу в других потоках. Для параллельного выполнения JavaScript-кода Node.js предоставляет |
Чем concurrency отличается от parallelism?
|
Concurrency означает, что несколько задач находятся в работе одновременно и переключаются во времени. Например, один event loop может ожидать несколько HTTP-запросов, не блокируя выполнение программы. Parallelism означает физическое выполнение нескольких задач в один момент времени на разных CPU cores. Для параллельного
JavaScript-кода в Node.js обычно используют Асинхронность сама по себе не делает CPU-bound код параллельным. Тяжелый синхронный цикл все равно блокирует event loop. |
Чем worker_threads отличаются от child_process и cluster?
Для CPU-bound вычислений внутри приложения обычно подходит pool из |
Как выполнить CPU-bound задачу в отдельном Worker Thread?
|
Основной поток создает
import {parentPort, workerData} from 'node:worker_threads';
const fibonacci = (value) => {
if (value < 2) {
return value;
}
return fibonacci(value - 1) + fibonacci(value - 2);
};
parentPort.postMessage(fibonacci(workerData));
import {Worker} from 'node:worker_threads';
const runFibonacci = (value) =>
new Promise((resolve, reject) => {
const worker = new Worker(new URL('./fibonacci-worker.mjs', import.meta.url), {
workerData: value,
});
worker.once('message', resolve);
worker.once('error', reject);
worker.once('exit', (code) => {
if (code !== 0) {
reject(new Error(`Worker завершился с кодом ${code}`));
}
});
});
console.log(await runFibonacci(42));Создавать новый worker для каждой маленькой задачи дорого. В production обычно используют постоянный worker pool и очередь задач. |
Как Worker Threads обмениваются данными?
|
Основные варианты:
Message passing обычно безопаснее и проще. Shared memory полезна только там, где стоимость копирования действительно существенна и команда готова управлять race conditions. |
Что такое race condition в Node.js?
|
Race condition возникает, когда результат зависит от порядка параллельного доступа к общему состоянию. Например,
операция Для счетчика в const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT);
const counter = new Int32Array(buffer);
Atomics.add(counter, 0, 1);Для обычных async callbacks в одном event loop тоже возможны логические race conditions, если между чтением и записью
есть |
Что такое Atomics и зачем он нужен?
|
|
Чем mutex отличается от semaphore?
|
Mutex разрешает вход в критическую секцию только одному участнику. Обычно освободить mutex должен тот же участник, который его захватил. Semaphore хранит счетчик разрешений. Counting semaphore со значением Примеры:
|
Как реализовать асинхронный semaphore для ограничения Promise-задач?
|
Такой semaphore ограничивает concurrency внутри одного event loop. Он полезен для HTTP requests, файловых операций или доступа к connection pool, но не делает CPU-bound JavaScript параллельным. class Semaphore {
#available;
#queue = [];
constructor(limit) {
if (!Number.isInteger(limit) || limit < 1) {
throw new TypeError('Semaphore limit must be a positive integer');
}
this.#available = limit;
}
acquire() {
if (this.#available > 0) {
this.#available -= 1;
return Promise.resolve(this.#createRelease());
}
return new Promise((resolve) => {
this.#queue.push(resolve);
});
}
async run(task) {
const release = await this.acquire();
try {
return await task();
} finally {
release();
}
}
#createRelease() {
let released = false;
return () => {
if (released) {
return;
}
released = true;
const next = this.#queue.shift();
if (next) {
next(this.#createRelease());
} else {
this.#available += 1;
}
};
}
}Использование с максимум двумя одновременными запросами: const semaphore = new Semaphore(2);
const urls = ['https://a.example', 'https://b.example', 'https://c.example'];
const responses = await Promise.all(urls.map((url) => semaphore.run(() => fetch(url))));Освобождение находится в |
Как реализовать semaphore между Worker Threads через SharedArrayBuffer?
|
В общей памяти можно хранить количество доступных permits. Захват выполняется через compare-and-swap, а ожидающие
workers блокируются через
export const acquire = (state) => {
while (true) {
const permits = Atomics.load(state, 0);
if (permits > 0 && Atomics.compareExchange(state, 0, permits, permits - 1) === permits) {
return;
}
Atomics.wait(state, 0, 0);
}
};
export const release = (state) => {
Atomics.add(state, 0, 1);
Atomics.notify(state, 0, 1);
};Основной поток создает shared state и передает его workers: import {Worker} from 'node:worker_threads';
const permits = 2;
const buffer = new SharedArrayBuffer(Int32Array.BYTES_PER_ELEMENT);
const state = new Int32Array(buffer);
Atomics.store(state, 0, permits);
const workers = Array.from(
{length: 4},
(_, id) =>
new Worker(new URL('./worker.mjs', import.meta.url), {
workerData: {id, semaphoreBuffer: buffer},
}),
);
await Promise.all(
workers.map(
(worker) =>
new Promise((resolve, reject) => {
worker.once('exit', resolve);
worker.once('error', reject);
}),
),
);
import {setTimeout} from 'node:timers/promises';
import {workerData} from 'node:worker_threads';
import {acquire, release} from './shared-semaphore.mjs';
const state = new Int32Array(workerData.semaphoreBuffer);
acquire(state);
try {
console.log(`Worker ${workerData.id} получил permit`);
await setTimeout(500);
} finally {
release(state);
}Этот пример учебный. В production нужно дополнительно продумать shutdown, timeout, cancellation, падение worker после
|
Какие ошибки часто допускают при работе с многопоточностью в Node.js?
По умолчанию лучше использовать message passing и изолированное состояние. Shared memory и низкоуровневые primitives нужны только после измерений и при понятной модели владения ресурсами. |
Что такое npm package?
|
Это directory или опубликованный artifact с |
Что такое package.json?
|
Manifest проекта описывает metadata, scripts, dependencies, package exports и настройки tools. Он не фиксирует точное дерево transitive dependencies. Для этого нужен lock-файл. |
Что такое peerDependencies?
|
Они объявляют, что package ожидает совместимую dependency от host-проекта. Это важно для frameworks и plugins, которым нужен общий runtime instance. Например, Angular library обычно указывает Angular как peer dependency. |
Что такое npm scripts?
|
Это именованные shell-команды в поле |
Что такое semantic versioning?
|
SemVer использует |
Что значит ^, ~ и exact version в package.json?
|
Exact устанавливает только указанную version. |
Чем dependencies отличаются от devDependencies?
|
|
Что такое package-lock.json?
|
Lock-файл фиксирует точные версии и integrity всего установленного dependency tree. Он делает installs воспроизводимыми. Ручное редактирование обычно не требуется. |
Почему lock-файл важно коммитить?
|
CI и разработчики получают одно и то же разрешенное дерево, а изменения dependencies видны в review. Без lock-файла compatible ranges могут установить разные transitive versions. Это усложняет debugging и supply-chain audit. |
Что делает npm install?
|
Разрешает dependencies, устанавливает их в |
Что делает npm ci?
|
Удаляет существующий |
Чем npm ci лучше для CI?
|
Дает чистую, воспроизводимую установку и быстро обнаруживает незакоммиченный lock update. Поведение меньше зависит от
предыдущего workspace state. Кеш npm downloads можно использовать отдельно от |
Как npm scripts используются во frontend-проектах?
|
Для |
Чем task runner отличается от package scripts?
|
Task runner вроде Gulp или Grunt описывает pipeline через отдельный инструмент и плагины. Package scripts запускают команды напрямую через npm, pnpm, Yarn или Bun. В современных frontend-проектах многие задачи закрываются framework CLI, bundler и package scripts, но legacy-проекты могут все еще использовать task runners для сборки assets или интеграции. |
Что такое dev server?
|
Локальный HTTP server для разработки с module transforms, source maps, watch и hot reload. Он оптимизирован для feedback, а не безопасности, кеширования и production traffic. Его нельзя использовать как production hosting. |
Почему frontend-проекту нужен Node.js?
|
Node запускает package manager, compiler, linter, tests, dev server и production build. Результат затем выполняется в browser и может не зависеть от Node. SSR-приложение дополнительно использует Node во время runtime. |
Как Node.js используется в Angular CLI?
|
CLI запускается как Node program, читает workspace config и вызывает builders. TypeScript/Angular compiler, dev server и test runner также работают в Node. Поддерживаемая Node version зависит от Angular version. |
Как Node.js используется в Vite/Webpack/esbuild?
|
Он запускает bundler process, читает файлы, разрешает modules и обслуживает plugins. Vite предоставляет dev server, Webpack строит module graph, esbuild выполняет быстрые transforms/bundling. Production output предназначен для browser или server target. |
Чем dev server отличается от production build?
|
Dev server часто преобразует modules по запросу и хранит часть данных в памяти. Production build минифицирует, хеширует, оптимизирует и записывает deployable artifacts. Поведение окружения нужно проверять production build. |
Почему код, который работает в Node.js, может не работать в браузере?
|
Browser не предоставляет |
Почему код, который работает в браузере, может не работать в Node.js?
|
В Node обычно нет |
Когда scaffolding tools полезны, а когда вредят?
|
Scaffolding tools полезны, когда создают повторяемую структуру components, features, libraries или tests по текущим командным conventions. Они вредят, если генерируют много непонятного boilerplate или закрепляют устаревшую архитектуру. Генератор должен отражать живую codebase, а не исторические привычки. |
Что такое idempotency?
|
Операция идемпотентна, если повтор одного и того же запроса имеет тот же ожидаемый итоговый эффект. Это важно для retries при сетевой неопределенности. API может использовать idempotency key для безопасного повторения создания платежа. |
Что такое HSTS и зачем браузер проверяет HSTS list?
|
HSTS (HTTP Strict Transport Security) говорит браузеру обращаться к сайту только по HTTPS. Если domain есть в preloaded
HSTS list или браузер уже получил Это защищает от downgrade attack и случайной отправки cookies по незащищенному соединению. Для frontend это важно при диагностике "почему HTTP redirect не виден в Network" и при настройке production-доменов. |
Что такое ETag?
|
|
Что такое Expires?
|
|
Из чего состоит HTTP request?
|
Request line содержит method, target и HTTP version, затем идут headers и optional body. URL включает path и query params. Host, authorization и content metadata передаются headers. |
Из чего состоит HTTP response?
|
Status line содержит HTTP version и status code, затем идут response headers и optional body. Headers описывают content, cache, cookies и transport metadata. Body может содержать JSON, HTML, файл или stream. |
Чем OPTIONS и HEAD отличаются от основных HTTP methods?
|
|
Какие HTTP methods обычно идемпотентны?
|
GET, HEAD, PUT, DELETE и OPTIONS определены как идемпотентные по семантике, PATCH может быть таким по контракту, POST обычно нет. Идемпотентность не означает одинаковый response: DELETE повторно может вернуть другой status. |
Как использовать curl для проверки HTTP API?
|
curl https://api.example.com/userscurl -X POST https://api.example.com/users \
-H "Content-Type: application/json" \
-d '{"name":"Max","role":"frontend"}'curl -X PATCH https://api.example.com/users/1 \
-H "Content-Type: application/json" \
-H "Authorization: Bearer token" \
-d '{"name":"Alex"}' |
Чем HTTP отличается от HTTPS?
|
HTTPS передает HTTP внутри защищенного TLS-соединения. Оно шифрует трафик, подтверждает подлинность сервера сертификатом и защищает данные от незаметного изменения в пути. HTTPS не исправляет XSS, слабую авторизацию или утечку данных на сервере. |
Как устроены TCP/IP и HTTP?
|
Упрощенная модель TCP/IP:
HTTP — протокол прикладного уровня с моделью request/response. Клиент отправляет метод, URL, заголовки и при необходимости body; сервер возвращает status code, заголовки и body. HTTPS — HTTP поверх защищенного TLS-соединения. TCP обеспечивает надежную упорядоченную доставку для HTTP/1.1 и HTTP/2; HTTP/3 использует QUIC поверх UDP. TCP устанавливает соединение, гарантирует порядок и повторную доставку потерянных данных. UDP отправляет datagrams без таких гарантий, но с меньшими накладными расходами. В модели OSI HTTP относится к прикладному уровню, TCP/UDP - к транспортному, IP - к сетевому. Для frontend-разработчика важны методы, коды ответа, заголовки, кеширование, cookies, CORS, TLS, сжатие и понимание того, что количество и размер запросов влияют на производительность. |
Как работает DNS lookup?
|
DNS lookup преобразует hostname в IP-адрес. Браузер и ОС сначала проверяют свои кеши, затем resolver обращается к настроенному DNS-серверу, который может вернуть ответ из кеша или выполнить recursive lookup через DNS hierarchy. Ответы имеют TTL, поэтому смена IP, CDN или DNS-записей может доходить до пользователей не мгновенно. В DevTools это видно как DNS timing, если соединение не было переиспользовано. |
Зачем frontend-разработчику понимать DNS?
|
DNS влияет на latency первого запроса к origin, API, CDN, fonts и analytics. Много разных domains увеличивает число DNS lookup, TCP/TLS setup и риск частичных сбоев. Практически это помогает объяснять медленный first visit, выбирать |
Что происходит перед отправкой HTTP-запроса по HTTPS?
|
Браузер открывает или переиспользует соединение с origin. Если нового соединения избежать нельзя, сначала устанавливается transport connection, затем выполняется TLS handshake: выбирается версия TLS и cipher suite, проверяется certificate chain, согласуются ключи шифрования и имя сервера через SNI. Только после успешного TLS handshake отправляется HTTP-запрос. Поэтому медленный HTTPS может быть связан не с API handler, а с network latency, certificate проблемами, отсутствием connection reuse или слишком большим числом origins. |
Чем TCP отличается от UDP в контексте HTTP?
|
TCP дает надежный упорядоченный byte stream: потерянные данные повторно передаются, а приложение получает их в порядке. HTTP/1.1 и HTTP/2 обычно работают поверх TCP. UDP не гарантирует доставку и порядок datagrams. HTTP/3 использует QUIC поверх UDP, добавляя надежность, шифрование и мультиплексирование на своем уровне. Для frontend это проявляется в timing, connection setup и поведении при packet loss. |
Что происходит, если сетевой пакет потерялся?
|
Для TCP потеря приводит к повторной передаче и увеличению latency; данные выше по стеку будут ждать недостающий кусок. В HTTP/2 поверх TCP потеря может задержать несколько streams на одном соединении. В QUIC/HTTP/3 потеря одного stream меньше блокирует остальные streams, но пользователь все равно видит задержку, timeout или retry на уровне приложения. Frontend должен проектировать loading, timeout и idempotent retry с учетом этой неопределенности. |
Как выглядит минимальный HTTP request?
|
Минимально важны method, request target, HTTP version и GET /products?limit=10 HTTP/1.1
Host: example.com
Accept: text/htmlРеальный browser request добавит headers вроде |
Что означают Date и Age в HTTP headers?
|
|
Почему раньше ассеты разносили по нескольким доменам?
|
В HTTP/1.1 браузеры ограничивали число одновременных соединений к одному host, поэтому domain sharding помогал качать больше файлов параллельно. Цена — дополнительные DNS lookup, TLS handshakes, cookies и сложность кеширования. В современных проектах этот прием чаще вреден. |
Что такое domain prefetch?
|
Domain prefetch заранее выполняет DNS lookup для origin, который скоро может понадобиться. Это может сократить задержку
первого запроса к стороннему домену, но лишние hints расходуют ресурсы и могут раскрывать будущие переходы. Для более
критичных ресурсов иногда уместнее |
Что происходит, если HTML ссылается на ресурсы с других доменов?
|
Для каждого нового origin браузеру могут понадобиться отдельные DNS lookup, connection setup и TLS handshake. CSS, scripts, images, fonts и API-запросы также подчиняются mixed content, CORS, CORP/CORB, CSP и cookie rules. Практические проблемы: медленные third-party scripts задерживают render, fonts могут блокировать текст, API может упасть
из-за CORS, а cookies не отправятся без правильных |
Что делает сервер после получения HTTP request?
|
Server или edge layer принимает request, разбирает method, path, headers и body, применяет routing, authentication, authorization, validation, business logic и обращение к данным. Затем формирует status code, response headers и body. До application code запрос могут обработать CDN, reverse proxy, WAF, cache или load balancer. Поэтому frontend диагностика должна смотреть status, headers, timing, trace id и то, на каком слое возникла ошибка. |
Из чего состоят HTTP-запрос и ответ?
|
Запрос содержит method, URL, headers и необязательный body. Ответ содержит status code, headers и необязательный body. Частые headers: |
Чем WebSocket отличается от SSE?
|
WebSocket предоставляет постоянный двусторонний канал и подходит для чатов, multiplayer и совместного редактирования. SSE передает события только от сервера к клиенту поверх HTTP, автоматически переподключается и проще для уведомлений, прогресса и live feed. SSE передает текстовые события и имеет browser-specific ограничения соединений. |
Когда выбрать polling, SSE или WebSocket?
Учитывают инфраструктуру, reconnect, authentication, масштабирование, mobile network и реальную частоту событий. |
Чем Long Polling, WebSocket и Server-Sent Events отличаются?
|
Long Polling держит HTTP-запрос открытым до появления события, затем клиент сразу открывает следующий запрос. SSE дает постоянный однонаправленный поток server-to-client поверх HTTP и хорошо подходит для уведомлений. WebSocket открывает двусторонний канал с низкой задержкой, но требует отдельного управления reconnect, auth, scaling и проксированием. |
Что такое 304 Not Modified и как он связан с кешем?
|
Это экономит bandwidth, но не убирает network round trip. Для hashed assets часто лучше долгий
|
Что такое Cache-Control?
|
|
Для чего нужны If-Modified-Since и If-None-Match?
|
Это conditional request headers для revalidation. |
Что такое Transfer-Encoding?
|
|
Как HTTP/2 и HTTP/3 изменили подход к domain sharding?
|
HTTP/2 добавил multiplexing нескольких streams в одном соединении, а HTTP/3 поверх QUIC уменьшает влияние части transport-level задержек. Поэтому много доменов обычно хуже: теряется reuse соединения и усложняется приоритизация. Оптимизация сместилась к правильному кешированию, размеру ресурсов и CDN, а не к искусственному дроблению origins. |
Что такое клиент-серверная архитектура?
|
Клиент отвечает за интерфейс и отправляет запросы, сервер хранит данные, применяет бизнес-правила и возвращает ответы. Граница не является границей доверия: server всегда повторно проверяет authentication, authorization и входные данные, даже если frontend уже выполнил validation. |
Чем CDN cache отличается от browser cache?
|
Browser cache находится у конкретного пользователя и ускоряет повторные посещения. CDN cache находится ближе к пользователям на edge-узлах и снижает latency, трафик до origin и нагрузку на backend. Для static assets обычно используют content hash и долгий Cache-Control: public, max-age=31536000, immutable |
Что такое RPS?
|
RPS, или Requests Per Second, — количество запросов, которое сервер обрабатывает за секунду. Например, |
Что такое RPS monitor?
|
RPS monitor измеряет количество запросов за единицу времени. Он помогает увидеть текущую нагрузку, всплески трафика и связать их с деградацией производительности или доступности. |
Зачем frontend-разработчику понимать RPS?
|
Frontend-разработчик может работать с SSR, BFF, dev server, Node.js tooling и API-интеграциями. RPS помогает оценивать нагрузку на SSR, rate limits, кеширование, retry-логику и влияние frontend-кода на backend. |
Как может выглядеть простой RPS monitor в Node.js?
|
Этот учебный HTTP-сервер считает запросы за последнюю секунду и выводит результат в консоль: import http from 'node:http';
let requests = 0;
setInterval(() => {
console.log(`RPS: ${requests}`);
requests = 0;
}, 1000);
const server = http.createServer((request, response) => {
requests += 1;
response.writeHead(200, {'Content-Type': 'application/json'});
response.end(JSON.stringify({ok: true}));
});
server.listen(3000, () => {
console.log('Server started on http://localhost:3000');
}); |
Как проверить RPS monitor через curl?
|
После запуска сервера можно отправить несколько запросов вручную: curl http://localhost:3000
curl http://localhost:3000
curl http://localhost:3000В следующем секундном интервале сервер выведет количество полученных запросов. |
Почему такой RPS monitor не production-ready?
|
Он хранит счетчик только в памяти одного процесса и теряет данные при перезапуске. Несколько процессов или containers будут считать RPS независимо. В production метрики агрегируют через Prometheus, OpenTelemetry, APM или другую систему observability и визуализируют, например, в Grafana. |
Какие метрики кроме RPS важны для Node.js сервера?
Метрики полезно связывать между собой: один RPS не объясняет состояние системы. |
Чем RPS отличается от latency?
|
RPS показывает количество обработанных запросов в секунду, а latency — время обработки отдельного запроса. Высокий RPS сам по себе не является проблемой, но рост latency и error rate вместе с ним может указывать на перегрузку. |
Что такое p95 и p99 latency?
|
|
Как event loop delay связан с производительностью Node.js?
|
JavaScript выполняется в основном потоке Node.js. CPU-bound работа и долгие синхронные операции блокируют event loop, из-за чего callbacks и обработчики запросов запускаются позже. Event loop delay измеряет эту задержку и помогает найти такие блокировки. |
Что может увеличить RPS capacity Node.js приложения?
Изменения нужно подтверждать нагрузочными тестами: увеличение RPS не должно ухудшать latency и error rate сверх SLO. |
Как package.json связан с рабочим окружением?
|
Подробности про manifest, зависимости, lock-файлы и npm-команды см. в разделе npm и package scripts. |
Зачем frontend-проекту единый tooling?
|
Единый tooling снижает расхождения между локальной разработкой, CI и production build. Команда должна понимать, какой package manager используется, какие scripts являются основными, как запускать tests, lint, format, build и preview. Это ускоряет onboarding и уменьшает проблемы класса works on my machine. |
Чем отличаются Bun, pnpm, Yarn и npm?
|
Все эти инструменты устанавливают зависимости, работают с
Практическое правило: в одном проекте выбирают один package manager, фиксируют его через поле |
Зачем нужен package-lock.json?
|
Canonical-ответ: Что такое package-lock.json? |
Чем npm install отличается от npm ci?
|
В рабочем процессе важно правило: локально чаще используют установку по правилам проекта, а в CI предпочитают воспроизводимую установку по lock-файлу. Подробное сравнение см. в Node.js-разделе: Что делает npm install? и Что делает npm ci?. |
Чем ESLint, Stylelint и Prettier отличаются?
|
ESLint анализирует код и находит потенциальные ошибки, небезопасные конструкции и нарушения правил проекта. Stylelint выполняет похожую проверку для CSS, SCSS и других стилей. Prettier отвечает за форматирование: отступы, переносы и кавычки, но не заменяет semantic linting. Вместе с EditorConfig эти инструменты автоматизируют механические правила и уменьшают споры в review. Важно запускать их локально и в CI, иначе guidelines остаются документом без enforcement. |
Как вы поддерживаете единый стиль кода в команде?
|
Команда фиксирует правила в formatter, linting, editor config, pull request checklist и CI. Важно автоматизировать механические споры, а в review обсуждать читаемость, архитектуру и поведение. Если правило не проверяется автоматически, его стоит описать в локальных соглашениях или пересмотреть. |
Для чего нужен linting tool?
|
Linting tool находит ошибки и risky patterns до runtime: неиспользуемый код, неправильные imports, нарушение accessibility, небезопасные конструкции и несогласованный стиль. Он не заменяет тесты и review, но дает быстрый feedback и делает качество менее зависимым от памяти конкретного разработчика. |
Чем Webpack отличается от Vite?
|
Webpack строит dependency graph и создает bundles через loaders и plugins. Он гибкий, но development-сборка крупного проекта может быть тяжелой. Vite в development использует native ES modules и преобразует файлы по запросу, поэтому обычно быстрее запускается и обновляет модули. Production-сборка использует отдельный bundling pipeline. В Angular конкретный инструмент часто скрыт за CLI builder. |
Как код попадает в отдельный chunk?
|
Основные сигналы для сборщика:
Сборщик анализирует dependency graph и выносит асинхронную или общую часть в отдельный файл. Chunk полезен, если уменьшает initial load, но слишком мелкое дробление увеличивает число запросов и служебные расходы. |
Как выглядит обычный workflow при разработке страницы или фичи?
|
Сначала уточняют цель, состояния UI, acceptance criteria, API-контракт, accessibility и способ проверки. Затем делают минимальный инкремент, запускают локальные проверки, добавляют нужные тесты и отправляют маленький pull request. Хороший workflow оставляет следы: описание решения, известные ограничения и понятные шаги проверки. |
Какое рабочее окружение вы предпочитаете?
|
Хороший ответ описывает не любимую IDE как самоцель, а условия продуктивности: быстрый запуск проекта, стабильный Node.js version, корректные extensions, formatter on save, debugger, терминал и доступ к DevTools. Важно уметь подстроиться под командные стандарты, чтобы локальная среда не расходилась с CI. |
Что вы делаете, если проект использует tabs, а вы привыкли к spaces?
|
Нужно следовать проектным настройкам, а не личной привычке. Форматирование должны задавать |
Зачем frontend-команде documentation guidelines?
|
Documentation guidelines объясняют, где описаны архитектура, conventions, design system, onboarding, troubleshooting и решения по workflow. Без этого знания остаются в головах отдельных людей, а новые разработчики повторяют старые ошибки. Практичный подход — обновлять docs вместе с кодом в том же pull request. |
Какие инструменты должны быть описаны в onboarding документации?
|
Нужно описать Node.js version, package manager, install command, dev server, build, tests, lint, format, environment variables, mock API и troubleshooting. Хорошая onboarding документация позволяет новому разработчику поднять проект без долгих личных созвонов и не расходиться с CI. |
Чем Babel, SWC, esbuild и TypeScript compiler отличаются в frontend toolchain?
|
TypeScript compiler умеет type checking и emit, но в современных frontend-сборках часто разделяют type checking и transpile. Babel трансформирует syntax через plugins, SWC и esbuild делают быстрые transforms на native-реализациях. Важно различать:
Angular CLI скрывает большую часть деталей, но разработчик должен понимать, где искать проблему: в {
"scripts": {
"typecheck": "tsc --noEmit",
"build": "vite build"
}
} |
Как объяснить Vite, Webpack и Rollup на интервью?
|
Webpack - универсальный bundler с большим plugin ecosystem и исторически богатой настройкой. Rollup силен для libraries и tree shaking ES modules. Vite использует быстрый dev server на native ESM и собирает production через Rollup-пайплайн или framework-specific integration. Хороший ответ не сводится к "Vite быстрее". Нужно объяснить dev server, HMR, module graph, code splitting, CSS/assets pipeline, source maps и то, как framework CLI ограничивает или расширяет доступ к настройкам. export default {
build: {
sourcemap: true,
rollupOptions: {
output: {
manualChunks: {
vendor: ['react', 'react-dom'],
},
},
},
},
}; |