我的学习笔记

土猛的员外

SvelteKit中文3-编译发布

该系列文章一共四篇,以下是系列文章链接:

SvelteKit中文1-开始
SvelteKit中文2-核心概念
SvelteKit中文3-编译发布
SvelteKit中文4-高级概念

构建 SvelteKit 应用程序分为两个阶段,这两个阶段都在运行 vite build 时发生(通常通过 npm run build 运行)。

首先,Vite 创建了一个优化的生产构建版本,包括您的服务器代码、浏览器代码和服务工作线程(如果有)。如果适当的话,在此阶段执行预渲染。

其次,适配器接受此生产构建并针对您的目标环境进行调整 - 更多信息请参见以下页面。

构建期间

SvelteKit将在构建期间加载您的+page/layout(.server).js文件(以及它们导入的所有文件)进行分析。任何不应在此阶段执行的代码都必须检查从$app/environment构建为false

1
2
3
4
5
6
7
8
9
10
import { building } from '$app/environment';
import { setupMyDatabase } from '$lib/server/database';

if (!building) {
setupMyDatabase();
}

export function load() {
// ...
}

预览你的应用程序

构建完成后,您可以通过vite预览(通过npm run preview)在本地查看生产版本。请注意,这将在Node中运行应用程序,因此不是您部署的应用程序的完美复制 - 适配器特定的调整(如平台对象)不适用于预览。

适配器

在部署 SvelteKit 应用程序之前,您需要为部署目标进行适应。适配器是小型插件,它们将构建的应用程序作为输入,并生成用于部署的输出。

针对各种平台存在官方适配器 - 这些在以下页面中有所记录:

Additional community-provided adapters exist for other platforms.

Using adapters

Your adapter is specified in svelte.config.js:

svelte.config.js

1
2
3
4
5
6
7
8
9
10
11
12
import adapter from 'svelte-adapter-foo';

/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter({
// adapter options go here
})
}
};

export default config;

Platform特定上下文

一些适配器可能可以访问有关请求的其他信息。例如,Cloudflare Workers 可以访问包含 KV 命名空间等内容的 env 对象。这可以作为platform属性传递给钩子和服务器路由中使用的 RequestEvent,请参阅每个适配器的文档以了解更多信息。

零配置发布

当你使用 npm create svelte@latest 创建一个新的 SvelteKit 项目时,默认会安装 adapter-auto。这个适配器会在部署时自动安装和使用支持环境的正确适配器:

建议在确定目标环境后,将适当的适配器安装到您的 devDependencies 中,因为这样会将适配器添加到锁定文件中,并略微提高 CI 的安装时间。

环境特定配置

要添加配置选项,例如在 adapter-verceladapter-netlify 中添加 { edge: true },您必须安装底层适配器 - adapter-auto 不接受任何选项。

增加社区版adapters

您可以通过编辑adapters.js并打开拉取请求来添加对其他适配器的零配置支持。

Node servers

使用 adapter-node 生成独立的 Node 服务器。

用法

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

svelte.config.js

1
2
3
4
5
6
7
import adapter from '@sveltejs/adapter-node';

export default {
kit: {
adapter: adapter()
}
};

Deploying

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

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

1
node build

开发依赖将使用Rollup打包到您的应用程序中。要控制给定软件包是否捆绑或外部化,请分别将其放置在package.json文件中的devDependenciesdependencies中。

环境变量

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

在生产中,.env 文件不会自动加载。要这样做,请在项目中安装 dotenv

1
npm install dotenv

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

1
2
node build
node -r dotenv/config build

PORT and HOST

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

1
HOST=127.0.0.1 PORT=4000 node build

ORIGIN, PROTOCOL_HEADER and HOST_HEADER

HTTP 无法为 SvelteKit 提供一种可靠的方式来知道当前请求的 URL。告诉 SvelteKit 应用程序正在哪里提供服务的最简单方法是设置 ORIGIN 环境变量:

1
2
3
4
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:

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

x-forwarded-protox-forwarded-host是事实上的标准头,如果您使用反向代理(例如负载均衡器和CDN),则会转发原始协议和主机。只有在服务器位于可信赖的反向代理后面时,才应设置这些变量;否则,客户端可能会伪造这些头部信息。

