Skip to content

Commit ecb423b

Browse files
Rich-HarrisbenmccannRich Harris
authored
Overhaul adapter API (#2931)
* start fiddling about with code-split server code * generate build data * working, minus adapters * prerendering * WIP * tidy some stuff up * fix prefixes * adapter-node working * tidy up * tidy * make copy opts optional * tidy * netlify working albeit with single function * expose route data to adapters * some progress * lint * remove sandbox example from PR * implement createEntries API * fix some tests * AMP fix * tests all passing * update gitignore * disable adapter-node tests for now * typechecking * always create prerendered output directory * manifest -> generateManifest, add utils-level method * spread -> rest * finesse return value of copy helper * no need to pass config through to adapter * Update packages/kit/src/core/build/index.js Co-authored-by: Ben McCann <[email protected]> * fix * refactor out method extraction * add comment to resolve separate routes/components entry point detection * remove out of date comment * nicer rollup output types * actually that caused chaos, doing this instead * fix tests * update adapter-cloudflare * refactor build functions into client/server/service worker modules * make build_server more readable * oops * gah * windows fix * split manifest into public and private parts, so we can use manifest.assets in adapters * lint * prevent duplication of asset list in functions * exclude prerendered pages from functions * lint * get vercel adapter working (with v1 filesystem API) * target node14 * rename utils -> builder * add methods for getting directories instead of hardcoding .svelte-kit etc * fix lockfile * update cloudflare adapters * update readmes * tidy up * tweak docs * remove sandbox from workspace * try pinning version * Update packages/kit/src/core/build/build_server.js Co-authored-by: Ben McCann <[email protected]> * remove redundant strict fs stuff * remove sandbox from gitignore * lint * fix cloudflare pages handling of prerendered pages * support esm and cjs manifests * force createEntries to follow prerender * fix types * fix adapter-netlify * separate App from InternalApp * Update packages/kit/types/internal.d.ts Co-authored-by: Ben McCann <[email protected]> * expose SSRManifest * fall back to HTTP fetch if endpoint is missing * app.render should not be passed a host string * default hostHeader to host in config * fix types * replace page.host with page.origin * fix host stuff * make SSR route splitting optional * simplify createEntries * these are no longer generic * implement .json heuristic * lint * changesets * changeset * Update packages/adapter-netlify/index.js Co-authored-by: Ben McCann <[email protected]> * Update packages/adapter-node/README.md Co-authored-by: Ben McCann <[email protected]> * this.server -> this.vite * give a bare-bones description of createEntries * lint * add missing origin * remove TODO * replace ts-ignore with ts-expect-error * Update packages/kit/src/core/adapt/builder.js Co-authored-by: Ben McCann <[email protected]> * document AdapterEntry * Update packages/kit/types/config.d.ts Co-authored-by: Ben McCann <[email protected]> * oops * manifest -> vite_manifest Co-authored-by: Ben McCann <[email protected]> Co-authored-by: Rich Harris <[email protected]>
1 parent 588aaaf commit ecb423b

File tree

110 files changed

+2345
-1761
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

110 files changed

+2345
-1761
lines changed

.changeset/clean-camels-pump.md

+12
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
'@sveltejs/adapter-auto': patch
3+
'@sveltejs/adapter-cloudflare': patch
4+
'@sveltejs/adapter-cloudflare-workers': patch
5+
'@sveltejs/adapter-netlify': patch
6+
'@sveltejs/adapter-node': patch
7+
'@sveltejs/adapter-static': patch
8+
'@sveltejs/adapter-vercel': patch
9+
'@sveltejs/kit': patch
10+
---
11+
12+
Overhaul adapter API

.changeset/early-snakes-peel.md

+7
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
---
2+
'@sveltejs/adapter-cloudflare': patch
3+
'@sveltejs/adapter-cloudflare-workers': patch
4+
'@sveltejs/adapter-vercel': patch
5+
---
6+
7+
Remove esbuild options

.changeset/fresh-years-do.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
Replace config.kit.hostHeader with config.kit.headers.host, add config.kit.headers.protocol

.changeset/fuzzy-forks-worry.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/kit': patch
3+
---
4+
5+
Replace page.host with page.origin

.changeset/smart-deers-approve.md

+5
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
'@sveltejs/adapter-netlify': patch
3+
---
4+
5+
Add experimental function splitting

.changeset/tiny-singers-allow.md

+6
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
---
2+
'@sveltejs/adapter-netlify': patch
3+
'@sveltejs/adapter-node': patch
4+
---
5+
6+
Don't bundle final output

.github/workflows/ci.yml

+3-3
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@ jobs:
1616
- uses: actions/checkout@v2
1717
- uses: pnpm/[email protected]
1818
with:
19-
version: 6
19+
version: 6.23.2
2020
- uses: actions/setup-node@v2
2121
with:
2222
node-version: '14.x'
@@ -41,7 +41,7 @@ jobs:
4141
- uses: actions/checkout@v2
4242
- uses: pnpm/[email protected]
4343
with:
44-
version: 6
44+
version: 6.23.2
4545
- uses: actions/setup-node@v2
4646
with:
4747
node-version: ${{ matrix.node-version }}
@@ -75,7 +75,7 @@ jobs:
7575
- uses: actions/checkout@v2
7676
- uses: pnpm/[email protected]
7777
with:
78-
version: 6
78+
version: 6.23.2
7979
- uses: actions/setup-node@v2
8080
with:
8181
node-version: ${{ matrix.node-version }}

.github/workflows/release.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ jobs:
1919
fetch-depth: 0
2020
- uses: pnpm/[email protected]
2121
with:
22-
version: 6
22+
version: 6.23.2
2323
- name: Setup Node.js 12.x
2424
uses: actions/setup-node@v2
2525
with:

documentation/docs/01-routing.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,6 @@ type RequestHeaders = Record<string, string>;
5959
export type RawBody = null | Uint8Array;
6060
export interface IncomingRequest {
6161
method: string;
62-
host: string;
6362
path: string;
6463
query: URLSearchParams;
6564
headers: RequestHeaders;
@@ -72,6 +71,7 @@ type ParameterizedBody<Body = unknown> = Body extends FormData
7271
// ServerRequest is exported as Request
7372
export interface ServerRequest<Locals = Record<string, any>, Body = unknown>
7473
extends IncomingRequest {
74+
origin: string;
7575
params: Record<string, string>;
7676
body: ParameterizedBody<Body>;
7777
locals: Locals; // populated by hooks handle
@@ -96,7 +96,7 @@ export interface RequestHandler<
9696
}
9797
```
9898

99-
For example, our hypothetical blog page, `/blog/cool-article`, might request data from `/blog/cool-article.json`, which could be represented by a `src/routes/blog/[slug].json.js` endpoint:
99+
For example, our hypothetical blog page, `/blog/cool-article`, might request data from `/blog/cool-article.json`, which could be represented by a `src/routes/blog/[slug].json.js` endpoint:
100100

101101
```js
102102
import db from '$lib/database';

documentation/docs/03-loading.md

+3-3
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ export interface LoadInput<
1414
Session = any
1515
> {
1616
page: {
17-
host: string;
17+
origin: string;
1818
path: string;
1919
params: PageParams;
2020
query: URLSearchParams;
@@ -92,11 +92,11 @@ The `load` function receives an object containing four fields — `page`, `fetch
9292

9393
#### page
9494

95-
`page` is a `{ host, path, params, query }` object where `host` is the URL's host, `path` is its pathname, `params` is derived from `path` and the route filename, and `query` is an instance of [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams). Mutating `page` does not update the current URL; you should instead navigate using [`goto`](#modules-$app-navigation).
95+
`page` is an `{ origin, path, params, query }` object where `origin` is the URL's origin, `path` is its pathname, `params` is derived from `path` and the route filename, and `query` is an instance of [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams). Mutating `page` does not update the current URL; you should instead navigate using [`goto`](#modules-$app-navigation).
9696

9797
So if the example above was `src/routes/blog/[slug].svelte` and the URL was `https://example.com/blog/some-post?foo=bar&baz&bizz=a&bizz=b`, the following would be true:
9898

99-
- `page.host === 'example.com'`
99+
- `page.origin === 'https://example.com'`
100100
- `page.path === '/blog/some-post'`
101101
- `page.params.slug === 'some-post'`
102102
- `page.query.get('foo') === 'bar'`

documentation/docs/04-hooks.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,6 @@ type RequestHeaders = Record<string, string>;
2626
export type RawBody = null | Uint8Array;
2727
export interface IncomingRequest {
2828
method: string;
29-
host: string;
3029
path: string;
3130
query: URLSearchParams;
3231
headers: RequestHeaders;
@@ -39,6 +38,7 @@ type ParameterizedBody<Body = unknown> = Body extends FormData
3938
// ServerRequest is exported as Request
4039
export interface ServerRequest<Locals = Record<string, any>, Body = unknown>
4140
extends IncomingRequest {
41+
origin: string;
4242
params: Record<string, string>;
4343
body: ParameterizedBody<Body>;
4444
locals: Locals; // populated by hooks handle

documentation/docs/05-modules.md

+5-5
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ Because of that, the stores are not free-floating objects: they must be accessed
5757
The stores themselves attach to the correct context at the point of subscription, which means you can import and use them directly in components without boilerplate. However, it still needs to be called synchronously on component or page initialisation when `$`-prefix isn't used. Use `getStores` to safely `.subscribe` asynchronously instead.
5858

5959
- `navigating` is a [readable store](https://svelte.dev/tutorial/readable-stores). When navigating starts, its value is `{ from, to }`, where `from` and `to` both mirror the `page` store value. When navigating finishes, its value reverts to `null`.
60-
- `page` is a readable store whose value reflects the object passed to `load` functions — it contains `host`, `path`, `params` and `query`. See the [`page` section](#loading-input-page) above for more details.
60+
- `page` is a readable store whose value reflects the object passed to `load` functions — it contains `origin`, `path`, `params` and `query`. See the [`page` section](#loading-input-page) above for more details.
6161
- `session` is a [writable store](https://svelte.dev/tutorial/writable-stores) whose initial value is whatever was returned from [`getSession`](#hooks-getsession). It can be written to, but this will _not_ cause changes to persist on the server — this is something you must implement yourself.
6262

6363
### $lib
@@ -84,12 +84,12 @@ This module provides a helper function to sequence multiple `handle` calls.
8484
import { sequence } from '@sveltejs/kit/hooks';
8585

8686
async function first({ request, resolve }) {
87-
console.log('first');
88-
return await resolve(request);
87+
console.log('first');
88+
return await resolve(request);
8989
}
9090
async function second({ request, resolve }) {
91-
console.log('second');
92-
return await resolve(request);
91+
console.log('second');
92+
return await resolve(request);
9393
}
9494

9595
export const handle = sequence(first, second);

documentation/docs/10-adapters.md

+6-6
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@ export default function (options) {
7676
/** @type {import('@sveltejs/kit').Adapter} */
7777
return {
7878
name: 'adapter-package-name',
79-
async adapt({ utils, config }) {
79+
async adapt(builder) {
8080
// adapter implementation
8181
}
8282
};
@@ -88,15 +88,15 @@ The types for `Adapter` and its parameters are available in [types/config.d.ts](
8888
Within the `adapt` method, there are a number of things that an adapter should do:
8989

9090
- Clear out the build directory
91+
- Call `builder.prerender({ dest })` to prerender pages
9192
- Output code that:
92-
- Imports `init` and `render` from `.svelte-kit/output/server/app.js`
93-
- Calls `init`, which configures the app
93+
- Imports `App` from `${builder.getServerDirectory()}/app.js`
94+
- Instantiates the app with a manifest generated with `builder.generateManifest({ relativePath })`
9495
- Listens for requests from the platform, converts them to a a [SvelteKit request](#hooks-handle), calls the `render` function to generate a [SvelteKit response](#hooks-handle) and responds with it
9596
- Globally shims `fetch` to work on the target platform, if necessary. SvelteKit provides a `@sveltejs/kit/install-fetch` helper for platforms that can use `node-fetch`
96-
- Bundle the output to avoid needing to install dependencies on the target platform, if desired
97-
- Call `utils.prerender`
97+
- Bundle the output to avoid needing to install dependencies on the target platform, if necessary
9898
- Put the user's static files and the generated JS/CSS in the correct location for the target platform
9999

100-
If possible, we recommend putting the adapter output under the `build/` directory with any intermediate output placed under `.svelte-kit/[adapter-name]`.
100+
Where possible, we recommend putting the adapter output under the `build/` directory with any intermediate output placed under `.svelte-kit/[adapter-name]`.
101101

102102
> The adapter API may change before 1.0.

documentation/docs/14-configuration.md

+20-7
Original file line numberDiff line numberDiff line change
@@ -26,8 +26,11 @@ const config = {
2626
template: 'src/app.html'
2727
},
2828
floc: false,
29+
headers: {
30+
host: null,
31+
protocol: null
32+
},
2933
host: null,
30-
hostHeader: null,
3134
hydrate: true,
3235
package: {
3336
dir: 'package',
@@ -47,6 +50,7 @@ const config = {
4750
entries: ['*'],
4851
onError: 'fail'
4952
},
53+
protocol: null,
5054
router: true,
5155
serviceWorker: {
5256
register: true,
@@ -103,25 +107,30 @@ Permissions-Policy: interest-cohort=()
103107

104108
> This only applies to server-rendered responses — headers for prerendered pages (e.g. created with [adapter-static](https://github.com/sveltejs/kit/tree/master/packages/adapter-static)) are determined by the hosting platform.
105109
106-
### host
107-
108-
A value that overrides the `Host` header when populating `page.host`
110+
### headers
109111

110-
### hostHeader
112+
The [`page.origin`] property is derived from the request protocol (normally `https`) and the host, which is taken from the `Host` header by default.
111113

112-
If your app is behind a reverse proxy (think load balancers and CDNs) then the `Host` header will be incorrect. In most cases, the underlying host is exposed via the [`X-Forwarded-Host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) header and you should specify this in your config if you need to access `page.host`:
114+
If your app is behind a reverse proxy (think load balancers and CDNs) then the `Host` header will be incorrect. In most cases, the underlying protocol and host are exposed via the [`X-Forwarded-Host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) and [`X-Forwarded-Proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) headers, which can be specified in your config:
113115

114116
```js
115117
// svelte.config.js
116118
export default {
117119
kit: {
118-
hostHeader: 'X-Forwarded-Host'
120+
headers: {
121+
host: 'X-Forwarded-Host',
122+
protocol: 'X-Forwarded-Proto'
123+
}
119124
}
120125
};
121126
```
122127

123128
**You should only do this if you trust the reverse proxy**, which is why it isn't the default.
124129

130+
### host
131+
132+
A value that overrides the one derived from [`config.kit.headers.host`](#configuration-headers-host).
133+
125134
### hydrate
126135

127136
Whether to [hydrate](#ssr-and-javascript-hydrate) the server-rendered HTML with a client-side app. (It's rare that you would set this to `false` on an app-wide basis.)
@@ -194,6 +203,10 @@ See [Prerendering](#ssr-and-javascript-prerender). An object containing zero or
194203
};
195204
```
196205

206+
### protocol
207+
208+
The protocol is assumed to be `'https'` (unless you're developing locally without the `--https` flag) unless [`config.kit.headers.protocol`](#configuration-headers-protocol) is set. If necessary, you can override it here.
209+
197210
### router
198211

199212
Enables or disables the client-side [router](#ssr-and-javascript-router) app-wide.

packages/adapter-auto/index.js

+4-6
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,10 @@ export default function () {
55
return {
66
name: '@sveltejs/adapter-auto',
77

8-
async adapt(options) {
8+
async adapt(builder) {
99
for (const candidate of adapters) {
1010
if (candidate.test()) {
11-
options.utils.log.info(
12-
`Detected environment: ${candidate.name}. Using ${candidate.module}`
13-
);
11+
builder.log.info(`Detected environment: ${candidate.name}. Using ${candidate.module}`);
1412

1513
let module;
1614

@@ -30,11 +28,11 @@ export default function () {
3028
}
3129

3230
const adapter = module.default();
33-
return adapter.adapt(options);
31+
return adapter.adapt(builder);
3432
}
3533
}
3634

37-
options.utils.log.warn(
35+
builder.log.warn(
3836
'Could not detect a supported production environment. See https://kit.svelte.dev/docs#adapters to learn how to configure your app to run on the platform of your choosing'
3937
);
4038
}

packages/adapter-cloudflare-workers/README.md

-33
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,6 @@
22

33
SvelteKit adapter that creates a Cloudflare Workers site using a function for dynamic server rendering.
44

5-
This is very experimental; the adapter API isn't at all fleshed out, and things will definitely change.
6-
75
_**Comparisons**_
86

97
- `adapter-cloudflare` – supports all SvelteKit features; builds for
@@ -86,37 +84,6 @@ npm run build && wrangler publish
8684

8785
More info on configuring a cloudflare worker site can be found [here](https://developers.cloudflare.com/workers/platform/sites/start-from-existing)
8886

89-
## Advanced Configuration
90-
91-
### esbuild
92-
93-
As an escape hatch, you may optionally specify a function which will receive the final esbuild options generated by this adapter and returns a modified esbuild configuration. The result of this function will be passed as-is to esbuild. The function can be async.
94-
95-
For example, you may wish to add a plugin:
96-
97-
```js
98-
adapterCfw({
99-
esbuild(options) {
100-
return {
101-
...options,
102-
plugins: []
103-
};
104-
}
105-
});
106-
```
107-
108-
The default options for this version are as follows:
109-
110-
```js
111-
const options = {
112-
entryPoints: ['.svelte-kit/cloudflare-workers/entry.js'],
113-
outfile: `${entrypoint}/index.js`,
114-
bundle: true,
115-
target: 'es2020',
116-
platform: 'browser'
117-
};
118-
```
119-
12087
## Changelog
12188

12289
[The Changelog for this package is available on GitHub](https://github.com/sveltejs/kit/blob/master/packages/adapter-cloudflare-workers/CHANGELOG.md).

packages/adapter-cloudflare-workers/files/entry.js

+4-5
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
// TODO hardcoding the relative location makes this brittle
2-
import { init, render } from '../output/server/app.js';
1+
import { App } from 'APP';
2+
import { manifest } from './manifest.js';
33
import { getAssetFromKV, NotFoundError } from '@cloudflare/kv-asset-handler';
44

5-
init();
5+
const app = new App(manifest);
66

77
addEventListener('fetch', (event) => {
88
event.respondWith(handle(event));
@@ -29,8 +29,7 @@ async function handle(event) {
2929
const request_url = new URL(request.url);
3030

3131
try {
32-
const rendered = await render({
33-
host: request_url.host,
32+
const rendered = await app.render({
3433
path: request_url.pathname,
3534
query: request_url.searchParams,
3635
rawBody: await read(request),
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,4 @@
11
import { Adapter } from '@sveltejs/kit';
2-
import { BuildOptions } from 'esbuild';
32

4-
interface AdapterOptions {
5-
esbuild?: (options: BuildOptions) => Promise<BuildOptions> | BuildOptions;
6-
}
7-
8-
declare function plugin(options?: AdapterOptions): Adapter;
3+
declare function plugin(): Adapter;
94
export = plugin;

0 commit comments

Comments
 (0)