Skip to main content

Node servers

要生成一个独立的 Node 服务器,请使用adapter-node

使用

安装 npm i -D @sveltejs/adapter-node 后,将适配器添加到您的svelte.config.js中:

svelte.config
import import adapteradapter from '@sveltejs/adapter-node';

export default {
	
kit: {
    adapter: any;
}
kit
: {
adapter: anyadapter: import adapteradapter() } };

部署

首先,使用npm run build构建您的应用。这将创建在适配器选项中指定的输出目录的生产服务器,默认为build

您需要输出目录、项目的package.json以及node_modules中的生产依赖来运行应用程序。可以通过复制package.jsonpackage-lock.json并运行npm ci --omit dev来生成生产依赖(如果您的应用程序没有依赖项,可以跳过此步骤)。然后,您可以使用以下命令启动您的应用程序:

node 编译

开发依赖将被打包到您的应用中,使用Rollup。要控制是否将某个包打包或外部化,请将其分别放置在您的package.json中的devDependenciesdependencies中。

压缩响应

通常您会希望压缩来自服务器的响应。如果您已经在部署使用 SSL 或负载均衡的反向代理服务器,由于 Node.js 是单线程的,因此在那个层面处理压缩通常可以获得更好的性能。

然而,如果您正在构建一个自定义服务器并且确实想在那里添加压缩中间件,请注意我们建议使用@polka/compression,因为 SvelteKit 流式传输响应,而更受欢迎的compression包不支持流式传输,可能会在使用时引发错误。

环境变量

devpreview中,SvelteKit 将从您的.env文件(或.env.local,或.env.[mode]由 Vite 确定。)中读取环境变量。

在生产中,.env 文件不会被自动加载。要实现这一点,请在您的项目中安装 dotenv...

npm 安装 dotenv

...在运行构建的应用程序之前调用它:

node -r dotenv/config build

如果您使用 Node.js v20.6+,可以使用--env-file标志:

node --env-file=.env build

端口主机SOCKET_PATH

默认情况下,服务器将在0.0.0.0上使用端口 3000 接受连接。这些可以通过PORTHOST环境变量进行自定义:

HOST=127.0.0.1 PORT=4000 node build

另外,服务器可以被配置为在指定的套接字路径上接受连接。当使用 SOCKET_PATH 环境变量执行此操作时,将忽略 HOSTPORT 环境变量。

SOCKET_PATH=/tmp/socket node build

ORIGINPROTOCOL_HEADERHOST_HEADERPORT_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

如果 适配器节点无法正确确定您的部署的 URL,您在使用表单操作时可能会遇到此错误:

[注意] 禁止跨站 POST 表单提交

地址头xff 深度

The RequestEvent 对象传递给钩子和端点时,包括一个 event.getClientAddress() 函数,该函数返回客户端的 IP 地址。默认情况下,这是连接的 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

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

SHUTDOWN_TIMEOUT

等待在接收到 SIGTERMSIGINT 信号后强制关闭任何剩余连接的秒数。默认为 30。内部适配器调用 closeAllConnections。有关更多详细信息,请参阅 优雅关闭

空闲超时

当使用 systemd 套接字激活时,IDLE_TIMEOUT指定了在收到无请求后应用自动休眠的秒数。如果没有设置,应用将连续运行。请参阅套接字激活获取更多详细信息。

选项

适配器可以配置为各种选项:

svelte.config
import import adapteradapter from '@sveltejs/adapter-node';