如果adapter-node无法正确确定您的部署URL,则在使用表单操作时可能会遇到此错误:

跨站点POST表单提交被禁止

ADDRESS_HEADER and XFF_DEPTH

传递给钩子和端点的RequestEvent对象包括一个event.getClientAddress()函数,该函数返回客户端的IP地址。默认情况下,这是连接的remoteAddress。如果您的服务器在一个或多个代理后面(例如负载均衡器),则此值将包含最内部代理的IP地址而不是客户端的IP地址,因此我们需要指定ADDRESS_HEADER来读取地址:

1
ADDRESS_HEADER=True-Client-IP node build

标题很容易被欺骗。就像PROTOCOL_HEADERHOST_HEADER一样,设置这些之前应该知道自己在做什么。

如果 ADDRESS_HEADER X-Forwarded-For,则头部值将包含一个逗号分隔的 IP 地址列表。XFF_DEPTH 环境变量应指定在您的服务器前面有多少个受信任的代理。例如,如果有三个受信任的代理,第三个代理将转发原始连接和前两个代理的地址:

1
<client address>, <proxy 1 address>, <proxy 2 address>

有些指南会告诉你阅读最左边的地址,但这样会让你容易受到欺骗攻击:

1
<spoofed address>, <client address>, <proxy 1 address>, <proxy 2 address>

我们相反地从右边读取,考虑到受信任的代理数量。在这种情况下,我们将使用XFF_DEPTH=3。

如果您需要阅读最左边的地址(并且不关心欺骗),例如提供地理定位服务,其中IP地址真实性比可信度更重要,则可以通过检查应用程序中的x-forwarded-for标头来实现。

BODY_SIZE_LIMIT

最大请求体大小(以字节为单位),包括流式传输。默认值为512kb。如果您需要更高级的功能,可以使用0来禁用此选项,并在处理程序中实现自定义检查。

Options

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

svelte.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
import adapter from '@sveltejs/adapter-node';

export default {
kit: {
adapter: adapter({
// default options are shown
out: 'build',
precompress: false,
envPrefix: '',
polyfill: true
})
}
};

out

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

precompress

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

envPrefix

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

1
2
3
4
5
envPrefix: 'MY_CUSTOM_';
MY_CUSTOM_HOST=127.0.0.1 \
MY_CUSTOM_PORT=4000 \
MY_CUSTOM_ORIGIN=https://my.site \
node build

polyfill

控制构建是否会为缺失的模块加载 polyfills。默认值为 true,仅在使用 Node 18.11 或更高版本时禁用。

Custom server

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

或者,您可以导入 handler.js 文件,该文件导出了适用于 Express、Connect 或 Polka(甚至只是内置的 http.createServer)的处理程序,并设置自己的服务器:

my-server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import { handler } from './build/handler.js';
import express from 'express';

const app = express();

// add a route that lives separately from the SvelteKit app
app.get('/healthcheck', (req, res) => {
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');
});

Troubleshooting

在服务器退出之前有清理的钩子吗?

SvelteKit 中没有内置此功能,因为这样的清理钩子高度依赖于您所在的执行环境。对于 Node,您可以使用其内置的 process.on(..) 来实现一个回调,在服务器退出之前运行:

1
2
3
4
5
6
7
function shutdownGracefully() {
// anything you need to clean up manually goes in here
db.shutdown();
}

process.on('SIGINT', shutdownGracefully);
process.on('SIGTERM', shutdownGracefully);

Static site generation

要将SvelteKit用作静态站点生成器(SSG),请使用adapter-static

这将把您的整个网站预渲染为一组静态文件。如果您只想预渲染一些页面并动态服务器呈现其他页面,则需要与prerender选项一起使用不同的适配器。

用法

使用npm i -D @sveltejs/adapter-static进行安装,然后将适配器添加到您的 svelte.config.js 文件中:

svelte.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import adapter from '@sveltejs/adapter-static';


export default {
kit: {
adapter: adapter({
// default options are shown. On some platforms
// these options are set automatically — see below
pages: 'build',
assets: 'build',
fallback: null,
precompress: false,
strict: true
})
}
};

…and add the prerender option to your root layout:

…并将prerender 选项添加到您的根布局中:

src/routes/+layout.js

1
2
// This can be false if you're using a fallback (i.e. SPA mode)
export const prerender = true;

