倔头 發表於 2025-3-26 20:36:00

SvelteKit 最新中文文档教程(11)—— 部署 Netlify 和 Vercel

<h2 id="前言">前言</h2>
<p>Svelte,一个语法简洁、入门容易,面向未来的前端框架。</p>
<p>从 Svelte 诞生之初,就备受开发者的喜爱,根据统计,<strong>从 2019 年到 2024 年,连续 6 年一直是开发者最感兴趣的前端框架 No.1</strong>:</p>
<p><img src="https://yayujs-blog.oss-cn-beijing.aliyuncs.com/405488775-48df16b1-939c-489b-8d52-6071869893f0.png"></p>
<p>Svelte 以其独特的编译时优化机制著称,具有<strong>轻量级</strong>、<strong>高性能</strong>、<strong>易上手</strong>等特性,<strong>非常适合构建轻量级 Web 项目</strong>。</p>
<p>为了帮助大家学习 Svelte,我同时搭建了 Svelte 最新的中文文档站点。</p>
<p>如果需要进阶学习,也可以入手我的小册《Svelte 开发指南》,语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!</p>
<p>欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。</p>
<h2 id="netlify">Netlify</h2>
<p>要部署到 Netlify,请使用 <code>adapter-netlify</code>。</p>
<p>当您使用 <code>adapter-auto</code> 时,此适配器将默认安装,但将其添加到您的项目中可以指定 Netlify 特定的选项。</p>
<h3 id="用法">用法</h3>
<p>使用 <code>npm i -D @sveltejs/adapter-netlify</code> 安装,然后将适配器添加到您的 <code>svelte.config.js</code>:</p>
<pre><code class="language-js">// @errors: 2307
/// file: svelte.config.js
import adapter from '@sveltejs/adapter-netlify';

export default {
        kit: {
                // 显示默认选项
                adapter: adapter({
                        // 如果为 true,将创建 Netlify Edge Function 而不是
                        // 使用标准的基于 Node 的函数
                        edge: false,

                        // 如果为 true,将把您的应用拆分为多个函数
                        // 而不是为整个应用创建单个函数。
                        // 如果 `edge` 为 true,则不能使用此选项
                        split: false
                })
        }
};
</code></pre>
<p>然后,确保在项目根目录中有一个 netlify.toml 文件。这将根据 <code>build.publish</code> 设置确定写入静态资源的位置,如此示例配置所示:</p>
<pre><code class="language-toml">
        command = "npm run build"
        publish = "build"
</code></pre>
<p>如果缺少 <code>netlify.toml</code> 文件或 <code>build.publish</code> 值,将使用默认值 <code>"build"</code>。请注意,如果您在 Netlify UI 中将发布目录设置为其他值,那么您也需要在 <code>netlify.toml</code> 中设置它,或使用默认值 <code>"build"</code>。</p>
<h4 id="node-版本">Node 版本</h4>
<p>新项目默认将使用当前的 Node LTS 版本。但是,如果您正在升级很久以前创建的项目,它可能会停留在旧版本上。有关手动指定当前 Node 版本的详细信息,请参阅 Netlify 文档。</p>
<h3 id="netlify-edge-functions">Netlify Edge Functions</h3>
<p>SvelteKit 支持 Netlify Edge Functions。如果您向 <code>adapter</code> 函数传递 <code>edge: true</code> 选项,服务端渲染将在部署在靠近站点访问者的基于 Deno 的边缘函数中进行。如果设置为 <code>false</code>(默认值),站点将部署到基于 Node 的 Netlify Functions。</p>
<pre><code class="language-js">// @errors: 2307
/// file: svelte.config.js
import adapter from '@sveltejs/adapter-netlify';

