Writing adapters
If an adapter for your preferred environment doesn't yet exist, you can build your own. We recommend looking at the source for an adapter to a platform similar to yours and copying it as a starting point.
Adapter packages implement the following API, which creates an Adapter:
/** @param {AdapterSpecificOptions} options */
export default function (options: anyoptions) {
/** @type {import('@sveltejs/kit').Adapter} */
const const adapter: Adapteradapter = {
Adapter.name: stringThe name of the adapter, using for logging. Will typically correspond to the package name.
name: 'adapter-package-name',
async Adapter.adapt: (builder: Builder) => MaybePromise<void>This function is called after SvelteKit has built your app.
adapt(builder: Builderbuilder) {
// adapter implementation
},
async Adapter.emulate?: (() => MaybePromise<Emulator>) | undefinedCreates an Emulator, which allows the adapter to influence the environment
during dev, build and prerendering.
emulate() {
return {
async Emulator.platform?(details: {
config: any;
prerender: PrerenderOption;
}): MaybePromise<App.Platform>
A function that is called with the current route config and prerender option
and returns an App.Platform object
platform({ config: anyconfig, prerender: PrerenderOptionprerender }) {
// the returned object becomes `event.platform` during dev, build and
// preview. Its shape is that of `App.Platform`
}
}
},
Adapter.supports?: {
read?: (details: {
config: Record<string, any>;
route: {
id: string;
};
}) => boolean;
instrumentation?: () => boolean;
} | undefined
Checks called during dev and build to determine whether specific features will work in production with this adapter.
supports: {
read: ({ config: Record<string, any>config, route: {
id: string;
}
route }) => {
// Return `true` if the route with the given `config` can use `read`
// from `$app/server` in production, return `false` if it can't.
// Or throw a descriptive error describing how to configure the deployment
},
instrumentation: () => {
// Return `true` if this adapter supports loading `instrumentation.server.js`.
// Return `false if it can't, or throw a descriptive error.
}
},
// Specify the path of a module to customise request handling
Adapter.customHandler?: string | undefinedThe path to a module whose default export is a custom handler.
customHandler: import.meta.ImportMeta.resolve(specifier: string, parent?: string | URL): string (+1 overload)import.meta.resolve is a module-relative resolution function scoped to
each module, returning the URL string.
const dependencyAsset = import.meta.resolve('component-lib/asset.css');
// file:///app/node_modules/component-lib/asset.css
import.meta.resolve('./dep.js');
// file:///app/dep.js
All features of the Node.js module resolution are supported. Dependency
resolutions are subject to the permitted exports resolutions within the package.
Caveats:
- This can result in synchronous file-system operations, which
can impact performance similarly to
require.resolve.
- This feature is not available within custom loaders (it would
create a deadlock).
resolve('./handler.js'),
Adapter.vite?: {
plugins?: Plugin[];
} | undefined
vite: {
plugins?: Plugin<any>[] | undefinedPlugins provided by the adapter are placed before any of SvelteKit's own plugins.
plugins: [
// add plugins here to integrate with Vite
]
}
};
return const adapter: Adapteradapter;
}Of these, name and adapt are required. emulate, customHandler, vite.plugins and supports are optional.
Within the adapt method, there are a number of things that an adapter should do:
- Clear out the build directory
- Write SvelteKit output with
builder.writeClient,builder.writeServer, andbuilder.writePrerendered - Output code that:
- Imports
Serverfrom${builder.getServerDirectory()}/index.js - Instantiates the app with a manifest generated with
builder.generateManifest({ relativePath }) - Listens for requests from the platform, converts them to a standard
Requestif necessary, calls theserver.respond(request, { getClientAddress })function to generate aResponseand responds with it - expose any platform-specific information to SvelteKit via the
platformoption passed toserver.respond
- Imports
- Bundle the output to avoid needing to install dependencies on the target platform, if necessary
- Put the user's static files and the generated JS/CSS in the correct location for the target platform
Where possible, we recommend putting the adapter output under the build/ directory with any intermediate output placed under .svelte-kit/[adapter-name].
Custom request handler
You can customise your server's initialisation and request handling by adding a customHandler property resolved to the path of your handler file.
/** @param {AdapterSpecificOptions} options */
export default function (options: anyoptions) {
/** @type {import('@sveltejs/kit').Adapter} */
const const adapter: Adapteradapter = {
Adapter.name: stringThe name of the adapter, using for logging. Will typically correspond to the package name.
name: 'adapter-package-name',
async Adapter.adapt: (builder: Builder) => MaybePromise<void>This function is called after SvelteKit has built your app.
adapt(builder: Builderbuilder) {
// adapter implementation
},
Adapter.customHandler?: string | undefinedThe path to a module whose default export is a custom handler.
customHandler: import.meta.ImportMeta.resolve(specifier: string, parent?: string | URL): string (+1 overload)import.meta.resolve is a module-relative resolution function scoped to
each module, returning the URL string.
const dependencyAsset = import.meta.resolve('component-lib/asset.css');
// file:///app/node_modules/component-lib/asset.css
import.meta.resolve('./dep.js');
// file:///app/dep.js
All features of the Node.js module resolution are supported. Dependency
resolutions are subject to the permitted exports resolutions within the package.
Caveats:
This can result in synchronous file-system operations, which
can impact performance similarly to require.resolve.
This feature is not available within custom loaders (it would
create a deadlock).
resolve('./src/handler.js')
}
return const adapter: Adapteradapter;
};The handler file should export a default function that returns a request handler. The should return a Response such as by calling server.respond along with any platform-specific context.
/** @type {import('@sveltejs/kit').SSRHandler} */
export default async function function handler(server: {
respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}): MaybePromise<(request: Request) => Promise<Response>>
handler(server: {
respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server) {
// perform setup work here
return async (request: Requestrequest) => {
// custom request/response handling logic goes here
return await server: {
respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server.respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>respond(request: Requestrequest, {
platform?: App.Platform | undefinedplatform: {
// the shape of `App.Platform`
}
});
};
}import type { type SSRHandler = (server: {
respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}) => MaybePromise<(request: Request) => Promise<Response>>
The custom handler an adapter can specify to customise request handling. It is expected to return a function which returns a Response or calls server.respond with any platform-specific context.
SSRHandler } from '@sveltejs/kit';
export const const handler: SSRHandlerhandler: type SSRHandler = (server: {
respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}) => MaybePromise<(request: Request) => Promise<Response>>
The custom handler an adapter can specify to customise request handling. It is expected to return a function which returns a Response or calls server.respond with any platform-specific context.
SSRHandler = async (server: {
respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server) => {
// perform setup work here
return async (request: Requestrequest) => {
// custom request/response handling logic goes here
return await server: {
respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>;
}
server.respond: (request: Request, options?: Pick<RequestOptions, "platform">) => Promise<Response>respond(request: Requestrequest, {
platform?: App.Platform | undefinedplatform: {
// the shape of `App.Platform`
}
});
};
};Edit this page on GitHub llms.txt