You must ensure SvelteKit’s trailingSlash option is set appropriately for your environment. If your host does not render /a.html upon receiving a request for /a then you will need to set trailingSlash: 'always' to create /a/index.html instead.

Zero-config support

一些平台具有零配置支持(未来将会有更多):

在这些平台上,您应该省略适配器选项,以便adapter-static 可以提供最佳配置:

svelte.config.js

1
2
3
4
5
6
export default {
kit: {
adapter: adapter({...})
adapter: adapter()
}
};

Options

pages

要写入预渲染页面的目录。默认为 build

assets(资产)

将静态资源(static目录下的内容以及SvelteKit生成的客户端JS和CSS)写入的目录。通常情况下,这应该与pages相同,并且默认为pages的值,但在极少数情况下,您可能需要将页面和资产输出到不同位置。

fallback(回退)

指定单页应用程序模式的回退页面,例如 index.html200.html404.html

precompress(预压缩)

如果true, 使用Brotli和Gzip预压缩文件。这将生成.br.gz文件。

strict

默认情况下,adapter-static 会检查您的应用程序的所有页面和端点(如果有)是否都已经预渲染,或者您已经设置了fallback。此检查存在是为了防止您意外发布一款无法访问其部分内容的应用程序,因为它们不包含在最终输出中。如果您知道这是可以接受的(例如当某个页面仅在特定条件下存在时),则可以将strict设置为 false 来关闭此检查。

GitHub Pages

在为 GitHub Pages 构建时,请确保更新 paths.base 以匹配您的仓库名称,因为该站点将从 https://your-username.github.io/your-repo-name 提供而不是从根目录提供。

您需要在static文件夹中放置一个空的 .nojekyll 文件来防止 GitHub 提供的 Jekyll 管理您的站点。

GitHub Pages 的配置可能如下所示:

svelte.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import adapter from '@sveltejs/adapter-static';


const dev = process.argv.includes('dev');


/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: adapter(),
paths: {
base: dev ? '' : process.env.BASE_PATH,
}
}
};

当您进行更改时,您可以使用GitHub Actions自动将站点部署到GitHub Pages。以下是一个示例工作流程:

.github/workflows/deploy.yml

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
name: Deploy to GitHub Pages


on:
push:
branches: 'main'


jobs:
build_site:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3


# If you're using pnpm, add this step then change the commands and cache key below to use `pnpm`
# - name: Install pnpm
# uses: pnpm/action-setup@v2
# with:
# version: 8


- name: Install Node.js
uses: actions/setup-node@v3
with:
node-version: 18
cache: npm


- name: Install dependencies
run: npm install


- name: build
env:
BASE_PATH: '/your-repo-name'
run: |
npm run build
touch build/.nojekyll


- name: Upload Artifacts
uses: actions/upload-pages-artifact@v1
with:
# this should match the `pages` option in your adapter-static options
path: 'build/'


deploy:
needs: build_site
runs-on: ubuntu-latest


permissions:
pages: write
id-token: write


environment:
name: github-pages
url: ${{ steps.deployment.outputs.page_url }}

steps:
- name: Deploy
id: deployment
uses: actions/deploy-pages@v1

单页面apps

您可以通过在根布局中禁用 SSR,将使用任何适配器的 SvelteKit 应用程序转换为完全客户端渲染的单页应用程序(SPA):

src/routes/+layout.js

1
export const ssr = false;

在大多数情况下,这是不推荐的:它会损害SEO,倾向于降低感知性能,并且如果JavaScript失败或被禁用(比你想象的更常见),则使您的应用程序无法访问用户。

如果您没有任何服务器端逻辑(即+page.server.js+layout.server.js+server.js文件),则可以使用adapter-static通过添加回退页面来创建您的SPA。

Usage

使用 npm i -D @sveltejs/adapter-static 进行安装,然后在svelte.config.js中添加适配器和以下选项:

svelte.config.js

1
2
3
4
5
6
7
8
9
10
import adapter from '@sveltejs/adapter-static';


export default {
kit: {
adapter: adapter({
fallback: '200.html' // may differ from host to host
})
}
};

