前言
Svelte,一个语法简洁、入门容易,面向未来的前端框架。
从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1:
Svelte 以其独特的编译时优化机制著称,具有轻量级、高性能、易上手等特性,非常适合构建轻量级 Web 项目。
为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。
如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。
Node 服务端
要生成独立的 Node 服务端,请使用 adapter-node。
使用方法
使用 npm i -D @sveltejs/adapter-node 安装,然后将适配器添加到您的 svelte.config.js:- // @errors: 2307
- /// file: 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 来生成(如果您的应用没有任何依赖项,可以跳过此步骤)。然后您可以使用以下命令启动您的应用:开发依赖项将使用 Rollup 打包到您的应用中。要控制某个包是打包还是外部化,请将其分别放在 package.json 的 devDependencies 或 dependencies 中。
压缩响应
通常您会希望压缩来自服务端的响应。如果您已经在为 SSL 或负载均衡部署了反向代理服务端,那么在该层处理压缩通常会带来更好的性能,因为 Node.js 是单线程的。
但是,如果您正在构建自定义服务端并确实想在那里添加压缩中间件,请注意我们建议使用 @polka/compression,因为 SvelteKit 会流式传输响应,而更流行的 compression 包不支持流式传输,使用时可能会导致错误。
环境变量
在 dev 和 preview 模式下,SvelteKit 将从您的 .env 文件(或 .env.local,或 .env.[mode],由 Vite 决定)中读取环境变量。
在生产环境中,不会自动加载 .env 文件。要做到这一点,请在您的项目中安装 dotenv......并在运行构建的应用之前调用它:- node +++-r dotenv/config+++ build
复制代码 如果您使用的是 Node.js v20.6+,您可以使用 --env-file 标志代替:- node +++--env-file=.env+++ build
复制代码 PORT, HOST 和 SOCKET_PATH
默认情况下,服务端将使用 0.0.0.0 并在端口 3000 上接受连接。可以使用 PORT 和 HOST 环境变量对其进行自定义:- HOST=127.0.0.1 PORT=4000 node build
复制代码 或者,还可以配置服务端在指定的 socket 路径上接受连接。如果您使用 SOCKET_PATH 环境变量来执行此操作,则会忽略 HOST 和 PORT 环境变量。- SOCKET_PATH=/tmp/socket node build
复制代码 ORIGIN, PROTOCOL_HEADER, HOST_HEADER 和 PORT_HEADER
HTTP 并不会为 SvelteKit 提供一种可靠的方法来获取当前请求的 URL。最简单的方式是设置 ORIGIN 环境变量来告诉 SvelteKit 应用在哪里被提供服务:- ORIGIN=https://my.site node build
- # 或者,例如本地预览和测试
- ORIGIN=http://localhost:3000 node build
复制代码 这样,当请求 /stuff 路径名时,就能正确解析到 https://my.site/stuff。或者,您可以指定用于告诉 SvelteKit 关于请求协议和主机的标头,由此 SvelteKit 可以构建 origin URL:- 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 读取地址:- ADDRESS_HEADER=True-Client-IP node build
复制代码[!NOTE] 标头很容易被伪造。与 PROTOCOL_HEADER 和 HOST_HEADER 一样,只有在您了解相关风险的情况下才应设置这些变量。
如果 ADDRESS_HEADER 是 X-Forwarded-For,其值会包含用逗号分隔的 IP 地址列表。此时应通过 XFF_DEPTH 环境变量指定在您的服务器前有多少个受信任的代理。例如,如果有三个受信任的代理,代理 3 会转发客户端原始连接和前两个代理的地址:- <client address>, <proxy 1 address>, <proxy 2 address>
复制代码 有些指南会告诉您读取最左边的地址,但这样会容易被伪造:- <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
该适配器可以通过多种选项进行配置:- // @errors: 2307
- /// file: svelte.config.js
- import adapter from '@sveltejs/adapter-node';
- export default {
- kit: {
- adapter: adapter({
- // 以下为默认选项
- out: 'build',
- precompress: true,
- envPrefix: ''
- })
- }
- };
复制代码 out
构建服务端输出的目录,默认为 build —— 也就是说,如果您使用默认目录,执行 node build 将在本地启动服务端。
precompress
使用 gzip 和 brotli 对资源和预渲染页面进行预压缩。默认值为 true。
envPrefix
如果您需要更改用于配置部署的环境变量名称(例如,与您无法控制的环境变量冲突),可以指定一个前缀:- MY_CUSTOM_HOST=127.0.0.1 \
- MY_CUSTOM_PORT=4000 \
- MY_CUSTOM_ORIGIN=https://my.site \
- node build
复制代码 优雅关闭
默认情况下,当接收到 SIGTERM 或 SIGINT 信号时,adapter-node 会优雅地关闭 HTTP 服务器。它将:
- 拒绝新的请求(server.close)
- 等待已经发出的请求但尚未收到响应的请求完成,并在连接变为空闲后关闭连接(server.closeIdleConnections)
- 最后,在超过 SHUTDOWN_TIMEOUT 秒后强制关闭所有仍处于活动状态的连接(server.closeAllConnections)。
[!NOTE] 如果您想自定义这一行为,您可以使用自定义服务端。
您还可以监听 sveltekit:shutdown 事件,该事件会在 HTTP 服务器关闭全部连接后触发。与 Node 的 exit 事件不同,sveltekit:shutdown 事件支持异步操作,并且无论服务器是否有未完成的任务(如未关闭的数据库连接),在所有连接都关闭后都会被触发:- // @errors: 2304
- 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 套接字单元。
[!NOTE] 您仍然可以在 systemd 套接字激活中使用 envPrefix。LISTEN_PID 和 LISTEN_FDS 始终无需前缀即可读取。
要利用套接字激活,请按以下步骤操作:
- 让您的应用作为一个 systemd 服务 运行。它既可以直接运行在主机系统上,也可以在容器内(例如使用 Docker 或 systemd 可移植服务)运行。
如果您额外向应用传递一个 IDLE_TIMEOUT 环境变量,它将在没有请求持续 IDLE_TIMEOUT 秒时,优雅地关闭。之后如果有新的请求到来,systemd 将自动重新启动您的应用。- /// file: /etc/systemd/system/myapp.service
- [Service]
- Environment=NODE_ENV=production IDLE_TIMEOUT=60
- ExecStart=/usr/bin/node /usr/bin/myapp/build
复制代码
- 创建一个配套的 socket 单元。适配器仅接受单个 socket。
- /// file: /etc/systemd/system/myapp.socket
- [Socket]
- ListenStream=3000
- [Install]
- 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)的处理程序,并且设置你自己的服务器:- // @errors: 2307 7006
- /// file: my-server.js
- import { handler } from './build/handler.js';
- import express from 'express';
- const app = express();
- // 添加一个独立于 SvelteKit 应用的路由
- app.get('/healthcheck', (req, res) => {
- res.end('ok');
- });
- // 让 SvelteKit 处理其他所有内容,包括提供预渲染页面和静态资源
- app.use(handler);
- app.listen(3000, () => {
- console.log('listening on port 3000');
- });
复制代码 Svelte 中文文档
点击查看中文文档 - SvelteKit Node 服务端。
系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!
此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog
欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。
来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作! |