Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions .changeset/lazy-tools-bathe.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
'@sveltejs/kit': major
---

feat: allow adapters to provide additional Vite plugins
Original file line number Diff line number Diff line change
Expand Up @@ -39,14 +39,19 @@ export default function (options) {
// Return `true` if this adapter supports loading `instrumentation.server.js`.
// Return `false if it can't, or throw a descriptive error.
}
},
vite: {
plugins: [
// add plugins here to integrate with Vite
]
}
};

return adapter;
}
```

Of these, `name` and `adapt` are required. `emulate` and `supports` are optional.
Of these, `name` and `adapt` are required. `emulate`, `vite.plugins` and `supports` are optional.

Within the `adapt` method, there are a number of things that an adapter should do:

Expand Down
8 changes: 8 additions & 0 deletions packages/kit/src/exports/public.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@ import {
import { BuildData, SSRNodeLoader, SSRRoute, ValidatedConfig } from 'types';
import { SvelteConfig } from '@sveltejs/vite-plugin-svelte';
import { StandardSchemaV1 } from '@standard-schema/spec';
import { Plugin } from 'vite';
import {
RouteId as AppRouteId,
LayoutParams as AppLayoutParams,
Expand Down Expand Up @@ -68,6 +69,13 @@ export interface Adapter {
* during dev, build and prerendering.
*/
emulate?: () => MaybePromise<Emulator>;
vite?: {
/**
* Plugins provided by the adapter are placed before any of SvelteKit's own plugins.
* @since 3.0.0
*/
plugins?: Plugin[];
};
}

export type LoadProperties<input extends Record<string, any> | void> = input extends void
Expand Down
121 changes: 74 additions & 47 deletions packages/kit/src/exports/vite/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -1171,6 +1171,9 @@ function kit({ svelte_config }) {
}
};

/** @type {() => Promise<void> | undefined} */
let finalise;

/** @type {Plugin} */
const plugin_compile = {
name: 'vite-plugin-sveltekit-compile',
Expand Down Expand Up @@ -1773,63 +1776,87 @@ function kit({ svelte_config }) {
})};\n`
);

if (service_worker_entry_file) {
log.info('Building service worker');

// mirror client settings that we couldn't set per environment in the config hook
builder.environments.serviceWorker.config.define =
builder.environments.client.config.define;
builder.environments.serviceWorker.config.resolve.alias = [
...get_config_aliases(kit, vite_config.root)
];
// defer the adapt step to run after any buildApp hooks the adapter might have
finalise = async () => {
// defer creating the service worker too because other plugins might build
// the client environment again and overwrite our service worker which
// outputs to the same directory
if (service_worker_entry_file) {
log.info('Building service worker');

// mirror client settings that we couldn't set per environment in the config hook
builder.environments.serviceWorker.config.define =
builder.environments.client.config.define;
builder.environments.serviceWorker.config.resolve.alias = [
...get_config_aliases(kit, vite_config.root)
];

// we have to overwrite this because it can't be configured per environment in the config hook
builder.environments.serviceWorker.config.experimental.renderBuiltUrl = (filename) => {
return {
runtime: `new URL(${JSON.stringify(filename)}, location.href).pathname`
// we have to overwrite this because it can't be configured per environment in the config hook
builder.environments.serviceWorker.config.experimental.renderBuiltUrl = (filename) => {
return {
runtime: `new URL(${JSON.stringify(filename)}, location.href).pathname`
};
};
};

await builder.build(builder.environments.serviceWorker);
}

console.log(
`\nRun ${styleText(['bold', 'cyan'], 'npm run preview')} to preview your production build locally.`
);

if (kit.adapter) {
const { adapt } = await import('../../core/adapt/index.js');
await adapt(
svelte_config,
build_data,
metadata,
prerendered,
prerender_results.prerender_map,
log,
remotes,
vite_config,
explicit_env_config
);
} else {
console.log(styleText(['bold', 'yellow'], '\nNo adapter specified'));
await builder.build(builder.environments.serviceWorker);
}

const link = styleText(['bold', 'cyan'], 'https://svelte.dev/docs/kit/adapters');
console.log(
`See ${link} to learn how to configure your app to run on the platform of your choosing`
`\nRun ${styleText(['bold', 'cyan'], 'npm run preview')} to preview your production build locally.`
);

if (kit.adapter) {
const { adapt } = await import('../../core/adapt/index.js');
await adapt(
svelte_config,
build_data,
metadata,
prerendered,
prerender_results.prerender_map,
log,
remotes,
vite_config,
explicit_env_config
);
} else {
console.log(styleText(['bold', 'yellow'], '\nNo adapter specified'));

const link = styleText(['bold', 'cyan'], 'https://svelte.dev/docs/kit/adapters');
console.log(
`See ${link} to learn how to configure your app to run on the platform of your choosing`
);
}
};
}
};

/** @type {Plugin} */
const plugin_adapter = {
name: 'vite-plugin-sveltekit-adapter',
apply: 'build',
buildApp: {
// this will run after any buildApp hooks provided by other Vite plugins
// see https://vite.dev/guide/api-environment-frameworks#environments-during-build
order: 'post',
async handler() {
await finalise?.();
}
}
};

return [
plugin_setup,
plugin_remote,
plugin_virtual_modules,
process.env.TEST !== 'true' ? plugin_guard : undefined,
service_worker_entry_file && plugin_service_worker_env,
plugin_service_worker,
plugin_compile
].filter((p) => !!p);
return /** @type {Plugin[]} */ (
[
svelte_config.kit.adapter?.vite?.plugins,
plugin_setup,
plugin_remote,
plugin_virtual_modules,
process.env.TEST !== 'true' ? plugin_guard : undefined,
service_worker_entry_file ? plugin_service_worker_env : undefined,
plugin_service_worker,
plugin_compile,
plugin_adapter
].filter(Boolean)
);
}

/**
Expand Down
8 changes: 8 additions & 0 deletions packages/kit/types/index.d.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
declare module '@sveltejs/kit' {
import type { SvelteConfig } from '@sveltejs/vite-plugin-svelte';
import type { StandardSchemaV1 } from '@standard-schema/spec';
import type { Plugin } from 'vite';
import type { RouteId as AppRouteId, LayoutParams as AppLayoutParams, ResolvedPathname } from '$app/types';
// @ts-ignore this is an optional peer dependency so could be missing. Written like this so dts-buddy preserves the ts-ignore
type Span = import('@opentelemetry/api').Span;
Expand Down Expand Up @@ -42,6 +43,13 @@ declare module '@sveltejs/kit' {
* during dev, build and prerendering.
*/
emulate?: () => MaybePromise<Emulator>;
vite?: {
/**
* Plugins provided by the adapter are placed before any of SvelteKit's own plugins.
* @since 3.0.0
*/
plugins?: Plugin[];
};
}

export type LoadProperties<input extends Record<string, any> | void> = input extends void
Expand Down
Loading