export default {
        kit: {
                adapter: adapter({
                        // 将使用基于 Deno 的 Netlify Edge Function
                        // 而不是使用标准的基于 Node 的函数
                        edge: true
                })
        }
};
</code></pre>
<h3 id="sveltekit-功能的-netlify-替代方案">SvelteKit 功能的 Netlify 替代方案</h3>
<p>您可以直接使用 SvelteKit 提供的功能构建应用,而无需依赖任何 Netlify 功能。使用这些功能的 SvelteKit 版本将允许它们在开发模式下使用,通过集成测试进行测试,并在您决定切换到其他适配器时能够正常工作。但是,在某些情况下,使用这些功能的 Netlify 版本可能会更有利。例如,如果您正在将已经托管在 Netlify 上的应用迁移到 SvelteKit。</p>
<h4 id="重定向规则">重定向规则</h4>
<p>在编译期间,重定向规则会自动附加到您的 <code>_redirects</code> 文件中。(如果该文件尚不存在,它将被创建。)这意味着:</p>
<ul>
<li><code>netlify.toml</code> 中的 <code>[]</code> 永远不会匹配,因为 <code>_redirects</code> 具有更高的优先级。因此,始终将您的规则放在 <code>_redirects</code> 文件中。</li>
<li><code>_redirects</code> 不应该有任何自定义的"捕获所有"规则,如 <code>/* /foobar/:splat</code>。否则,由于 Netlify 只处理第一个匹配的规则,自动附加的规则将永远不会被应用。</li>
</ul>
<h4 id="netlify-forms">Netlify Forms</h4>
<ol>
<li>按照这里的描述创建您的 Netlify HTML 表单,例如作为 <code>/routes/contact/+page.svelte</code>。(别忘了添加隐藏的 <code>form-name</code> input 元素!)</li>
<li>Netlify 的构建机器人在部署时解析您的 HTML 文件,这意味着您的表单必须预渲染为 HTML 。您可以在您的 <code>contact.svelte</code> 中添加 <code>export const prerender = true</code> 来仅预渲染该页面,或设置 <code>kit.prerender.force: true</code> 选项来预渲染所有页面。</li>
<li>如果您的 Netlify 表单有一个自定义成功消息,如 <code>&lt;form netlify ... action="/success"&gt;</code>,则确保相应的 <code>/routes/success/+page.svelte</code> 存在并已预渲染。</li>
</ol>
<h4 id="netlify-functions">Netlify Functions</h4>
<p>使用此适配器,SvelteKit 端点将作为 Netlify Functions 托管。Netlify 函数处理程序具有额外的上下文,包括 Netlify Identity 信息。您可以通过您的 hooks 和 <code>+page.server</code> 或 <code>+layout.server</code> 端点中的 <code>event.platform.context</code> 字段访问此上下文。当适配器配置中的 <code>edge</code> 属性为 <code>false</code> 时,这些是serverless functions,当为 <code>true</code> 时,这些是edge functions。</p>
<pre><code class="language-js">// @errors: 2705 7006
/// file: +page.server.js
export const load = async (event) =&gt; {
        const context = event.platform.context;
        console.log(context); // 在 Netlify 应用的函数日志中显示
};
</code></pre>
<p>此外,您可以通过创建一个目录并在 <code>netlify.toml</code> 文件中添加配置来添加您自己的 Netlify 函数。例如:</p>
<pre><code class="language-toml">
        command = "npm run build"
        publish = "build"


        directory = "functions"
</code></pre>
<h3 id="故障排除">故障排除</h3>
<h4 id="访问文件系统">访问文件系统</h4>
<p>您不能在 edge 部署中使用 <code>fs</code>。</p>
<p>您<em>可以</em>在 serverless 部署中使用它,但它不会按预期工作,因为文件不会从您的项目复制到部署中。相反,使用 <code>$app/server</code> 中的 <code>read</code> 函数来访问您的文件。<code>read</code> 在 edge 部署中不起作用(这在将来可能会改变)。</p>
<p>或者,您可以预渲染相关路由。</p>
<h2 id="vercel">Vercel</h2>
<p>要部署到 Vercel,请使用 <code>adapter-vercel</code>。</p>
<p>当您使用 <code>adapter-auto</code> 时,这个适配器会被默认安装,但将其添加到您的项目中可以让您指定 Vercel 特定的选项。</p>
<h3 id="用法-1">用法</h3>
<p>使用 <code>npm i -D @sveltejs/adapter-vercel</code> 安装,然后将适配器添加到您的 <code>svelte.config.js</code> 中:</p>
<pre><code class="language-js">// @errors: 2307 2345
/// file: svelte.config.js
import adapter from '@sveltejs/adapter-vercel';

export default {
        kit: {
                adapter: adapter({
                        // 可以在此处设置选项,详见下文
                })
        }
};
</code></pre>
<h3 id="部署配置">部署配置</h3>
<p>要控制您的路由如何作为函数部署到 Vercel,您可以通过上面显示的选项或在 <code>+server.js</code>、<code>+page(.server).js</code> 和 <code>+layout(.server).js</code> 文件中使用 <code>export const config</code> 来指定部署配置。</p>
<p>例如,您可以将应用的某些部分部署为 Edge Functions...</p>
<pre><code class="language-js">/// file: about/+page.js
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const config = {
        runtime: 'edge'
};
</code></pre>
<p>...其他部分则作为 Serverless Functions(注意,在布局中指定 <code>config</code> 时,它会应用于所有子页面):</p>
<pre><code class="language-js">/// file: admin/+layout.js
/** @type {import('@sveltejs/adapter-vercel').Config} */
export const config = {
        runtime: 'nodejs22.x'
};
</code></pre>
<p>以下选项适用于所有函数:</p>
<ul>
<li><code>runtime</code>:<code>'edge'</code>、<code>'nodejs18.x'</code>、<code>'nodejs20.x'</code> 或 <code>'nodejs22.x'</code>。默认情况下,适配器会选择与您的项目在 Vercel 仪表板上配置的 Node 版本对应的 <code>'nodejs&lt;version&gt;.x'</code></li>
<li><code>regions</code>:边缘网络区域数组(对于 serverless 函数默认为 <code>["iad1"]</code>)或当 <code>runtime</code> 为 <code>edge</code> 时为 <code>'all'</code>(其默认值)。注意,serverless 函数的多区域部署仅在企业版计划中支持</li>
<li><code>split</code>:如果为 <code>true</code>,会导致路由被部署为独立函数。如果在适配器级别将 <code>split</code> 设置为 <code>true</code>,所有路由都将被部署为独立函数</li>
</ul>
<p>此外,以下选项适用于 edge functions:</p>
<ul>
<li><code>external</code>:esbuild 在打包函数时应该视为外部的依赖项数组。这只应用于排除在 Node 之外不会运行的可选依赖项</li>
</ul>
<p>以下选项适用于 serverless 函数:</p>
<ul>
<li><code>memory</code>:函数可用的内存量。默认为 <code>1024</code> Mb,可以降低到 <code>128</code> Mb 或在专业版或企业版账户中以 64Mb 为增量增加到 <code>3008</code> Mb</li>
<li><code>maxDuration</code>:函数的最大执行时长。Hobby 账户默认为 <code>10</code> 秒,Pro 为 <code>15</code> 秒,Enterprise 为 <code>900</code> 秒</li>
<li><code>isr</code>:配置增量静态重生成,详见下文</li>
</ul>
<p>如果您的函数需要访问特定区域的数据,建议将它们部署在同一区域(或靠近该区域)以获得最佳性能。</p>
<h3 id="图像优化">图像优化</h3>
<p>您可以设置 <code>images</code> 配置来控制 Vercel 如何构建您的图像。完整细节请参见图像配置参考。例如,您可以设置:</p>
<pre><code class="language-js">// @errors: 2300 2842 7031 1181 1005 1136 1128
/// file: svelte.config.js
import adapter from '@sveltejs/adapter-vercel';

