找回密码
 立即注册
首页 业界区 安全 SvelteKit 最新中文文档教程(8)—— 部署 Node 服务端 ...

SvelteKit 最新中文文档教程(8)—— 部署 Node 服务端

郗燕岚 2025-5-30 10:37:42
前言

Svelte,一个语法简洁、入门容易,面向未来的前端框架。
从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1
1.png

Svelte 以其独特的编译时优化机制著称,具有轻量级高性能易上手等特性,非常适合构建轻量级 Web 项目
为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。
如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。
Node 服务端

要生成独立的 Node 服务端,请使用 adapter-node。
使用方法

使用 npm i -D @sveltejs/adapter-node 安装,然后将适配器添加到您的 svelte.config.js:
  1. // @errors: 2307
  2. /// file: svelte.config.js
  3. import adapter from '@sveltejs/adapter-node';
  4. export default {
  5.         kit: {
  6.                 adapter: adapter()
  7.         }
  8. };
复制代码
部署

首先,使用 npm run build 构建您的应用。这将在适配器选项中指定的输出目录(默认为 build)中创建生产服务端。
要运行应用程序,您需要输出目录、项目的 package.json 和 node_modules 中的生产依赖项。生产依赖项可以通过复制 package.json 和 package-lock.json 然后运行 npm ci --omit dev 来生成(如果您的应用没有任何依赖项,可以跳过此步骤)。然后您可以使用以下命令启动您的应用:
  1. node build
复制代码
开发依赖项将使用 Rollup 打包到您的应用中。要控制某个包是打包还是外部化,请将其分别放在 package.json 的 devDependencies 或 dependencies 中。
压缩响应

通常您会希望压缩来自服务端的响应。如果您已经在为 SSL 或负载均衡部署了反向代理服务端,那么在该层处理压缩通常会带来更好的性能,因为 Node.js 是单线程的。
但是,如果您正在构建自定义服务端并确实想在那里添加压缩中间件,请注意我们建议使用 @polka/compression,因为 SvelteKit 会流式传输响应,而更流行的 compression 包不支持流式传输,使用时可能会导致错误。
环境变量

在 dev 和 preview 模式下,SvelteKit 将从您的 .env 文件(或 .env.local,或 .env.[mode],由 Vite 决定)中读取环境变量。
在生产环境中,不会自动加载 .env 文件。要做到这一点,请在您的项目中安装 dotenv...
  1. npm install dotenv
复制代码
...并在运行构建的应用之前调用它:
  1. node +++-r dotenv/config+++ build
复制代码
如果您使用的是 Node.js v20.6+,您可以使用 --env-file 标志代替:
  1. node +++--env-file=.env+++ build
复制代码
PORT, HOST 和 SOCKET_PATH

默认情况下,服务端将使用 0.0.0.0 并在端口 3000 上接受连接。可以使用 PORT 和 HOST 环境变量对其进行自定义:
  1. HOST=127.0.0.1 PORT=4000 node build
复制代码
或者,还可以配置服务端在指定的 socket 路径上接受连接。如果您使用 SOCKET_PATH 环境变量来执行此操作,则会忽略 HOST 和 PORT 环境变量。
  1. SOCKET_PATH=/tmp/socket node build
复制代码
ORIGIN, PROTOCOL_HEADER, HOST_HEADER 和 PORT_HEADER

HTTP 并不会为 SvelteKit 提供一种可靠的方法来获取当前请求的 URL。最简单的方式是设置 ORIGIN 环境变量来告诉 SvelteKit 应用在哪里被提供服务:
  1. ORIGIN=https://my.site node build
  2. # 或者,例如本地预览和测试
  3. ORIGIN=http://localhost:3000 node build
复制代码
这样,当请求 /stuff 路径名时,就能正确解析到 https://my.site/stuff。或者,您可以指定用于告诉 SvelteKit 关于请求协议和主机的标头,由此 SvelteKit 可以构建 origin URL:
  1. PROTOCOL_HEADER=x-forwarded-proto HOST_HEADER=x-forwarded-host node build
