跳至主要內容

建置並部署

Node 伺服器

在 GitHub 上編輯此頁面

若要產生獨立的 Node 伺服器,請使用 adapter-node

用法

使用 npm i -D @sveltejs/adapter-node 安裝,然後將轉接器新增到您的 svelte.config.js

svelte.config.js
ts
import adapter from '@sveltejs/adapter-node';
Cannot find module '@sveltejs/adapter-node' or its corresponding type declarations.2307Cannot find module '@sveltejs/adapter-node' or its corresponding type declarations.
export default {
kit: {
adapter: adapter()
}
};

部署

首先,使用 npm run build 建置您的應用程式。這將在轉接器選項中指定的輸出目錄(預設為 build)中建立生產伺服器。

您將需要輸出目錄、專案的 package.json 以及 node_modules 中的生產相依套件才能執行應用程式。生產相依套件可以透過複製 package.jsonpackage-lock.json,然後執行 npm ci --omit dev 來產生(如果您的應用程式沒有任何相依套件,您可以略過此步驟)。然後,您可以使用此命令啟動您的應用程式

node build

開發相依套件將使用 Rollup 捆綁到您的應用程式中。若要控制特定套件是捆綁還是外部化,請分別將其放在 package.json 中的 devDependenciesdependencies 中。

壓縮回應

您通常會想要壓縮從伺服器傳來的回應。如果您已經在 SSL 或負載平衡的反向代理後面部署您的伺服器,由於 Node.js 是單執行緒的,因此通常會在該層處理壓縮以獲得更好的效能。

但是,如果您正在建構 自訂伺服器 並且確實想要在那裡新增壓縮中介軟體,請注意,我們建議使用 @polka/compression,因為 SvelteKit 會串流回應,而較受歡迎的 compression 套件不支援串流,並且在使用時可能會造成錯誤。

環境變數

devpreview 中,SvelteKit 會從您的 .env 檔案(或 .env.local,或 .env.[mode]由 Vite 決定)讀取環境變數。

在生產環境中,不會 自動載入 .env 檔案。若要執行此操作,請在您的專案中安裝 dotenv...

npm install dotenv

...並在執行建置的應用程式之前呼叫它

node build
node -r dotenv/config build

PORT、HOST 和 SOCKET_PATH

預設情況下,伺服器將使用埠 3000 在 0.0.0.0 上接受連線。這些可以使用 PORTHOST 環境變數自訂。

HOST=127.0.0.1 PORT=4000 node build

或者,可以將伺服器設定為在指定的 socket 路徑上接受連線。當使用 SOCKET_PATH 環境變數執行此操作時,將會忽略 HOSTPORT 環境變數。

SOCKET_PATH=/tmp/socket node build

ORIGIN、PROTOCOL_HEADER、HOST_HEADER 和 PORT_HEADER

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 關於要求協定和主機的標頭,它可以由此建構原始 URL

PROTOCOL_HEADER=x-forwarded-proto HOST_HEADER=x-forwarded-host node build

x-forwarded-protox-forwarded-host 是事實上的標準標頭,如果您使用反向代理(例如負載平衡器和 CDN),則會轉發原始協定和主機。您只應在您的伺服器位於可信賴的反向代理之後時設定這些變數;否則,客戶端有可能偽造這些標頭。

如果您將代理主機在非標準埠上,並且您的反向代理支援 x-forwarded-port,您也可以設定 PORT_HEADER=x-forwarded-port

如果 adapter-node 無法正確地確定您的部署的 URL,您在使用 表單動作 時可能會遇到此錯誤

禁止跨網站 POST 表單提交

ADDRESS_HEADER 和 XFF_DEPTH

傳遞給掛勾和終端點的 RequestEvent 物件包含一個傳回用戶端 IP 位址的 event.getClientAddress() 函式。預設情況下,這是連線的 remoteAddress。如果您的伺服器位於一個或多個代理程式(例如負載平衡器)之後,這個值將包含最內層代理程式的 IP 位址,而不是用戶端的,因此我們需要指定一個 ADDRESS_HEADER 來從中讀取位址

ADDRESS_HEADER=True-Client-IP node build

標頭很容易被偽造。與 PROTOCOL_HEADERHOST_HEADER 一樣,在設定這些之前,您應該 知道自己在做什麼

如果 ADDRESS_HEADERX-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

如果您需要讀取最左邊的位址(而不關心偽造)——例如,提供地理定位服務,其中 IP 位址真實受信任更重要,您可以在應用程式內檢查 x-forwarded-for 標頭來執行此操作。

BODY_SIZE_LIMIT

可接受的請求主體最大位元組大小,包括串流時。預設為 512kb。您可以使用 Infinity(較舊版本的轉接器中為 0)的值停用此選項,並在 handle 中實作自訂檢查,如果您需要更進階的功能。

SHUTDOWN_TIMEOUT

在收到 SIGTERMSIGINT 訊號後強制關閉任何剩餘連線之前等待的秒數。預設為 30。在內部,轉接器會呼叫 closeAllConnections。請參閱 正常關閉 以取得更多詳細資訊。

IDLE_TIMEOUT

在使用 systemd socket 啟動時,IDLE_TIMEOUT 指定在沒有收到任何請求後,應用程式自動進入休眠狀態的秒數。如果未設定,應用程式將持續執行。請參閱 Socket 啟動 以取得更多詳細資訊。

選項

此轉接器可以使用各種選項進行設定