fallback页面是由SvelteKit从您的页面模板(例如app.html)创建的HTML页面,它加载您的应用程序并导航到正确的路由。例如Surge,一个静态Web主机,允许您添加一个200.html文件来处理不对应于静态资源或预渲染页面的任何请求。

在一些主机上可能是index.html或完全不同的其他内容 - 请查阅平台文档。

Apache

要在Apache上运行SPA,您应该添加一个static/.htaccess文件来将请求路由到回退页面:

1
2
3
4
5
6
7
8
<IfModule mod_rewrite.c>
RewriteEngine On
RewriteBase /
RewriteRule ^200\.html$ - [L]
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule . /200.html [L]
</IfModule>

渲染单个页面

如果您想要某些页面进行预渲染,您可以重新启用 SSR 并在应用程序的这些部分中同时使用prerender

src/routes/my-prerendered-page/+page.js

1
2
export const prerender = true;
export const ssr = true;

Cloudflare Pages

要部署到 Cloudflare Pages,请使用 adapter-cloudflare

当您使用 adapter-auto 时,此适配器将默认安装,但建议将其添加到您的项目中,以便自动为 event.platform 进行类型设置。

Comparisons

  • adapter-cloudflare - 支持所有SvelteKit功能;适用于Cloudflare Pages构建
  • adapter-cloudflare-workers - 支持所有SvelteKit功能;适用于Cloudflare Workers构建
  • adapter-static - 仅生成客户端静态资源;与Cloudflare Pages兼容

除非您有使用 adapter-cloudflare-workers 的特定原因,否则建议您改用此适配器。两个适配器具有等效的功能,但 Cloudflare Pages 提供了诸如 GitHub 集成、自动构建和部署、预览部署、即时回滚等功能。

Usage

使用 npm i -D @sveltejs/adapter-cloudflare 进行安装,然后将适配器添加到您的 svelte.config.js 文件中:

svelte.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
import adapter from '@sveltejs/adapter-cloudflare';


export default {
kit: {
adapter: adapter({
// See below for an explanation of these options
routes: {
include: ['/*'],
exclude: ['<all>']
}
})
}
};

Options

routes 选项允许您自定义适配器-Cloudflare生成的_routes.json文件。

  • include 定义将调用函数的路由,并默认为['/*']

  • exclude 定义不会调用函数的路由 - 这是一种更快、更便宜的方式来提供应用程序的静态资源。此数组可以包含以下特殊值:

    • 包含您应用程序构建工件(Vite 生成的文件)

    • 包含您静态目录中的内容

    • 包含预渲染页面列表

    • (默认)包括以上所有内容

您最多可以有100个includeexclude规则组合。通常情况下,您可以省略routes选项,但如果(例如)您的 <prerendered> 路径超过该限制,则可能会发现手动创建一个排除列表(其中包括 '/articles/*' 而不是自动生成 ['/articles/foo', '/articles/bar', '/articles/baz', ...])很有帮助。

Deployment(发布)

请按照 Cloudflare Pages 的入门指南开始操作。

在配置项目设置时,您必须使用以下设置:

  • 框架预设 - 无
  • 构建命令 - npm run buildvite build
  • 构建输出目录 - .svelte-kit/cloudflare
  • 环境变量
    • NODE_VERSION: 16

您需要在“production”和“preview”环境中都添加NODE_VERSION环境变量。您可以在项目设置期间或稍后在Pages项目设置中添加此变量。SvelteKit要求使用Node 16.14或更高版本,因此您应该将NODE_VERSION值设为16

环境变量

env对象包含KV/DO命名空间等信息,通过platform属性传递给SvelteKit,同时还有contextcaches,这意味着您可以在钩子和端点中访问它:

1
2
3
export async function POST({ request, platform }) {
const x = platform.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x');
}

要使这些类型在您的应用程序中可用,请在src/app.d.ts中引用它们:

src/app.d.ts

1
2
3
4
5
6
7
8
9
10
11
12
declare global {
namespace App {
interface Platform {
env?: {
YOUR_KV_NAMESPACE: KVNamespace;
YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace;
};
}
}
}

export {};

platform.env 仅在生产构建中可用。请使用 wrangler 在本地进行测试。

Notes

位于项目根目录下的/functions文件夹中的函数不会被包含在部署中,该部署编译为单个_worker.js文件。应将函数实现为SvelteKit应用程序中的服务器端点。