复制代码
[!NOTE] x-forwarded-proto 和 x-forwarded-host 是事实上的标准请求头,用于在使用反向代理(如负载均衡器和 CDN)时转发原始协议和主机。只有在您的服务端位于受信任的反向代理之后时,才应设置这些变量;否则,客户端可能会伪造这些标头。
如果您在非标准端口托管代理,并且您的反向代理支持 x-forwarded-port,您也可以设置 PORT_HEADER=x-forwarded-port。
如果 adapter-node 无法正确确定您的部署的 URL,在使用 表单 actions 时可能会出现以下错误:
[!NOTE] Cross-site POST form submissions are forbidden
ADDRESS_HEADER 和 XFF_DEPTH

传递给 hooks 和端点的 RequestEvent 对象包含一个 event.getClientAddress() 函数,用于返回客户端的 IP 地址。默认情况下,这是发起连接的 remoteAddress。如果您的服务器位于一个或多个代理(如负载均衡器)之后,这个值将包含最内部代理的 IP 地址,而不是客户端的 IP 地址,因此我们需要指定一个 ADDRESS_HEADER 读取地址:
  1. ADDRESS_HEADER=True-Client-IP node build
复制代码
[!NOTE] 标头很容易被伪造。与 PROTOCOL_HEADER 和 HOST_HEADER 一样,只有在您了解相关风险的情况下才应设置这些变量。
如果 ADDRESS_HEADER 是 X-Forwarded-For,其值会包含用逗号分隔的 IP 地址列表。此时应通过 XFF_DEPTH 环境变量指定在您的服务器前有多少个受信任的代理。例如,如果有三个受信任的代理,代理 3 会转发客户端原始连接和前两个代理的地址:
  1. <client address>, <proxy 1 address>, <proxy 2 address>
复制代码
有些指南会告诉您读取最左边的地址,但这样会容易被伪造:
  1. <client address>, <proxy 1 address>, <proxy 2 address>,
复制代码
因此,我们从右侧读取,并依据受信任的代理数量进行处理。在这个示例里,我们会使用 XFF_DEPTH=3。
[!NOTE] 如果您确实需要读取最左侧的地址(并且不在意被伪造)——例如提供地理位置服务,在此情况下,IP 地址“真实性”比“可信度”更重要,您可以在应用中自行检查 x-forwarded-for 标头来实现这一点。
BODY_SIZE_LIMIT

接受的最大请求体大小,以字节为单位(包括流式传输时)。
请求体大小也可以使用单位后缀指定,包括千字节(K)、兆字节(M)或千兆字节(G)。例如 512K 或 1M。默认值为 512kb。
您可以设置值为 Infinity(在适配器的旧版本中为 0)来禁用此选项,如果需要更高级的功能,可以在 handle 中自行实现更高级的检查逻辑。
SHUTDOWN_TIMEOUT

接收到 SIGTERM 或 SIGINT 信号后,在强制关闭任何剩余连接之前等待的秒数。默认值是 30。在内部,适配器会调用 closeAllConnections。更多细节请参见 优雅关闭。
IDLE_TIMEOUT

在使用 systemd 套接字激活时,IDLE_TIMEOUT 用于指定当应用在没有请求的情况下经过多少秒会自动休眠。如果未设置,则应用会一直运行。详见 套接字激活 获取更多信息。
Options

该适配器可以通过多种选项进行配置:
  1. // @errors: 2307
  2. /// file: svelte.config.js
  3. import adapter from '@sveltejs/adapter-node';
  4. export default {
  5.         kit: {
  6.                 adapter: adapter({
  7.                         // 以下为默认选项
  8.                         out: 'build',
  9.                         precompress: true,
  10.                         envPrefix: ''
  11.                 })
  12.         }
  13. };
复制代码
out

构建服务端输出的目录,默认为 build —— 也就是说,如果您使用默认目录,执行 node build 将在本地启动服务端。
precompress

使用 gzip 和 brotli 对资源和预渲染页面进行预压缩。默认值为 true。
envPrefix

如果您需要更改用于配置部署的环境变量名称(例如,与您无法控制的环境变量冲突),可以指定一个前缀:
  1. envPrefix: 'MY_CUSTOM_';
复制代码
  1. MY_CUSTOM_HOST=127.0.0.1 \
  2. MY_CUSTOM_PORT=4000 \
  3. MY_CUSTOM_ORIGIN=https://my.site \
  4. node build
复制代码
优雅关闭