export default {
        kit: {
                adapter({
                        images: {
                                sizes: ,
                                formats: ['image/avif', 'image/webp'],
                                minimumCacheTTL: 300,
                                domains: ['example-app.vercel.app'],
                        }
                })
        }
};
</code></pre>
<h3 id="增量静态重生成">增量静态重生成</h3>
<p>Vercel 支持增量静态重生成 (ISR),它提供了预渲染内容的性能和成本优势,同时保持动态渲染内容的灵活性。</p>
<p>要为路由添加 ISR,在您的 <code>config</code> 对象中包含 <code>isr</code> 属性:</p>
<pre><code class="language-js">// @errors: 2664
import { BYPASS_TOKEN } from '$env/static/private';

export const config = {
        isr: {
                // 缓存资源将通过调用 Serverless 函数重新生成的过期时间(以秒为单位)。
                // 将值设置为 `false` 表示永不过期。
                expiration: 60,

                // 可以在 URL 中提供的随机令牌,通过使用 __prerender_bypass=&lt;token&gt; cookie 请求资源来绕过缓存版本。
                //
                // 使用 `x-prerender-revalidate: &lt;token&gt;` 进行 `GET` 或 `HEAD` 请求将强制重新验证资源。
                bypassToken: BYPASS_TOKEN,

                // 有效查询参数列表。其他参数(如 utm 跟踪代码)将被忽略,
                // 确保它们不会导致不必要的内容重新生成
                allowQuery: ['search']
        }
};
</code></pre>
<p><code>expiration</code> 属性是必需的;其他都是可选的。</p>
<blockquote>
<p>预渲染的页面将忽略 ISR 配置。</p>
</blockquote>
<h3 id="环境变量">环境变量</h3>
<p>Vercel 提供了一组用于部署的特定的环境变量。像其他环境变量一样,这些变量可以从 <code>$env/static/private</code> 和 <code>$env/dynamic/private</code> 访问(有时候 — 稍后会详细说明),并且不能从它们的公共对应项访问。要从客户端访问这些变量之一:</p>
<pre><code class="language-js">// @errors: 2305
/// file: +layout.server.js
import { VERCEL_COMMIT_REF } from '$env/static/private';