特定于Cloudflare Pages的_headers_redirects文件可通过将它们放入/static文件夹来用于静态资产响应(如图像)。

但是,它们对由SvelteKit动态呈现的响应没有影响,这些响应应从服务器端点或使用handle钩子返回自定义标头或重定向响应。

Troubleshooting

访问文件系统

在Serverless/Edge环境中,您无法通过fs.readFileSync等方法访问文件系统。如果您需要以这种方式访问文件,请在预渲染期间构建应用程序时执行此操作。例如,如果您有一个博客并且不想通过CMS管理内容,则需要对内容进行预渲染(或从获取内容的端点进行预渲染),并在每次添加新内容时重新部署博客。

Cloudflare Workers

要部署到Cloudflare Workers,请使用adapter-cloudflare-workers

除非您有特定的原因使用此适配器,否则我们建议使用adapter-cloudflare

Requires Wrangler v2.

Usage

使用 npm i -D @sveltejs/adapter-cloudflare-workers 进行安装,然后将适配器添加到您的 svelte.config.js 文件中:

svelte.config.js

1
2
3
4
5
6
7
8
import adapter from '@sveltejs/adapter-cloudflare-workers';


export default {
kit: {
adapter: adapter()
}
};

Basic Configuration

该适配器期望在项目根目录中找到一个名为 wrangler.toml 的文件。它应该长这样:

wrangler.toml

1
2
3
4
5
6
7
8
9
10
name = "<your-service-name>"
account_id = "<your-account-id>"

main = "./.cloudflare/worker.js"
site.bucket = "./.cloudflare/public"

build.command = "npm run build"

compatibility_date = "2021-11-12"
workers_dev = true

<your-service-name> 可以是任何名称。<your-account-id>可以在登录 Cloudflare 仪表板后从 URL 的末尾获取:

1
https://dash.cloudflare.com/<your-account-id>

您应该将 .cloudflare 目录(或者您为 main site.bucket 指定的任何目录)添加到您的 .gitignore 文件中。

如果您还没有安装wrangler并登录,您需要先进行安装:

1
2
npm i -g wrangler
wrangler login

然后你可以build应用,并发布它:

1
wrangler publish

Custom config(自定义配置)

如果您想使用除wrangler.toml以外的配置文件,可以按照以下方式操作:

svelte.config.js

1
2
3
4
5
6
7
8
import adapter from '@sveltejs/adapter-cloudflare-workers';


export default {
kit: {
adapter: adapter({ config: '<your-wrangler-name>.toml' })
}
};

Environment variables(环境变量)

env对象包含KV/DO命名空间等信息,通过platform属性传递给SvelteKit,同时还有contextcaches,这意味着您可以在钩子和端点中访问它:

1
2
3
export async function POST({ request, platform }) {
const x = platform.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x');
}

要使这些类型在您的应用程序中可用,请在src/app.d.ts中引用它们:

src/app.d.ts

1
2
3
4
5
6
7
8
9
10
11
12
declare global {
namespace App {
interface Platform {
env?: {
YOUR_KV_NAMESPACE: KVNamespace;
YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace;
};
}
}
}

export {};

platform.env 仅在生产构建中可用。请使用 wrangler 在本地进行测试。

Troubleshooting

Worker size limits

在部署到工作线程时,SvelteKit 生成的服务器会被捆绑成一个单独的文件。如果经过缩小后超出大小限制,则 Wrangler 将无法发布您的工作线程。通常情况下不太可能达到此限制,但某些大型库可能会导致这种情况发生。在这种情况下,您可以尝试通过仅在客户端上导入此类库来减小工作线程的大小。有关更多信息,请参见 FAQ。

Accessing the file system

在Serverless/Edge环境中,您无法通过fs.readFileSync等方法访问文件系统。如果您需要以这种方式访问文件,请在预渲染期间构建应用程序时执行此操作。例如,如果您有一个博客并且不想通过CMS管理内容,则需要对内容进行预渲染(或从获取内容的端点进行预渲染),并在每次添加新内容时重新部署博客。

Netlify

要部署到 Netlify,请使用 adapter-netlify

当您使用 adapter-auto 时,此适配器将默认安装,但将其添加到项目中允许您指定特定于 Netlify 的选项。

