Серверы Node
Для создания автономного сервера Node используйте adapter-node
.
Использование
Заголовок раздела «Использование»Установите адаптер с помощью команды npm i -D @sveltejs/adapter-node
, затем добавьте его в ваш файл svelte.config.js
:
import adapter from '@sveltejs/adapter-node';
export default { kit: { adapter: adapter() }};
Развёртывание
Заголовок раздела «Развёртывание»Сначала соберите приложение с помощью команды npm run build
. Это создаст продакшен-сервер в выходной директории, указанной в настройках адаптера, по умолчанию — build
.
Для запуска приложения вам понадобятся выходная директория, файл package.json
проекта и производственные зависимости в node_modules
. Производственные зависимости можно установить, скопировав файлы package.json
и package-lock.json
, а затем выполнив команду npm ci --omit dev
(этот шаг можно пропустить, если у вашего приложения нет зависимостей). После этого вы можете запустить приложение с помощью следующей команды:
node build
Зависимости для разработки будут включены в ваше приложение с использованием Rollup. Чтобы определить, будет ли определённый пакет включён в сборку или останется внешним, указывайте его в devDependencies
или dependencies
соответственно в вашем файле package.json
.
Сжатие ответов
Заголовок раздела «Сжатие ответов»Обычно требуется сжимать ответы, отправляемые с сервера. Если вы уже разворачиваете сервер за обратным прокси для SSL или балансировки нагрузки, сжатие лучше выполнять на этом уровне, так как это обычно обеспечивает лучшую производительность, учитывая, что Node.js является однопоточным.
Однако, если вы создаёте пользовательский сервер и хотите добавить мидлвар для сжатия, мы рекомендуем использовать @polka/compression
, поскольку SvelteKit использует потоковую передачу ответов, а более популярный пакет compression
не поддерживает стриминг и может вызывать ошибки при использовании.
Переменные окружения
Заголовок раздела «Переменные окружения»В режимах dev
и preview
SvelteKit читает переменные окружения из файла .env
(или .env.local
, или .env.[mode]
, как определено в Vite).
В продакшене файлы .env
не загружаются автоматически. Чтобы это сделать, установите dotenv
в ваш проект…
npm install dotenv
…и вызовите его перед запуском собранного приложения:
node -r dotenv/config build
Если вы используете Node.js версии 20.6 или выше, вы можете вместо этого использовать флаг --env-file
:
node --env-file=.env build
PORT
, HOST
и SOCKET_PATH
Заголовок раздела «PORT, HOST и SOCKET_PATH»По умолчанию сервер принимает соединения на 0.0.0.0
через порт 3000. Эти параметры можно настроить с помощью переменных окружения PORT
и HOST
:
HOST=127.0.0.1 PORT=4000 node build
В качестве альтернативы сервер можно настроить для приема соединений по указанному пути сокета. Если это делается с помощью переменной окружения SOCKET_PATH
, переменные окружения HOST
и PORT
будут игнорироваться.
SOCKET_PATH=/tmp/socket node build
ORIGIN
, PROTOCOL_HEADER
, HOST_HEADER
и PORT_HEADER
Заголовок раздела «ORIGIN, PROTOCOL_HEADER, HOST_HEADER и PORT_HEADER»HTTP не предоставляет SvelteKit надежного способа узнать URL, который запрашивается в данный момент. Самый простой способ указать SvelteKit, где размещено приложение, — это установить переменную окружения ORIGIN
:
ORIGIN=https://my.site node build
# или, например, для локального предпросмотра и тестированияORIGIN=http://localhost:3000 node build
С помощью этого запрос к пути /stuff
будет корректно разрешаться в https://my.site/stuff
. В качестве альтернативы вы можете указать заголовки, которые сообщат SvelteKit о протоколе запроса и хосте, на основе которых он сможет сформировать исходный URL:
PROTOCOL_HEADER=x-forwarded-proto HOST_HEADER=x-forwarded-host node build
Если adapter-node
не может корректно определить URL вашего развёртывания, вы можете столкнуться с ошибкой при использовании действий форм:
ADDRESS_HEADER
и XFF_DEPTH
Заголовок раздела «ADDRESS_HEADER и XFF_DEPTH»Объект RequestEvent
, передаваемый в хуки и конечные точки, включает функцию event.getClientAddress()
, которая возвращает IP-адрес клиента. По умолчанию это адрес подключения remoteAddress
. Если ваш сервер находится за одним или несколькими прокси (например, балансировщиком нагрузки), это значение будет содержать IP-адрес самого внутреннего прокси, а не клиента, поэтому необходимо указать ADDRESS_HEADER
для чтения адреса:
ADDRESS_HEADER=True-Client-IP node build
Если ADDRESS_HEADER
установлен как X-Forwarded-For
, значение заголовка будет содержать список IP-адресов, разделённых запятыми. Переменная окружения XFF_DEPTH
должна указывать, сколько доверенных прокси находится перед вашим сервером. Например, если есть три доверенных прокси, прокси 3 будет пересылать адреса исходного соединения и первых двух прокси:
<client address>, <proxy 1 address>, <proxy 2 address>
Некоторые руководства советуют читать самый левый адрес, но это делает вас уязвимым для подделки:
<spoofed address>, <client address>, <proxy 1 address>, <proxy 2 address>
Вместо этого мы читаем с правой стороны, учитывая количество доверенных прокси. В данном случае мы используем XFF_DEPTH=3
.
BODY_SIZE_LIMIT
Заголовок раздела «BODY_SIZE_LIMIT»Максимальный размер тела запроса в байтах, принимаемый при потоковой передаче. Размер тела можно также указать с суффиксом единицы измерения для килобайт (K
), мегабайт (M
) или гигабайт (G
). Например, 512K
или 1M
. По умолчанию — 512 КБ. Эту опцию можно отключить, установив значение Infinity
(в старых версиях адаптера — 0) и реализовав пользовательскую проверку в handle
, если требуется более сложная логика.
SHUTDOWN_TIMEOUT
Заголовок раздела «SHUTDOWN_TIMEOUT»Количество секунд ожидания перед принудительным закрытием оставшихся соединений после получения сигнала SIGTERM
или SIGINT
. По умолчанию — 30
. Внутри адаптер вызывает closeAllConnections
. Подробности см. в разделе Грамотное завершение работы.
IDLE_TIMEOUT
Заголовок раздела «IDLE_TIMEOUT»При использовании активации сокетов systemd переменная IDLE_TIMEOUT
указывает количество секунд, после которых приложение автоматически переводится в спящий режим, если запросы не поступают. Если не установлено, приложение работает непрерывно. Подробности см. в разделе Активация сокетов.
Адаптер можно настроить с помощью различных параметров:
import adapter from '@sveltejs/adapter-node';
export default { kit: { adapter: adapter({ // параметры по умолчанию out: 'build', precompress: true, envPrefix: '' }) }};
Директория, в которую собирается сервер. По умолчанию — build
, то есть команда node build
запустит сервер локально после его создания.
precompress
Заголовок раздела «precompress»Включает предварительное сжатие с использованием gzip и brotli для активов и предварительно отрендеренных страниц. По умолчанию — true
.
envPrefix
Заголовок раздела «envPrefix»Если вам нужно изменить названия переменных окружения, используемых для настройки развёртывания (например, чтобы избежать конфликтов с переменными окружения, которые вы не контролируете), вы можете указать префикс:
envPrefix: 'MY_CUSTOM_';
MY_CUSTOM_HOST=127.0.0.1 \MY_CUSTOM_PORT=4000 \MY_CUSTOM_ORIGIN=https://my.site \node build
Грамотное завершение работы
Заголовок раздела «Грамотное завершение работы»По умолчанию adapter-node
выполняет корректное завершение работы HTTP-сервера при получении сигнала SIGTERM
или SIGINT
. Процесс включает:
- Отклонение новых запросов
server.close
. - Ожидание завершения уже поступивших, но ещё не обработанных запросов, и закрытие соединений, как только они станут неактивными
server.closeIdleConnections
. - Принудительное закрытие всех оставшихся активных соединений после истечения времени, указанного в
SHUTDOWN_TIMEOUT
(в секундах)server.closeAllConnections
.
Вы можете подписаться на событие sveltekit:shutdown
, которое вызывается после того, как HTTP-сервер закроет все соединения. В отличие от события exit
в Node, событие sveltekit:shutdown
поддерживает асинхронные операции и всегда вызывается после закрытия всех соединений, даже если у сервера остались незавершённые задачи, такие как открытые подключения к базе данных.
process.on('sveltekit:shutdown', async (reason) => { await jobs.stop(); await db.close();});
Параметр reason
принимает одно из следующих значений:
SIGINT
— завершение работы инициировано сигналомSIGINT
SIGTERM
— завершение работы инициировано сигналомSIGTERM
IDLE
— завершение работы инициировано по истечении времениIDLE_TIMEOUT
Активация сокетов
Заголовок раздела «Активация сокетов»Большинство современных операционных систем Linux используют менеджер процессов systemd для запуска сервера и управления сервисами. Вы можете настроить сервер для выделения сокета и запуска или масштабирования приложения по требованию. Это называется активацией сокетов. В этом случае операционная система передаст приложению две переменные окружения — LISTEN_PID
и LISTEN_FDS
. Адаптер будет прослушивать файловый дескриптор 3, который соответствует юниту сокета systemd, который вам нужно будет создать.
Чтобы воспользоваться активацией сокетов, выполните следующие шаги:
-
Запустите приложение как сервис systemd. Оно может работать непосредственно на хост-системе или внутри контейнера (например, с использованием Docker или портативного сервиса systemd). Если вы дополнительно передадите приложению переменную окружения
IDLE_TIMEOUT
, оно будет грамотно завершать работу, если в течение указанного времени не поступает запросов. systemd автоматически перезапустит приложение, когда поступят новые запросы./etc/systemd/system/myapp.service [Service]Environment=NODE_ENV=production IDLE_TIMEOUT=60ExecStart=/usr/bin/node /usr/bin/myapp/build -
Создайте соответствующий юнит сокета. Адаптер принимает только один сокет.
/etc/systemd/system/myapp.socket [Socket]ListenStream=3000[Install]WantedBy=sockets.target -
Убедитесь, что systemd распознал оба юнита, выполнив команду
sudo systemctl daemon-reload
. Затем включите запуск сокета при загрузке системы и запустите его немедленно с помощью командыsudo systemctl enable --now myapp.socket
. После этого приложение автоматически запустится при первом запросе кlocalhost:3000
.
Пользовательский сервер
Заголовок раздела «Пользовательский сервер»Адаптер создаёт два файла в вашей директории сборки — index.js
и handler.js
. Запуск index.js
— например, node build
, если используется директория сборки по умолчанию — запустит сервер на настроенном порту.
В качестве альтернативы вы можете импортировать файл handler.js
, который экспортирует обработчик, подходящий для использования с Express, Connect или Polka (или даже просто со встроенным http.createServer
), и настроить собственный сервер:
import { handler } from './build/handler.js';import express from 'express';
const app = express();
// добавляем маршрут, который работает отдельно от приложения SvelteKitapp.get('/healthcheck', (req, res) => { res.end('ok');});
// пусть SvelteKit занимается всем остальным, включая обслуживание предварительно отрисованных страниц и статических ресурсовapp.use(handler);
app.listen(3000, () => { console.log('listening on port 3000');});