/** @type {import('./$types').LayoutServerLoad} */
export function load() {
        return {
                deploymentGitBranch: VERCEL_COMMIT_REF
        };
}
</code></pre>
<pre><code class="language-svelte">&lt;!--- file: +layout.svelte ---&gt;
&lt;script&gt;
        /** @type {{ data: import('./$types').LayoutServerData }} */
        let { data } = $props();
&lt;/script&gt;

&lt;p&gt;此暂存环境是从 {data.deploymentGitBranch} 部署的。&lt;/p&gt;
</code></pre>
<p>由于在 Vercel 上构建时,所有这些变量在构建时和运行时之间都保持不变,我们建议使用 <code>$env/static/private</code>(它会静态替换变量,启用死代码消除等优化)而不是 <code>$env/dynamic/private</code>。</p>
<h3 id="版本偏差保护">版本偏差保护</h3>
<p>当部署应用的新版本时,之前版本的资源可能不再可访问。如果用户在此时正在使用您的应用,在导航时可能会导致错误 — 这就是所谓的<em>版本偏差</em>。SvelteKit 通过检测由版本偏差导致的错误并触发硬重载来获取应用的最新版本来缓解这个问题,但这会导致客户端状态丢失。(您也可以通过观察 <code>updated</code> store 值来主动缓解它,这个值会告诉客户端何时部署了新版本。)</p>
<p>版本偏差保护是Vercel 的一个功能,可以将客户端请求路由到它们的原始部署。当用户访问您的应用时,会设置一个带有部署 ID 的 cookie,只要版本偏差保护处于活动状态,任何后续请求都会被路由到该部署。当他们重新加载页面时,将获得最新的部署。(<code>updated</code> store 不受此行为影响,因此将继续报告新的部署。)要启用它,请访问 Vercel 上项目设置的高级部分。</p>
<p>基于 cookie 的版本偏差保护有一个注意事项:如果用户在多个标签页中打开了您的应用的多个版本,旧版本的请求将被路由到较新的版本,这意味着它们将回退到 SvelteKit 的内置版本偏差保护。</p>
<h3 id="注意事项">注意事项</h3>
<h4 id="vercel-函数">Vercel 函数</h4>
<p>如果您在项目根目录的 <code>api</code> 目录中有 Vercel 函数,任何对 <code>/api/*</code> 的请求将<em>不会</em>由 SvelteKit 处理。您应该在您的 SvelteKit 应用中将这些实现为 API 路由,除非您需要使用非 JavaScript 语言,在这种情况下您需要确保您的 SvelteKit 应用中没有任何 <code>/api/*</code> 路由。</p>
<h4 id="node-版本-1">Node 版本</h4>
<p>在某个日期之前创建的项目可能默认使用比 SvelteKit 当前要求的更旧的 Node 版本。您可以在项目设置中更改 Node 版本。</p>
<h3 id="故障排除-1">故障排除</h3>
<h4 id="访问文件系统-1">访问文件系统</h4>
<p>您不能在 edge functions 中使用 <code>fs</code>。</p>
<p>您<em>可以</em>在 serverless 函数中使用它,但它不会按预期工作,因为文件不会从您的项目复制到您的部署中。相反,使用 <code>$app/server</code> 中的 <code>read</code> 函数来访问您的文件。<code>read</code> 在部署为 edge functions 的路由中不起作用(这在将来可能会改变)。</p>
<p>或者,您可以预渲染相关路由。</p>
<h2 id="svelte-中文文档">Svelte 中文文档</h2>
<p>点击查看中文文档:</p>
<ul>
<li>SvelteKit Netlify</li>
<li>SvelteKit Vercel</li>
</ul>
<p>系统学习 Svelte,欢迎入手小册《Svelte 开发指南》。语法篇、实战篇、原理篇三大篇章带你系统掌握 Svelte!</p>
<p>此外我还写过 JavaScript 系列、TypeScript 系列、React 系列、Next.js 系列、冴羽答读者问等 14 个系列文章, 全系列文章目录:https://github.com/mqyqingfeng/Blog</p>
<p>欢迎围观我的“网页版朋友圈”、加入“冴羽·成长陪伴社群”,踏上“前端大佬成长之路”。</p><br><br>
来源:https://www.cnblogs.com/yayujs/p/18794624
頁: [1]
查看完整版本: SvelteKit 最新中文文档教程(11)—— 部署 Netlify 和 Vercel