Usage

使用npm i -D @sveltejs/adapter-netlify进行安装,然后将适配器添加到您的 svelte.config.js 文件中:

svelte.config.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
import adapter from '@sveltejs/adapter-netlify';


export default {
kit: {
// default options are shown
adapter: adapter({
// if true, will create a Netlify Edge Function rather
// than using standard Node-based functions
edge: false,


// if true, will split your app into multiple functions
// instead of creating a single one for the entire app.
// if `edge` is true, this option cannot be used
split: false
})
}
};

然后,请确保在项目根目录中有一个netlify.toml文件。这将根据build.publish设置确定静态资产的写入位置,如此示例配置所示:

1
2
3
[build]
command = "npm run build"
publish = "build"

如果 netlify.toml 文件或 build.publish 值缺失,则默认值为 "build"。请注意,如果您已在 Netlify UI 中将发布目录设置为其他内容,则还需要在 netlify.toml 中设置它,或者使用默认值 "build"

Node version

新项目将默认使用 Node 16。但是,如果您正在升级一段时间前创建的项目,则可能会停留在旧版本上。请参阅 Netlify 文档以了解手动指定 Node 16 或更新版本的详细信息。

Netlify边缘函数(beta)

SvelteKit 支持 Netlify Edge Functions 的 beta 版本。如果您将选项 edge: true 传递给adapter函数,则服务器端渲染将在基于 Deno 的边缘函数中发生,该函数部署在靠近站点访问者的位置。如果设置为 false(默认值),则网站将部署到基于标准 Node 的 Netlify 函数上。

svelte.config.js

1
2
3
4
5
6
7
8
9
10
11
12
import adapter from '@sveltejs/adapter-netlify';


export default {
kit: {
adapter: adapter({
// will create a Netlify Edge Function using Deno-based
// rather than using standard Node-based functions
edge: true
})
}
};

Netlify的替代方案,以实现SvelteKit的功能

您可以使用 SvelteKit 直接提供的功能构建您的应用程序,而无需依赖于任何 Netlify 功能。使用这些功能的 SvelteKit 版本将允许它们在开发模式下使用,在集成测试中进行测试,并且如果您决定切换到其他适配器,则可以与其一起工作。但是,在某些情况下,您可能会发现使用这些功能的 Netlify 版本很有益处。一个例子是,如果您正在将已经托管在 Netlify 上的应用迁移到 SvelteKit。

重定向规则

在编译过程中,重定向规则会自动添加到您的 _redirects 文件中。(如果尚不存在,则将创建该文件。)这意味着:

