ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

SvelteKit 服务端运行时统一配置:用 `builder.generateServerInstance` 取代 `Server` 类

SvelteKit 服务端运行时统一配置:用 `builder.generateServerInstance` 取代 `Server` 类 SvelteKit 服务端运行时统一配置用builder.generateServerInstance取代Server类【免费下载链接】kitweb development, streamlined项目地址: https://gitcode.com/gh_mirrors/kit/kitSvelteKit 在 3.0 系列中重构了服务端运行时server runtime的启动方式将原本分散在适配器adapter各处的环境变量、manifest、静态资源读取等配置集中到统一的入口并由builder.generateServerInstance在构建期生成可直接消费的server对象取代此前需要手动new Server(manifest)的Server类。本文结合当前仓库的源码实现讲解这一新 API 的签名、生成物形态、底层configure机制以及 Node、Bun 等官方适配器的迁移示例帮助适配器作者与应用开发者理解并完成迁移。背景为什么要把服务端运行时配置集中到一处在旧的设计中SvelteKit 暴露了一个公开的Server类适配器需要自己拿到 SSR manifest然后手动完成一整套启动流程const { Server } await import(sveltejs/kit); const server new Server(manifest); await server.init({ env, read }); // 之后用 server.respond(request, options) 处理请求这套流程存在两个问题启动配置散落在适配器代码里env、read读取静态资源的实现、assets、building、prerendering、fix_stack_trace等运行时状态由每个适配器各自处理难以统一演进。manifest 的获取依赖旧 API构建期通过builder.generateManifest生成 manifest 字符串再由适配器自行拼装启动代码环节多、易出错。当前仓库中的变更集.changeset/server-boot-configure.md对此的表述是在一个地方配置服务端运行时弃用Server改用builder.generateServerInstance写出的server对象chore: configure the server runtime in one place, deprecateServerin favour of theserverobject written bybuilder.generateServerInstance。这一变更把配置运行时这一职责收拢到框架内部适配器只需要拿到一个已经配置好的server对象调用init与respond即可。核心 APIbuilder.generateServerInstance新的构建期 API 是Builder上的generateServerInstance方法实现在 packages/kit/src/core/adapt/builder.jsgenerateServerInstance(dest, { routes: subset, serverDirectory } {}) { const relative relative_path( path.dirname(dest), serverDirectory ?? this.getServerDirectory() ); write( dest, dedent import { create_server } from ${relative}/index.js; const manifest ${generate_manifest({ build_data, prerendered: prerendered.paths, relative_path: relative, routes: subset ? subset.map((route) /** type {import(types).RouteData} */ (lookup.get(route))) : route_data.filter((route) prerender_map.get(route.id) ! true), remotes, root: vite_config.root })}; export const server create_server(manifest); ); }参数说明dest必填生成文件的输出路径。官方适配器通常输出到builder.getServerDirectory()下的server.js见后文。opts.routes可选路由子集用于只把部分路由纳入生成的 manifest例如 split 部署场景下每个部署单元只包含自己的路由。未传时默认包含所有未被预渲染的路由route_data.filter((route) prerender_map.get(route.id) ! true)。opts.serverDirectory可选服务器代码所在目录默认取builder.getServerDirectory()即outDir/output/server。它在public.d.ts中的公开类型签名位于 packages/kit/src/exports/public.d.ts标注为since 3.0.0。生成物的形态generateServerInstance会写入一个模块它只做三件事从服务器目录的index.js导入create_server在构建期用generate_manifest生成 SSR manifest 的静态代码export const server create_server(manifest)导出一个已绑定 manifest 的server对象。也就是说适配器最终拿到的是一个开箱即用的servermanifest 的拼装完全由框架在构建期完成不再需要适配器在运行时自行加载 manifest。create_server与configure运行时配置的单一入口生成的server对象来自create_server定义在 packages/kit/src/runtime/server/index.jsexport function create_server(manifest) { let server; return { // adapters get to set env and read, nothing else init: async ({ env, read }) { server await configure({ manifest, env, read }); await server.init(); }, respond: (request, options) server.respond(request, options) }; }这里的设计意图非常明确适配器能设置的只有env和read其他一律不许碰源码注释原话adapters get to setenvandread, nothing else。init内部把manifest、env、read一起交给configure。configure真正的统一配置点configure位于同一文件 packages/kit/src/runtime/server/index.js接受一个ServerConfigureOptionsexport async function configure({ building, prerendering, manifest, read, assets, fix_stack_trace, env }) { if (building) set_building(); if (prerendering) set_prerendering(); if (manifest) set_manifest(manifest); if (read) set_read_implementation(read); if (assets ! undefined) set_assets(assets); if (fix_stack_trace) set_fix_stack_trace(fix_stack_trace); const instance await import(./instance.js); if (env) instance.set_env(env); return instance; }它的行为是把各类模块级运行时状态building、prerendering、manifest、read、assets、fix_stack_trace写入对应的内部 setter如set_manifest、set_read_implementation定义于 packages/kit/src/runtime/server/internal.js延迟导入instance.js也就是所有会求值用户代码包括 env 配置的部分都放在这次 import 之后源码注释Everything that evaluates user code, the env config included, sits behind this import确保状态先就绪通过instance.set_env(env)注入环境变量然后返回一个完整的运行时实例。ServerInstance类型configure与create_server返回的实例类型是ServerInstance定义在 packages/kit/src/types/internal.d.tsexport interface ServerInstance { init(): Promisevoid; respond(request: Request, options: InternalRequestOptions): PromiseResponse; set_env(env: Recordstring, string | undefined): void; }ServerConfigureOptions则位于同文件 packages/kit/src/types/internal.d.ts是PartialServerInitOptions并额外支持manifest、assets、building、prerendering、fix_stack_trace等字段。生成的server/index.js的模块类型ServerModuleinternal.d.ts暴露configure、create_server与format_response。Server类的弃用与generateManifest的移除Server类进入弃用状态Server类仍然保留但已被标注deprecated位于 packages/kit/src/runtime/server/index.js/** deprecated use the server written by builder.generateServerInstance, or configure */ export class Server { #server; constructor(manifest) { this.#server create_server(manifest); } init(opts) { return this.#server.init(opts); } respond(request, options) { return this.#server.respond(request, options); } }从源码看它现在只是对create_server(manifest)的薄封装行为与新的server对象完全一致——这正是一个典型的先内部收敛、再逐步移除的弃用路径。generateManifest已被移除旧的builder.generateManifest在 3.0 中已经不可用调用会直接抛出错误见 packages/kit/src/core/adapt/builder.jsgenerateManifest() { throw new Error( The generateManifest adapter API has been removed — use generateServerInstance or builder.manifest instead. You may need to update your adapter ); }同时SSRManifest与Server构造函数也已从公开类型中移除见 packages/kit/CHANGELOG.md 中 3.0.0-next.27 的 breaking 记录removeServerconstructor andSSRManifestfrom public types、replace thebuilder.generateManifestwithbuilder.generateServerInstanceandbuilder.manifest。generateManifest的公开类型声明上也标注了deprecated removed in 3.0public.d.ts。官方适配器中的实际用法adapter-nodesveltejs/adapter-node在adapt()中调用generateServerInstance见 packages/adapter-node/index.jsconst server builder.getServerDirectory(); builder.generateServerInstance(${server}/server.js);即把生成的模块写到output/server/server.js随后随服务器代码一起拷贝到输出目录。运行时适配器的处理器packages/adapter-node/src/handler.js这样使用它import { server, dir, base, ... } from #sveltejs/adapter-node; await server.init({ env: process.env, read: (file) createReadableStream(${asset_dir}/${file}) });然后对每个请求调用server.respond(request, { platform, getClientAddress })handler.js。注意适配器层只负责传入env与read完全符合上文create_server注释中adapters get to setenvandread, nothing else的约束。adapter-bunsveltejs/adapter-bun的用法与 Node 版对称见 packages/adapter-bun/index.jsconst server builder.getServerDirectory(); builder.generateServerInstance(${server}/server.js);测试与类型验证仓库中仍有旧式用法的测试遗留例如 packages/kit/test/apps/basics/test/vitest/server.spec.js 使用new Server(manifest)packages/adapter-bun/test/handler.spec.ts 的 mock 也构造new Server()它们对应弃用前的行为新适配器代码则应统一改为generateServerInstance产出的server。迁移指南如果你是适配器作者移除generateManifest调用它在 3.0 中会抛错如需路由子集改传给generateServerInstance(dest, { routes })。用generateServerInstance生成启动模块输出到服务器目录builder.getServerDirectory()下例如server/server.js。消费server对象await server.init({ env, read })后用server.respond(request, options)处理请求不要再new Server(manifest)也不要直接引用公开的SSRManifest类型。如需手动配置也可以直接使用生成的模块中导出的configure(options)类型见ServerModule它是全部运行时状态的唯一注入点。如果你只是应用开发者通常你无需改动业务代码这些变化发生在适配器层。只要使用支持 3.0 的官方适配器Node、Bun 等重新构建应用server对象的生成与启动就会自动切换到新机制。小结本次变更的核心是把 SvelteKit 服务端运行时的配置动作收敛到框架内部构建期builder.generateServerInstance在构建时生成包含完整 manifest 的server模块取代旧generateManifestnew Server(manifest)的组合运行时create_server与configure成为唯一配置入口适配器只能注入env与read其余状态由框架统一管理兼容期Server类被标记弃用并退化为create_server的薄封装为后续彻底移除留出过渡空间。对适配器生态而言这意味着更少的样板代码、更一致的行为以及更小的出错面——这正是在同一个地方配置服务端运行时这一变更的价值所在。【免费下载链接】kitweb development, streamlined项目地址: https://gitcode.com/gh_mirrors/kit/kit创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表