Build and deploy
Node サーバー
Edit this page on GitHubスタンドアロンな Node サーバーを作る場合は、adapter-node
を使います。
使い方permalink
npm i -D @sveltejs/adapter-node
を実行してインストールし、svelte.config.js
にこの adapter を追加します:
ts
importCannot find module '@sveltejs/adapter-node' or its corresponding type declarations.2307Cannot find module '@sveltejs/adapter-node' or its corresponding type declarations.adapter from'@sveltejs/adapter-node' ;export default {kit : {adapter :adapter ()}};
デプロイ(Deploying)permalink
まず、npm run build
でアプリをビルドします。これによって adapter のオプションで指定した出力ディレクトリ (デフォルトは build
) に本番環境用のサーバーが作成されます。
アプリケーションを実行するには、出力ディレクトリ、プロジェクトの package.json
、node_modules
の本番向けの依存関係(production dependencies)が必要です。本番向けの依存関係は、package.json
と package-lock.json
をコピーしてから npm ci --omit dev
を実行すると生成することができます (あなたのアプリが何の依存関係も持たない場合はこのステップをスキップできます)。そして、このコマンドでアプリを起動することができます:
node build
Rollup を使うと開発用の依存関係(Development dependencies)もアプリにバンドルされます。パッケージをバンドルするか外部化するかコントロールするには、そのパッケージを package.json
の devDependencies
か dependencies
にそれぞれ配置します。
レスポンスの圧縮permalink
通常、サーバーからのレスポンスを圧縮したいでしょう。SSL やロードバランシングのためにリバースプロキシの後ろにサーバーを配置している場合は、通常はそちらのレイヤーで圧縮を処理したほうがパフォーマンスの向上につながります。Node.js はシングルスレッドだからです。
しかし、あなたが custom server を構築していて、そこに圧縮用のミドルウェアを追加したい場合は、@polka/compression
を使用することをおすすめします。SvelteKit はレスポンスをストリーミングしますが、一般的な compression
パッケージはストリーミングをサポートしていないため、使用するとエラーとなる可能性があります。
環境変数permalink
dev
と preview
のときは、SvelteKit は .env
ファイル (または .env.local
や .env.[mode]
、Vite によって決定されているもの) から環境変数を読み取ります。
プロダクションでは、.env
ファイルは自動的に読み取れらません。そうするには、プロジェクトに dotenv
をインストールします…
npm install dotenv
…そしてビルドされたアプリを実行する前にそれを呼び出します:
node build
node -r dotenv/config build
If you use Node.js v20.6+, you can use the --env-file
flag instead:
node build
node --env-file=.env build
PORT、HOST、SOCKET_PATHpermalink
デフォルトでは、サーバーは 0.0.0.0
、port 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_HEADERpermalink
HTTP は SvelteKit に現在リクエストされている URL を知るための信頼できる方法を提供しません。アプリがホストされている場所を Sveltekit に伝える最も簡単な方法は、環境変数 ORIGIN
を設定することです:
ORIGIN=https://my.site node build
# or e.g. for local previewing and testing
ORIGIN=http://localhost:3000 node build
これにより、パス名 /stuff
に対するリクエストは正しく https://my.site/stuff
に解決されます。別の方法として、リクエストプロトコルとホストを SvelteKit に伝えるヘッダーを指定し、そこから origin URL を組み立てることもできます:
PROTOCOL_HEADER=x-forwarded-proto HOST_HEADER=x-forwarded-host node build
x-forwarded-proto
とx-forwarded-host
は事実上の標準となっているヘッダーで、リバースプロキシー (ロードバランサーや CDN などを考えてみてください) を使用している場合に、オリジナルのプロトコルとホストを転送します。これらの変数は、あなたのサーバーが信頼できるリバースプロキシーの後ろにある場合にのみ設定すべきです。そうしないと、クライアントがこれらのヘッダーを偽装することが可能になってしまいます。プロキシーを非標準の port でホストしていて、リバースプロキシ−が
x-forwarded-port
をサポートしている場合は、PORT_HEADER=x-forwarded-port
を設定することもできます。
adapter-node
があなたのデプロイの URL を正しく判断することができない場合、form actions を使用するとこのエラーが発生することがあります:
クロスサイトの POST フォーム送信は禁止されています
ADDRESS_HEADER と XFF_DEPTHpermalink
hooks とエンドポイントに渡される RequestEvent オブジェクトにはクライアントの IP アドレスを返す event.getClientAddress()
関数が含まれています。デフォルトでは、これは接続中の remoteAddress
です。もしサーバーが1つ以上のプロキシー (例えばロードバランサー) の後ろにある場合、この値はクライアントの IP アドレスではなく、最も内側にあるプロキシーの IP アドレスを含むことになるため、アドレスを読み取るために ADDRESS_HEADER
を指定する必要があります:
ADDRESS_HEADER=True-Client-IP node build
ヘッダーは簡単に偽装されます。
PROTOCOL_HEADER
やHOST_HEADER
と同様、これらを設定する前に自分が何をしているのか知るべきです。
ADDRESS_HEADER
が X-Forwarded-For
の場合、ヘッダーの値にはカンマで区切られた IP アドレスのリストが含まれます。環境変数 XFF_DEPTH
には、あなたのサーバーの前に信頼できるプロキシーがいくつあるか指定する必要があります。例えば、3つの信頼できるプロキシーがある場合、プロキシー3はオリジナルのコネクションと最初の2つのプロキシーのアドレスを転送します:
<client address>, <proxy 1 address>, <proxy 2 address>
一番左のアドレスを読め、というガイドもありますが、これだとスプーフィング(なりすまし)に対し脆弱なままです:
<spoofed address>, <client address>, <proxy 1 address>, <proxy 2 address>
代わりに、信頼できるプロキシーの数を考慮して右から読み込みます。この場合、XFF_DEPTH=3
を使用します。
もし、一番左のアドレスを読む必要がある場合 (そしてスプーフィングを気にしない場合) — 例えば、位置情報サービスを提供する場合、つまり IP アドレスが信頼できることよりもリアルであることが重要な場合、アプリの中で
x-forwarded-for
ヘッダーを検査することでそれが可能です。
BODY_SIZE_LIMITpermalink
ストリーミング中も含め、受け付けるリクエストボディの最大サイズを byte で指定します。ボディサイズの指定には単位を使用することができます。キロバイトには (K
)、メガバイトには (M
)、ギガバイトには (G
) です。例えば、512K
や 1M
のようにします。デフォルトは 512キロバイト です。もっと高度な設定が必要な場合は、このオプションの値を Infinity
(adapter が古いバージョンの場合は 0) にして無効化し、handle
にカスタムのチェックを実装することができます。
SHUTDOWN_TIMEOUTpermalink
The number of seconds to wait before forcefully closing any remaining connections after receiving a SIGTERM
or SIGINT
signal. Defaults to 30
. Internally the adapter calls closeAllConnections
. See Graceful shutdown for more details.
IDLE_TIMEOUTpermalink
When using systemd socket activation, IDLE_TIMEOUT
specifies the number of seconds after which the app is automatically put to sleep when receiving no requests. If not set, the app runs continuously. See Socket activation for more details.
Optionspermalink
この adapter は様々なオプションで設定を行うことができます:
ts
importCannot find module '@sveltejs/adapter-node' or its corresponding type declarations.2307Cannot find module '@sveltejs/adapter-node' or its corresponding type declarations.adapter from'@sveltejs/adapter-node' ;export default {kit : {adapter :adapter ({// default options are shownout : 'build',precompress : true,envPrefix : ''})}};
outpermalink
サーバーをビルドするディレクトリです。デフォルトは build
です。つまり、node build
を指定すると、サーバが作成されローカルで起動します。
precompresspermalink
アセットやプリレンダリングされたページを gzip や brotli を使って事前圧縮(precompress)するのを有効にします。デフォルトは true
です。
envPrefixpermalink
デプロイの設定に使用される環境変数の名前を変更する必要がある場合 (例えば、あなたのコントロール下にない環境変数との競合を解消するため)、接頭辞(prefix)を指定することができます:
ts
envPrefix: 'MY_CUSTOM_';
MY_CUSTOM_HOST=127.0.0.1 \
MY_CUSTOM_PORT=4000 \
MY_CUSTOM_ORIGIN=https://my.site \
node build
Graceful shutdownpermalink
By default adapter-node
gracefully shuts down the HTTP server when a SIGTERM
or SIGINT
signal is received. It will:
- reject new requests (
server.close
) - wait for requests that have already been made but not received a response yet to finish and close connections once they become idle (
server.closeIdleConnections
) - and finally, close any remaining connections that are still active after
SHUTDOWN_TIMEOUT
seconds. (server.closeAllConnections
)
If you want to customize this behaviour you can use a custom server.
You can listen to the sveltekit:shutdown
event which is emitted after the HTTP server has closed all connections. Unlike Node's exit
event, the sveltekit:shutdown
event supports asynchronous operations and is always emitted when all connections are closed even if the server has dangling work such as open database connections.
ts
process .on ('sveltekit:shutdown', async (reason ) => {awaitCannot find name 'jobs'.2304Cannot find name 'jobs'.. jobs stop ();awaitCannot find name 'db'.2304Cannot find name 'db'.. db close ();});
The parameter reason
has one of the following values:
SIGINT
- shutdown was triggered by aSIGINT
signalSIGTERM
- shutdown was triggered by aSIGTERM
signalIDLE
- shutdown was triggered byIDLE_TIMEOUT
Socket activationpermalink
Most Linux operating systems today use a modern process manager called systemd to start the server and run and manage services. You can configure your server to allocate a socket and start and scale your app on demand. This is called socket activation. In this case, the OS will pass two environment variables to your app — LISTEN_PID
and LISTEN_FDS
. The adapter will then listen on file descriptor 3 which refers to a systemd socket unit that you will have to create.
You can still use
envPrefix
with systemd socket activation.LISTEN_PID
andLISTEN_FDS
are always read without a prefix.
To take advantage of socket activation follow these steps.
- Run your app as a systemd service. It can either run directly on the host system or inside a container (using Docker or a systemd portable service for example). If you additionally pass an
IDLE_TIMEOUT
environment variable to your app it will gracefully shutdown if there are no requests forIDLE_TIMEOUT
seconds. systemd will automatically start your app again when new requests are coming in.
[Service]
Environment=NODE_ENV=production IDLE_TIMEOUT=60
ExecStart=/usr/bin/node /usr/bin/myapp/build
- Create an accompanying socket unit. The adapter only accepts a single socket.
[Socket]
ListenStream=3000
[Install]
WantedBy=sockets.target
- Make sure systemd has recognised both units by running
sudo systemctl daemon-reload
. Then enable the socket on boot and start it immediately usingsudo systemctl enable --now myapp.socket
. The app will then automatically start once the first request is made tolocalhost:3000
.
カスタムサーバーpermalink
この adapter は、ビルドのディレクトリに2つのファイルを作成します — index.js
と handler.js
です。デフォルトのビルドのディレクトリを使用している場合、node build
などで index.js
を実行すると、設定された port でサーバーが起動されます。
別の方法として、Express、Connect、Polka (またはビルトインの http.createServer
) を使用するためのハンドラーをエクスポートする handler.js
ファイルをインポートし、独自のサーバーをセットアップすることもできます。
ts
import {Cannot find module './build/handler.js' or its corresponding type declarations.2307Cannot find module './build/handler.js' or its corresponding type declarations.handler } from'./build/handler.js' ;importCannot find module 'express' or its corresponding type declarations.2307Cannot find module 'express' or its corresponding type declarations.express from'express' ;constapp =express ();// add a route that lives separately from the SvelteKit appParameter 'req' implicitly has an 'any' type.Parameter 'res' implicitly has an 'any' type.7006app .get ('/healthcheck', (, req ) => { res
7006Parameter 'req' implicitly has an 'any' type.Parameter 'res' implicitly has an 'any' type.res .end ('ok');});// let SvelteKit handle everything else, including serving prerendered pages and static assetsapp .use (handler );app .listen (3000, () => {console .log ('listening on port 3000');});
ts
import {Cannot find module './build/handler.js' or its corresponding type declarations.2307Cannot find module './build/handler.js' or its corresponding type declarations.handler } from'./build/handler.js' ;importCannot find module 'express' or its corresponding type declarations.2307Cannot find module 'express' or its corresponding type declarations.express from'express' ;constapp =express ();// add a route that lives separately from the SvelteKit appParameter 'req' implicitly has an 'any' type.Parameter 'res' implicitly has an 'any' type.7006app .get ('/healthcheck', (, req ) => { res
7006Parameter 'req' implicitly has an 'any' type.Parameter 'res' implicitly has an 'any' type.res .end ('ok');});// let SvelteKit handle everything else, including serving prerendered pages and static assetsapp .use (handler );app .listen (3000, () => {console .log ('listening on port 3000');});