默认情况下,当接收到 SIGTERM 或 SIGINT 信号时,adapter-node 会优雅地关闭 HTTP 服务器。它将:

  • 拒绝新的请求(server.close)
  • 等待已经发出的请求但尚未收到响应的请求完成,并在连接变为空闲后关闭连接(server.closeIdleConnections)
  • 最后,在超过 SHUTDOWN_TIMEOUT 秒后强制关闭所有仍处于活动状态的连接(server.closeAllConnections)。
[!NOTE] 如果您想自定义这一行为,您可以使用自定义服务端。
您还可以监听 sveltekit:shutdown 事件,该事件会在 HTTP 服务器关闭全部连接后触发。与 Node 的 exit 事件不同,sveltekit:shutdown 事件支持异步操作,并且无论服务器是否有未完成的任务(如未关闭的数据库连接),在所有连接都关闭后都会被触发:
  1. // @errors: 2304
  2. process.on('sveltekit:shutdown', async (reason) => {
  3.         await jobs.stop();
  4.         await db.close();
  5. });
复制代码
参数 reason 的可能取值包括:

  • SIGINT - 关机由 SIGINT 信号触发
  • SIGTERM - 关机由 SIGTERM 信号触发
  • IDLE - 关机由 IDLE_TIMEOUT 触发
套接字激活

当今大多数 Linux 操作系统都使用名为 systemd 的现代进程管理器来启动、运行和管理服务。您可以配置服务器来分配一个套接字,并在需要时按需启动应用。这被称为 套接字激活。在这种情况下,操作系统会向您的应用传递两个环境变量:LISTEN_PID 和 LISTEN_FDS。然后,适配器会在文件描述符 3 上进行监听,该描述符对应您创建的 systemd 套接字单元。
[!NOTE] 您仍然可以在 systemd 套接字激活中使用 envPrefix。LISTEN_PID 和 LISTEN_FDS 始终无需前缀即可读取。
要利用套接字激活,请按以下步骤操作:

  • 让您的应用作为一个 systemd 服务 运行。它既可以直接运行在主机系统上,也可以在容器内(例如使用 Docker 或 systemd 可移植服务)运行。
如果您额外向应用传递一个 IDLE_TIMEOUT 环境变量,它将在没有请求持续 IDLE_TIMEOUT 秒时,优雅地关闭。之后如果有新的请求到来,systemd 将自动重新启动您的应用。
  1. /// file: /etc/systemd/system/myapp.service
  2. [Service]
  3. Environment=NODE_ENV=production IDLE_TIMEOUT=60
  4. ExecStart=/usr/bin/node /usr/bin/myapp/build
复制代码

  • 创建一个配套的 socket 单元。适配器仅接受单个 socket。
  1. /// file: /etc/systemd/system/myapp.socket
  2. [Socket]
  3. ListenStream=3000
  4. [Install]
  5. WantedBy=sockets.target
复制代码

  • 通过运行 sudo systemctl daemon-reload 确保 systemd 识别了这两个单元。然后使用 sudo systemctl enable --now myapp.socket 在启动时启用该 socket 并立即启动它。这样当第一个请求到达 localhost:3000 时,应用将自动启动。
自定义服务端

该适配器会在您的构建目录中创建两个文件——index.js 和 handler.js。运行 index.js(例如,如果您使用默认 build 目录,那么执行 node build)将会在指定端口上启动服务器。
或者,您可以导入 handler.js 文件,它导出一个兼容 Express、Connect 或 Polka (甚至是内置的 http.createServer)的处理程序,并且设置你自己的服务器:
  1. // @errors: 2307 7006
  2. /// file: my-server.js
  3. import { handler } from './build/handler.js';
  4. import express from 'express';
  5. const app = express();
  6. // 添加一个独立于 SvelteKit 应用的路由
  7. app.get('/healthcheck', (req, res) => {
  8.         res.end('ok');
  9. });
  10. // 让 SvelteKit 处理其他所有内容,包括提供预渲染页面和静态资源
  11. app.use(handler);
  12. app.listen(3000, () => {
  13.         console.log('listening on port 3000');
  14. });
复制代码
Svelte 中文文档

点击查看中文文档 - SvelteKit Node 服务端。
系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。

来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!

相关推荐

您需要登录后才可以回帖 登录 | 立即注册