В чем отличие среды исполнения JavaScript в браузере и на сервере
Что проверяют
Понимаете ли вы, что язык один, а окружение разное, и что из этого следует для фронтенда, особенно при серверном рендеринге. Следом часто спрашивают про ошибку window is not defined в SSR или про различия event loop.
Как отвечать
Язык в обоих случаях ECMAScript, и часто движок тоже один: V8 работает в Chrome, Node.js и Deno, а Bun построен на JavaScriptCore из Safari. Отличаются API и модель выполнения:
- глобальный объект:
windowв браузере,globalв Node.js, универсальное имяglobalThis; - API: в браузере DOM,
localStorage,history, Web Workers; на сервереfs,process,Buffer,worker_threads. Общая часть растёт: в Node.js есть глобальныеfetch,URL,AbortController,structuredClone; - event loop: в браузере он описан спецификацией HTML и чередуется с отрисовкой, отсюда
requestAnimationFrame; в Node.js цикл реализован в libuv с фазами таймеров, ввода-вывода иsetImmediate, плюс очередьprocess.nextTick; - безопасность: браузер это песочница с same-origin policy и CORS, без доступа к файлам; на сервере код видит ОС, поэтому секреты живут только там;
- окружение: браузер и устройство выбирает пользователь, отсюда Browserslist, транспиляция и полифилы; версию Node.js на сервере вы контролируете сами.
Главное следствие для фронтенда это SSR в Next.js или Nuxt: один компонент исполняется и на сервере, и в браузере. Код с window и document уносят в useEffect или проверяют окружение, иначе серверный рендер падает. Если сервер и клиент выдали разную разметку, будет ошибка гидратации. Есть и edge-рантаймы вроде Cloudflare Workers: там веб-стандартные API, а многих модулей Node.js нет.
Где спотыкаются
Говорят, что Node.js многопоточный. JavaScript там исполняется в одном потоке, а пул потоков libuv обслуживает часть операций: файлы, DNS, криптографию.
Считают, что setTimeout везде одинаковый. В браузере он возвращает число, в Node.js объект Timeout, и типы в TypeScript из-за этого расходятся.
Кладут ключи API в клиентский бандл, забывая, что всё отправленное в браузер видит любой пользователь.