netlify.toml 中的 [[redirects]] 永远不会匹配,因为 _redirects 具有更高的优先级。因此,请始终将规则放在 _redirects 文件中。
_redirects 不应具有任何自定义“捕获所有”规则,例如 /* /foobar/:splat。否则,由于 Netlify 仅处理第一个匹配规则,自动添加的规则永远不会被应用。

Netlify Forms

  1. 按照此处描述创建您的Netlify HTML表单,例如作为/routes/contact/+page.svelte。(不要忘记添加隐藏的form-name输入元素!)
  2. Netlify的构建机器人在部署时解析您的HTML文件,这意味着您的表单必须预渲染为HTML。 您可以将export const prerender = true添加到contact.svelte中以仅预渲染该页面,或者设置kit.prerender.force:true选项以预渲染所有页面。
  3. 如果您的Netlify表单具有自定义成功消息(如<form netlify ... action="/success">),则请确保相应的/routes/success/+page.svelte存在并已经预渲染。

Netlify Functions

通过这个适配器,SvelteKit 端点可以作为 Netlify 函数托管。Netlify 函数处理程序具有额外的上下文信息,包括 Netlify Identity 信息。您可以通过 hooks 和+page.server +layout.server 端点内的event.platform.context字段访问此上下文。当适配器配置中 edge 属性为 false 时,它们是无服务器函数;当其为 true 时,则是边缘函数。

+page.server.js

1
2
3
4
export const load = async (event) => {
const context = event.platform.context;
console.log(context); // shows up in your functions log in the Netlify app
};

此外,您可以通过创建一个目录并将配置添加到 netlify.toml 文件中来添加自己的 Netlify 函数。例如:

1
2
3
4
5
6
[build]
command = "npm run build"
publish = "build"

[functions]
directory = "functions"

Troubleshooting

访问文件系统

在Serverless/Edge环境中,您无法通过fs.readFileSync等方法访问文件系统。如果您需要以这种方式访问文件,请在预渲染期间构建应用程序时执行此操作。例如,如果您有一个博客并且不想通过CMS管理内容,则需要对内容进行预渲染(或从获取内容的端点进行预渲染),并在每次添加新内容时重新部署博客。

Vercel

要部署到 Vercel,请使用 adapter-vercel

当您使用 adapter-auto 时,此适配器将默认安装,但将其添加到项目中允许您指定特定于 Vercel 的选项。

Usage

使用 npm i -D @sveltejs/adapter-vercel 进行安装,然后将适配器添加到您的 svelte.config.js 文件中:

svelte.config.js

1
2
3
4
5
6
7
8
9
10
import adapter from '@sveltejs/adapter-vercel';


export default {
kit: {
adapter: adapter({
// see the 'Deployment configuration' section below
})
}
};

Deployment configuration

要控制您的路由如何作为函数部署到 Vercel,您可以通过上面显示的选项或在 +server.js+page(.server).js +layout(.server).js 文件中使用 export const config 指定部署配置。

例如,您可以将应用程序的某些部分部署为 Edge Functions…

about/+page.js

1
2
3
4
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const config = {
runtime: 'edge'
};

…以及其他作为无服务器函数(请注意,通过在布局中指定config,它适用于所有子页面):

admin/+layout.js

1
2
3
4
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const config = {
runtime: 'nodejs18.x'
};

以下选项适用于所有函数:

  • runtime: 'edge''nodejs16.x' 'nodejs18.x'。默认情况下,适配器将根据您在 Vercel 仪表板上配置的 Node 版本选择'nodejs16.x' 'nodejs18.x'
  • regions: 边缘网络区域的数组(默认为 ["iad1"] 用于无服务器函数),或者如果运行时是 edge,则为'all'(其默认值)。请注意,仅企业版计划支持多个无服务功能区域
  • split: 如果设置为 true,则会导致路由部署为单独的函数。如果在适配器级别上将 split 设置为 true,则所有路由都将作为单独的函数部署。

此外,以下选项适用于边缘功能:

  • envVarsInUse:应该在边缘功能内可访问的环境变量数组
  • external:esbuild 在捆绑函数时应视为外部依赖项的数组。这只应该用于排除不会在 Node 外运行的可选依赖项

以下选项适用于无服务器功能:

  • memory:函数可用内存量。默认值为1024 Mb,并且可以减少到128 Mb或以64Mb增量增加到Pro或Enterprise帐户中最高3008 Mb。
  • maxDuration:函数执行时间限制。Hobby 帐户默认值为10秒,Pro 帐户60秒,Enterprise 帐户900秒。
  • isr:配置增量静态再生,如下所述

如果您的函数需要访问特定区域中的数据,则建议将它们部署在相同的区域(或接近该区域)以获得最佳性能。

增量静态再生

Vercel 支持增量静态再生 (ISR),它提供了预渲染内容的性能和成本优势,同时具备动态渲染内容的灵活性。

要将 ISR 添加到路由中,请在您的config对象中包含 isr 属性:

blog/[slug]/+page.server.js

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
import { BYPASS_TOKEN } from '$env/static/private';


export const config = {
isr: {
// Expiration time (in seconds) before the cached asset will be re-generated by invoking the Serverless Function.
// Setting the value to `false` means it will never expire.
expiration: 60,


// Random token that can be provided in the URL to bypass the cached version of the asset, by requesting the asset
// with a __prerender_bypass=<token> cookie.
//
// Making a `GET` or `HEAD` request with `x-prerender-revalidate: <token>` will force the asset to be re-validated.
bypassToken: BYPASS_TOKEN,


// List of valid query parameters. Other parameters (such as utm tracking codes) will be ignored,
// ensuring that they do not result in content being regenerated unnecessarily
allowQuery: ['search']
}
};

expiration(过期)属性是必需的;其他所有属性都是可选的。

环境变量

Vercel 提供了一组特定于部署的环境变量。与其他环境变量一样,这些变量可以从 $env/static/private$env/dynamic/private 访问(有时候会有所不同——稍后再说),并且无法从其公共对应项中访问。要从客户端访问其中一个变量:

+layout.server.js

1
2
3
4
5
6
7
8
9
import { VERCEL_COMMIT_REF } from '$env/static/private';


/** @type {import('./$types').LayoutServerLoad} */
export function load() {
return {
deploymentGitBranch: VERCEL_COMMIT_REF
};
}