export default {
	
kit: {
    adapter: any;
}
kit
: {
adapter: anyadapter: import adapteradapter({ // default options are shown out: stringout: 'build', precompress: booleanprecompress: true, envPrefix: stringenvPrefix: '' }) } };

服务器构建目录。默认为 build — 即 node build 将在创建后本地启动服务器。

预压缩

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

envPrefix

如果您需要更改用于配置部署的环境变量名称(例如,为了避免与您无法控制的环境变量冲突),您可以指定一个前缀:

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

优雅关机

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

  1. 拒绝新的请求(server.close
  2. 等待已完成但尚未收到响应的请求完成,并在它们变为空闲时关闭连接(server.closeIdleConnections
  3. 最后,关闭在SHUTDOWN_TIMEOUT秒后仍然活跃的任何剩余连接。(server.closeAllConnections

[!注意] 如果您想自定义此行为,可以使用自定义服务器

您可以在 HTTP 服务器关闭所有连接后监听 sveltekit:shutdown 事件。与 Node 的 exit 事件不同,sveltekit:shutdown 事件支持异步操作,并且当所有连接关闭时始终会触发,即使服务器有悬挂的工作,如打开的数据库连接。

var process: NodeJS.Processprocess.NodeJS.Process.on(event: string | symbol, listener: (...args: any[]) => void): NodeJS.Process (+12 overloads)

Adds the listener function to the end of the listeners array for the event named eventName. No checks are made to see if the listener has already been added. Multiple calls passing the same combination of eventName and listener will result in the listener being added, and called, multiple times.

server.on('connection', (stream) => {
  console.log('someone connected!');
});

Returns a reference to the EventEmitter, so that calls can be chained.

By default, event listeners are invoked in the order they are added. The emitter.prependListener() method can be used as an alternative to add the event listener to the beginning of the listeners array.

import { EventEmitter } from 'node:events';
const myEE = new EventEmitter();
myEE.on('foo', () => console.log('a'));
myEE.prependListener('foo', () => console.log('b'));
myEE.emit('foo');
// Prints:
//   b
//   a
@sincev0.1.101
@parameventName The name of the event.
@paramlistener The callback function
on
('sveltekit:shutdown', async (reason: anyreason) => {
await jobs.stop(); await db.close(); });

参数 reason 有以下几种值:

  • SIGINT - 关闭操作由 SIGINT 信号触发
  • SIGTERM - 关闭操作由 SIGTERM 信号触发
  • 空闲 - 关闭由 空闲超时 触发

套接字激活

大多数 Linux 操作系统今天使用名为 systemd 的现代进程管理器来启动服务器并运行和管理服务。您可以将服务器配置为分配套接字并在需要时启动和扩展您的应用程序。这被称为套接字激活。在这种情况下,操作系统将传递两个环境变量到您的应用程序中——LISTEN_PIDLISTEN_FDS。然后适配器将在文件描述符 3 上监听,该描述符指向您必须创建的系统 d 套接字单元。

[注意] 您仍然可以使用 envPrefix 与 systemd 网络套接字激活一起使用。 LISTEN_PIDLISTEN_FDS 总是带前缀读取。

利用套接字激活,请按照以下步骤操作。

  1. 运行您的应用作为systemd 服务。它可以直接在主机系统上运行,或者在容器内运行(例如使用 Docker 或 systemd 便携式服务)。如果您向应用传递一个IDLE_TIMEOUT环境变量,当没有请求持续IDLE_TIMEOUT秒时,它将优雅地关闭。当有新请求到来时,systemd 将自动重新启动您的应用。
/etc/systemd/system/myapp
[Service]
Environment=NODE_ENV=production IDLE_TIMEOUT=60
ExecStart=/usr/bin/node /usr/bin/myapp/build
  1. 创建一个配套的套接字单元。适配器仅接受一个套接字。
/etc/systemd/system/myapp
[Socket]
ListenStream=3000

[Install]
WantedBy=sockets.target
  1. 确保 systemd 已识别这两个单元,通过运行sudo systemctl daemon-reload。然后,在启动时启用套接字并立即使用 sudo systemctl enable --now myapp.socket 启动它。一旦对localhost:3000发起第一个请求,应用程序将自动启动。

自定义服务器

适配器在您的构建目录中创建两个文件——index.jshandler.js。运行index.js——例如node build,如果您使用默认的构建目录——将在配置的端口上启动服务器。

或者,您可以导入 handler.js 文件,该文件导出一个适用于与 ExpressConnectPolka(甚至只是内置的 http.createServer)一起使用的处理器,并设置自己的服务器:

my-server
import { import handlerhandler } from './build/handler.js';
import import expressexpress from 'express';

const const app: anyapp = import expressexpress();

// add a route that lives separately from the SvelteKit app
const app: anyapp.get('/healthcheck', (req, res) => {

	res: anyres.end('ok');
});

// let SvelteKit handle everything else, including serving prerendered pages and static assets
const app: anyapp.use(import handlerhandler);

const app: anyapp.listen(3000, () => {
	var console: Console

The console module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers.

The module exports two specific components:

  • A Console class with methods such as console.log(), console.error() and console.warn() that can be used to write to any Node.js stream.
  • A global console instance configured to write to process.stdout and process.stderr. The global console can be used without importing the node:console module.

Warning: The global console object’s methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the note on process I/O for more information.

Example using the global console:

console.log('hello world');
// Prints: hello world, to stdout
console.log('hello %s', 'world');
// Prints: hello world, to stdout
console.error(new Error('Whoops, something bad happened'));
// Prints error message and stack trace to stderr:
//   Error: Whoops, something bad happened
//     at [eval]:5:15
//     at Script.runInThisContext (node:vm:132:18)
//     at Object.runInThisContext (node:vm:309:38)
//     at node:internal/process/execution:77:19
//     at [eval]-wrapper:6:22
//     at evalScript (node:internal/process/execution:76:60)
//     at node:internal/main/eval_string:23:3

const name = 'Will Robinson';
console.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to stderr

Example using the Console class:

const out = getStreamSomehow();
const err = getStreamSomehow();
const myConsole = new console.Console(out, err);

myConsole.log('hello world');
// Prints: hello world, to out
myConsole.log('hello %s', 'world');
// Prints: hello world, to out
myConsole.error(new Error('Whoops, something bad happened'));
// Prints: [Error: Whoops, something bad happened], to err

const name = 'Will Robinson';
myConsole.warn(`Danger ${name}! Danger!`);
// Prints: Danger Will Robinson! Danger!, to err
@seesource
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)

Prints to stdout with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to printf(3) (the arguments are all passed to util.format()).

const count = 5;
console.log('count: %d', count);
// Prints: count: 5, to stdout
console.log('count:', count);
// Prints: count: 5, to stdout

See util.format() for more information.

@sincev0.1.100
log
('listening on port 3000');
});

Edit this page on GitHub llms.txt