svelte.config.js
ts
import adapter from '@sveltejs/adapter-node';
Cannot find module '@sveltejs/adapter-node' or its corresponding type declarations.2307Cannot find module '@sveltejs/adapter-node' or its corresponding type declarations.
export default {
kit: {
adapter: adapter({
// default options are shown
out: 'build',
precompress: true,
envPrefix: ''
})
}
};

out

建立伺服器的目錄。預設為 build — 亦即 node build 會在建立伺服器後在本地端啟動伺服器。

precompress

啟用對資源和預先呈現頁面使用 gzip 和 brotli 進行預先壓縮。預設為 true

envPrefix

如果您需要變更用於設定部署的環境變數名稱(例如,與您無法控制的環境變數發生衝突),您可以指定一個前綴

ts
envPrefix: 'MY_CUSTOM_';
MY_CUSTOM_HOST=127.0.0.1 \
MY_CUSTOM_PORT=4000 \
MY_CUSTOM_ORIGIN=https://my.site \
node build

正常關閉

預設情況下,adapter-node 會在收到 SIGTERMSIGINT 訊號時正常關閉 HTTP 伺服器。它將會

  1. 拒絕新的要求(server.close
  2. 等待已經發出但尚未收到回應的要求完成,並在它們閒置後關閉連線(server.closeIdleConnections
  3. 最後,在 SHUTDOWN_TIMEOUT 秒後關閉任何仍處於活動狀態的剩餘連線。(server.closeAllConnections

如果您想要自訂此行為,可以使用 自訂伺服器

Socket 啟動

現今大多數 Linux 作業系統使用稱為 systemd 的現代處理程序管理員來啟動伺服器並執行和管理服務。您可以設定伺服器以配置 socket,並依需要啟動和擴充您的應用程式。這稱為 socket 啟動。在這種情況下,作業系統會將兩個環境變數傳遞給您的應用程式 — LISTEN_PIDLISTEN_FDS。然後,轉接器會在檔案描述符 3 上進行監聽,該檔案描述符會參考您必須建立的 systemd socket 單元。

您仍可以使用 envPrefix 搭配 systemd socket 啟動。LISTEN_PIDLISTEN_FDS 始終會在沒有前綴的情況下讀取。

若要利用 socket 啟動,請遵循下列步驟。

  1. systemd 服務 執行您的應用程式。它可以直接在主機系統上執行,或在容器內執行(例如使用 Docker 或 systemd 可攜式服務)。如果您另外傳遞 IDLE_TIMEOUT 環境變數給您的應用程式,如果在 IDLE_TIMEOUT 秒內沒有要求,它將正常關閉。當有新的要求進來時,systemd 會自動再次啟動您的應用程式。
/etc/systemd/system/myapp.service
[Service]
Environment=NODE_ENV=production IDLE_TIMEOUT=60
ExecStart=/usr/bin/node /usr/bin/myapp/build
  1. 建立一個隨附的 socket 單元。此轉接器只接受單一 socket。
/etc/systemd/system/myapp.socket
[Socket]
ListenStream=3000

[Install]
WantedBy=sockets.target
  1. 透過執行 sudo systemctl daemon-reload 確保 systemd 已辨識兩個單元。然後使用 sudo systemctl enable --now myapp.socket 在開機時啟用 socket 並立即啟動它。接著,一旦對 localhost:3000 提出第一個請求,此應用程式就會自動啟動。

自訂伺服器

此轉接器會在您的建置目錄中建立兩個檔案 — index.jshandler.js。執行 index.js — 例如,如果您使用預設建置目錄,則為 node build — 會在已設定好的埠上啟動一個伺服器。

或者,您可以匯入 handler.js 檔案,它會匯出一個適用於 ExpressConnectPolka(甚至只是內建的 http.createServer)的處理常式,並設定您自己的伺服器

my-server.js
ts
import { handler } from './build/handler.js';
Cannot find module './build/handler.js' or its corresponding type declarations.2307Cannot find module './build/handler.js' or its corresponding type declarations.
import express from 'express';
Cannot find module 'express' or its corresponding type declarations.2307Cannot find module 'express' or its corresponding type declarations.
const app = express();
// add a route that lives separately from the SvelteKit app
app.get('/healthcheck', (req, res) => {
Parameter 'req' implicitly has an 'any' type.
Parameter 'res' implicitly has an 'any' type.
7006
7006
Parameter '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 assets
app.use(handler);
app.listen(3000, () => {
console.log('listening on port 3000');
});
my-server.ts
ts
import { handler } from './build/handler.js';
Cannot find module './build/handler.js' or its corresponding type declarations.2307Cannot find module './build/handler.js' or its corresponding type declarations.
import express from 'express';
Cannot find module 'express' or its corresponding type declarations.2307Cannot find module 'express' or its corresponding type declarations.
const app = express();
// add a route that lives separately from the SvelteKit app
app.get('/healthcheck', (req, res) => {
Parameter 'req' implicitly has an 'any' type.
Parameter 'res' implicitly has an 'any' type.
7006
7006
Parameter '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 assets
app.use(handler);
app.listen(3000, () => {
console.log('listening on port 3000');
});

疑難排解

在應用程式結束前,是否有用於清理的掛鉤?

SvelteKit 中沒有內建此功能,因為此類清理掛鉤高度依賴您所處的執行環境。對於 Node,您可以使用其內建的 process.on(...) 來實作一個在應用程式結束前執行的回呼函式

ts
function shutdownGracefully() {
// anything you need to clean up manually goes in here
db.shutdown();
Cannot find name 'db'.2304Cannot find name 'db'.
}
process.on('exit', shutdownGracefully);