+layout.svelte

1
2
3
4
5
<script>
/** @type {import('./$types').LayoutServerData} */ export let data;
</script>

<p>This staging environment was deployed from {data.deploymentGitBranch}.</p>

由于在 Vercel 上构建时,所有这些变量在构建时间和运行时间之间都没有改变,因此我们建议使用 $env/static/private —— 它将静态地替换这些变量,从而实现像死代码消除等优化 —— 而不是 $env/dynamic/private。如果您正在使用 edge: true 进行部署,则必须使用 $env/static/private 或填充 envVarsInUse 配置。

Notes

Vercel函数

如果您在项目根目录的 api 目录中包含了 Vercel 函数,则任何对/api/*的请求都不会由 SvelteKit 处理。您应该将这些实现为 SvelteKit 应用程序中的 API 路由,除非您需要使用非 JavaScript 语言,在这种情况下,您需要确保在 SvelteKit 应用程序中没有任何 /api/* 路由。

Node version

在某个日期之前创建的项目将默认使用 Node 14,而 SvelteKit 需要 Node 16 或更高版本。您可以在项目设置中更改 Node 版本。

Troubleshooting

文件访问系统

在Serverless/Edge环境中,您无法通过fs.readFileSync等方法访问文件系统。如果您需要以这种方式访问文件,请在预渲染期间构建应用程序时执行此操作。例如,如果您有一个博客并且不想通过CMS管理内容,则需要对内容进行预渲染(或从获取内容的端点进行预渲染),并在每次添加新内容时重新部署博客。

编写适配器

如果您的首选环境尚未存在适配器,您可以自己构建。我们建议查看与您类似的平台适配器的源代码,并将其复制为起点。

适配器包必须实现以下 API,以创建一个 Adapter

1
2
3
4
5
6
7
8
9
10
11
12
13
/** @param {AdapterSpecificOptions} options */
export default function (options) {
/** @type {import('@sveltejs/kit').Adapter} */
const adapter = {
name: 'adapter-package-name',
async adapt(builder) {
// adapter implementation
}
};


return adapter;
}

Adapter 及其参数的类型可以在 types/index.d.ts 中找到。

adapt方法中,适配器应该完成以下几件事情:

  • 清空构建目录

  • 使用 builder.writeClientbuilder.writeServer builder.writePrerendered 编写 SvelteKit 输出

  • 输出代码:

    • ${builder.getServerDirectory()}/index.js 导入 Server
    • 使用 builder.generateManifest({ relativePath }) 生成的清单实例化应用程序
    • 监听来自平台的请求,如果需要将其转换为标准请求,调用server.respond(request, { getClientAddress })函数生成响应并进行响应
    • 通过传递给 server.respond platform 选项向 SvelteKit 公开任何特定于平台的信息
    • 在必要时全局模拟 fetch 在目标平台上工作。SvelteKit 为可以使用 node-fetch 的平台提供了 @sveltejs/kit/install-fetch 助手
  • 将输出打包以避免在目标平台上需要安装依赖项(如果必要的话)

  • 将用户的静态文件和生成的JS / CSS放置在目标平台的正确位置

如有可能,我们建议将适配器输出放在 build/ 目录下,并将任何中间输出放置在 .svelte-kit/[adapter-name] 下。

该系列文章一共四篇,以下是系列文章链接:

SvelteKit中文1-开始
SvelteKit中文2-核心概念
SvelteKit中文3-编译发布
SvelteKit中文4-高级概念



关注我的微信公众号,可收到实时更新通知

公众号:土猛的员外


目前正在接受试用中!!!

请将您的称谓、公司名称和使用场景,发邮件到yuanwai@mengjia.net。

也可以直接加微信:lxdhdgss 咨询

更多详情,可查看文章:TorchV Bot开始对外试用了!


最新内容,关注“土猛的员外”公众号