diff --git a/.changeset/afraid-schools-scream.md b/.changeset/afraid-schools-scream.md new file mode 100644 index 000000000000..c34528848bae --- /dev/null +++ b/.changeset/afraid-schools-scream.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-cloudflare-workers': patch +--- + +feat: expose `App.Platform` interface automatically diff --git a/.changeset/hungry-singers-tease.md b/.changeset/hungry-singers-tease.md new file mode 100644 index 000000000000..8f4a695af256 --- /dev/null +++ b/.changeset/hungry-singers-tease.md @@ -0,0 +1,11 @@ +--- +'@sveltejs/adapter-auto': patch +'@sveltejs/adapter-cloudflare': patch +'@sveltejs/adapter-cloudflare-workers': patch +'@sveltejs/adapter-netlify': patch +'@sveltejs/adapter-node': patch +'@sveltejs/adapter-static': patch +'@sveltejs/adapter-vercel': patch +--- + +docs: move adapter docs to site diff --git a/.changeset/sixty-rabbits-speak.md b/.changeset/sixty-rabbits-speak.md new file mode 100644 index 000000000000..cebd6640fc94 --- /dev/null +++ b/.changeset/sixty-rabbits-speak.md @@ -0,0 +1,5 @@ +--- +'@sveltejs/adapter-cloudflare-workers': patch +--- + +fix: amend `App.Platform` diff --git a/documentation/docs/20-core-concepts/20-load.md b/documentation/docs/20-core-concepts/20-load.md index ebea67a8420f..3df805300c05 100644 --- a/documentation/docs/20-core-concepts/20-load.md +++ b/documentation/docs/20-core-concepts/20-load.md @@ -192,7 +192,7 @@ Often the `load` function depends on the URL in one way or another. For this, th An instance of [`URL`](https://developer.mozilla.org/en-US/docs/Web/API/URL), containing properties like the `origin`, `hostname`, `pathname` and `searchParams` (which contains the parsed query string as a [`URLSearchParams`](https://developer.mozilla.org/en-US/docs/Web/API/URLSearchParams) object). `url.hash` cannot be accessed during `load`, since it is unavailable on the server. -> In some environments this is derived from request headers during server-side rendering. If you're using [adapter-node](/docs/adapters#supported-environments-node-js), for example, you may need to configure the adapter in order for the URL to be correct. +> In some environments this is derived from request headers during server-side rendering. If you're using [adapter-node](/docs/adapter-node), for example, you may need to configure the adapter in order for the URL to be correct. ### route diff --git a/documentation/docs/20-core-concepts/50-adapters.md b/documentation/docs/20-core-concepts/50-adapters.md deleted file mode 100644 index 9315e47cb709..000000000000 --- a/documentation/docs/20-core-concepts/50-adapters.md +++ /dev/null @@ -1,114 +0,0 @@ ---- -title: Adapters ---- - -Before you can deploy your SvelteKit app, you need to _adapt_ it for your deployment target. Adapters are small plugins that take the built app as input and generate output for deployment. - -By default, projects are configured to use `@sveltejs/adapter-auto`, which detects your production environment and selects the appropriate adapter where possible. If your platform isn't (yet) supported, you may need to [install a custom adapter](/docs/adapters#community-adapters) or [write one](/docs/adapters#writing-custom-adapters). - -> See the [adapter-auto README](https://github.com/sveltejs/kit/tree/master/packages/adapter-auto) for information on adding support for new environments. - -## Supported environments - -SvelteKit offers a number of officially supported adapters. - -You can deploy to the following platforms with the default adapter, `adapter-auto`: - -- [Cloudflare Pages](https://developers.cloudflare.com/pages/) via [`adapter-cloudflare`](https://github.com/sveltejs/kit/tree/master/packages/adapter-cloudflare) -- [Netlify](https://netlify.com) via [`adapter-netlify`](https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify) -- [Vercel](https://vercel.com) via [`adapter-vercel`](https://github.com/sveltejs/kit/tree/master/packages/adapter-vercel) - -### Node.js - -To create a simple Node server, install the [`@sveltejs/adapter-node`](https://github.com/sveltejs/kit/tree/master/packages/adapter-node) package and update your `svelte.config.js`: - -```diff -/// file: svelte.config.js --import adapter from '@sveltejs/adapter-auto'; -+import adapter from '@sveltejs/adapter-node'; -``` - -With this, `vite build` will generate a self-contained Node app inside the `build` directory. You can pass options to adapters, such as customising the output directory: - -```diff -/// file: svelte.config.js -import adapter from '@sveltejs/adapter-node'; - -export default { - kit: { -- adapter: adapter() -+ adapter: adapter({ out: 'my-output-directory' }) - } -}; -``` - -### Static sites - -Most adapters will generate static HTML for any [prerenderable](/docs/page-options#prerender) pages of your site. In some cases, your entire app might be prerenderable, in which case you can use [`@sveltejs/adapter-static`](https://github.com/sveltejs/kit/tree/master/packages/adapter-static) to generate static HTML for _all_ your pages. A fully static site can be hosted on a wide variety of platforms, including static hosts like [GitHub Pages](https://pages.github.com/). - -```diff -/// file: svelte.config.js --import adapter from '@sveltejs/adapter-auto'; -+import adapter from '@sveltejs/adapter-static'; -``` - -You can also use `adapter-static` to generate single-page apps (SPAs) by specifying a [fallback page and disabling SSR](https://github.com/sveltejs/kit/tree/master/packages/adapter-static#spa-mode). - -> You must ensure [`trailingSlash`](/docs/page-options#trailingslash) is set appropriately for your environment. If your host does not render `/a.html` upon receiving a request for `/a` then you will need to set `trailingSlash: 'always'` to create `/a/index.html` instead. - -### Platform-specific context - -Some adapters may have access to additional information about the request. For example, Cloudflare Workers can access an `env` object containing KV namespaces etc. This can be passed to the `RequestEvent` used in [hooks](/docs/hooks) and [server routes](/docs/routing#server) as the `platform` property — consult each adapter's documentation to learn more. - -## Community adapters - -Additional [community-provided adapters](https://sveltesociety.dev/components#adapters) exist for other platforms. After installing the relevant adapter with your package manager, update your `svelte.config.js`: - -```diff -/// file: svelte.config.js --import adapter from '@sveltejs/adapter-auto'; -+import adapter from 'svelte-adapter-[x]'; -``` - -## Writing custom adapters - -We recommend [looking at the source for an adapter](https://github.com/sveltejs/kit/tree/master/packages) to a platform similar to yours and copying it as a starting point. - -Adapters packages must implement the following API, which creates an `Adapter`: - -```js -// @filename: ambient.d.ts -type AdapterSpecificOptions = any; - -// @filename: index.js -// ---cut--- -/** @param {AdapterSpecificOptions} options */ -export default function (options) { - /** @type {import('@sveltejs/kit').Adapter} */ - const adapter = { - name: 'adapter-package-name', - async adapt(builder) { - // adapter implementation - } - }; - - return adapter; -} -``` - -The types for `Adapter` and its parameters are available in [types/index.d.ts](https://github.com/sveltejs/kit/blob/master/packages/kit/types/index.d.ts). - -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`, and `builder.writePrerendered` -- Output code that: - - Imports `Server` from `${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 [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) if necessary, calls the `server.respond(request, { getClientAddress })` function to generate a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) and responds with it - - expose any platform-specific information to SvelteKit via the `platform` option passed to `server.respond` - - 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` -- 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]`. diff --git a/documentation/docs/25-build-and-deploy/10-building-your-app.md b/documentation/docs/25-build-and-deploy/10-building-your-app.md new file mode 100644 index 000000000000..60005f696c27 --- /dev/null +++ b/documentation/docs/25-build-and-deploy/10-building-your-app.md @@ -0,0 +1,30 @@ +--- +title: Building your app +--- + +Building a SvelteKit app happens in two stages, which both happen when you run `vite build` (usually via `npm run build`). + +Firstly, Vite creates an optimized production build of your server code, your browser code, and your service worker (if you have one). [Prerendering](/docs/page-options#prerender) is executed at this stage, if appropriate. + +Secondly, an _adapter_ takes this production build and tunes it for your target environment — more on this on the following pages. + +## During the build + +SvelteKit will load your `+page/layout(.server).js` files (and all files they import) for analysis during the build. Any code that should _not_ be executed at this stage must check that `building` from [`$app/environment`](/docs/modules#$app-environment) is `false`: + +```diff ++import { building } from '$app/environment'; +import { setupMyDatabase } from '$lib/server/database'; + ++if (!building) { + setupMyDatabase(); ++} + +export function load() { + // ... +} +``` + +## Preview your app + +After building, you can view your production build locally with `vite preview` (via `npm run preview`). Note that this will run the app in Node, and so is not a perfect reproduction of your deployed app — adapter-specific adjustments like the [`platform` object](adapters#platform-specific-context) do not apply to previews. diff --git a/documentation/docs/25-build-and-deploy/20-adapters.md b/documentation/docs/25-build-and-deploy/20-adapters.md new file mode 100644 index 000000000000..815cfab708bd --- /dev/null +++ b/documentation/docs/25-build-and-deploy/20-adapters.md @@ -0,0 +1,49 @@ +--- +title: Adapters +--- + +Before you can deploy your SvelteKit app, you need to _adapt_ it for your deployment target. Adapters are small plugins that take the built app as input and generate output for deployment. + +Official adapters exist for a variety of platforms — these are documented on the following pages: + +- [`@sveltejs/adapter-cloudflare`](adapter-cloudflare) for Cloudflare Pages +- [`@sveltejs/adapter-cloudflare-workers`](adapter-cloudflare-workers) for Cloudflare Workers +- [`@sveltejs/adapter-netlify`](adapter-netlify) for Netlify +- [`@sveltejs/adapter-node`](adapter-node) for Node servers +- [`@sveltejs/adapter-static`](adapter-static) for static site generation (SSG) +- [`@sveltejs/adapter-vercel`](adapter-vercel) for Vercel + +Additional [community-provided adapters](https://sveltesociety.dev/components#adapters) exist for other platforms. + +## Using adapters + +Your adapter is specified in `svelte.config.js`: + +```js +/// file: svelte.config.js +// @filename: ambient.d.ts +declare module 'svelte-adapter-foo' { + const adapter: (opts: any) => import('@sveltejs/kit').Adapter; + export default adapter; +} + +// @filename: index.js +// ---cut--- +import adapter from 'svelte-adapter-foo'; + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + adapter: adapter({ + // adapter options go here + }) + } +}; + +export default config; +``` + +## Platform-specific context + +Some adapters may have access to additional information about the request. For example, Cloudflare Workers can access an `env` object containing KV namespaces etc. This can be passed to the `RequestEvent` used in [hooks](/docs/hooks) and [server routes](/docs/routing#server) as the `platform` property — consult each adapter's documentation to learn more. + diff --git a/documentation/docs/25-build-and-deploy/30-adapter-auto.md b/documentation/docs/25-build-and-deploy/30-adapter-auto.md new file mode 100644 index 000000000000..d0719ebafc3d --- /dev/null +++ b/documentation/docs/25-build-and-deploy/30-adapter-auto.md @@ -0,0 +1,20 @@ +--- +title: Zero-config deployments +--- + +When you create a new SvelteKit project with `npm create svelte@latest`, it installs [`adapter-auto`](https://github.com/sveltejs/kit/tree/master/packages/adapter-auto) by default. This adapter automatically installs and uses the correct adapter for supported environments when you deploy: + +- [`@sveltejs/adapter-cloudflare`](adapter-cloudflare) for [Cloudflare Pages](https://developers.cloudflare.com/pages/) +- [`@sveltejs/adapter-netlify`](adapter-netlify) for [Netlify](https://netlify.com/) +- [`@sveltejs/adapter-vercel`](adapter-vercel) for [Vercel](https://vercel.com/) +- [`svelte-adapter-azure-swa`](https://github.com/geoffrich/svelte-adapter-azure-swa) for [Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/) + +It's recommended to install the appropriate adapter to your `devDependencies` once you've settled on a target environment, since this will add the adapter to your lockfile and slightly improve install times on CI. + +## Environment-specific configuration + +To add configuration options, such as `{ edge: true }` in [`adapter-vercel`](adapter-vercel) and [`adapter-netlify`](adapter-netlify), you must install the underlying adapter — `adapter-auto` does not take any options. + +## Adding community adapters + +You can add zero-config support for additional adapters by editing [adapters.js](https://github.com/sveltejs/kit/blob/master/packages/adapter-auto/adapters.js) and opening a pull request. \ No newline at end of file diff --git a/documentation/docs/25-build-and-deploy/40-adapter-node.md b/documentation/docs/25-build-and-deploy/40-adapter-node.md new file mode 100644 index 000000000000..8ca23baa73f1 --- /dev/null +++ b/documentation/docs/25-build-and-deploy/40-adapter-node.md @@ -0,0 +1,194 @@ +--- +title: Node servers +--- + +To generate a standalone Node server, use [`adapter-node`](https://github.com/sveltejs/kit/tree/master/packages/adapter-node). + +## Usage + +Install with `npm i -D @sveltejs/adapter-node`, then add the adapter to your `svelte.config.js`: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-node'; + +export default { + kit: { + adapter: adapter() + } +}; +``` + +## Deploying + +You will need the output directory (`build` by default), the project's `package.json`, and the production dependencies in `node_modules` to run the application. Production dependencies can be generated with `npm ci --prod` (you can skip this step if your app doesn't have any dependencies). You can then start your app with this command: + +```bash +node build +``` + +Development dependencies will be bundled into your app using [Rollup](https://rollupjs.org). To control whether a given package is bundled or externalised, place it in `devDependencies` or `dependencies` respectively in your `package.json`. + +## Environment variables + +In `dev` and `preview`, SvelteKit will read environent variables from your `.env` file (or `.env.local`, or `.env.[mode]`, [as determined by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files).) + +In production, `.env` files are _not_ automatically loaded. To do so, install `dotenv` in your project... + +```bash +npm install dotenv +``` + +...and invoke it before running the built app: + +```diff +-node build ++node -r dotenv/config build +``` + +### `PORT` and `HOST` + +By default, the server will accept connections on `0.0.0.0` using port 3000. These can be customised with the `PORT` and `HOST` environment variables: + +``` +HOST=127.0.0.1 PORT=4000 node build +``` + +### `ORIGIN`, `PROTOCOL_HEADER` and `HOST_HEADER` + +HTTP doesn't give SvelteKit a reliable way to know the URL that is currently being requested. The simplest way to tell SvelteKit where the app is being served is to set the `ORIGIN` environment variable: + +``` +ORIGIN=https://my.site node build +``` + +With this, a request for the `/stuff` pathname will correctly resolve to `https://my.site/stuff`. Alternatively, you can specify headers that tell SvelteKit about the request protocol and host, from which it can construct the origin URL: + +``` +PROTOCOL_HEADER=x-forwarded-proto HOST_HEADER=x-forwarded-host node build +``` + +> [`x-forwarded-proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) and [`x-forwarded-host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) are de facto standard headers that forward the original protocol and host if you're using a reverse proxy (think load balancers and CDNs). You should only set these variables if your server is behind a trusted reverse proxy; otherwise, it'd be possible for clients to spoof these headers. + +If `adapter-node` can't correctly determine the URL of your deployment, you may experience this error when using [form actions](/docs/form-actions): + +> Cross-site POST form submissions are forbidden + +### `ADDRESS_HEADER` and `XFF_DEPTH` + +The [RequestEvent](/docs/types#public-types-requestevent) object passed to hooks and endpoints includes an `event.getClientAddress()` function that returns the client's IP address. By default this is the connecting `remoteAddress`. If your server is behind one or more proxies (such as a load balancer), this value will contain the innermost proxy's IP address rather than the client's, so we need to specify an `ADDRESS_HEADER` to read the address from: + +``` +ADDRESS_HEADER=True-Client-IP node build +``` + +> Headers can easily be spoofed. As with `PROTOCOL_HEADER` and `HOST_HEADER`, you should [know what you're doing](https://adam-p.ca/blog/2022/03/x-forwarded-for/) before setting these. + +If the `ADDRESS_HEADER` is `X-Forwarded-For`, the header value will contain a comma-separated list of IP addresses. The `XFF_DEPTH` environment variable should specify how many trusted proxies sit in front of your server. E.g. if there are three trusted proxies, proxy 3 will forward the addresses of the original connection and the first two proxies: + +``` +, , +``` + +Some guides will tell you to read the left-most address, but this leaves you [vulnerable to spoofing](https://adam-p.ca/blog/2022/03/x-forwarded-for/): + +``` +, , , +``` + +We instead read from the _right_, accounting for the number of trusted proxies. In this case, we would use `XFF_DEPTH=3`. + +> If you need to read the left-most address instead (and don't care about spoofing) — for example, to offer a geolocation service, where it's more important for the IP address to be _real_ than _trusted_, you can do so by inspecting the `x-forwarded-for` header within your app. + +### `BODY_SIZE_LIMIT` + +The maximum request body size to accept in bytes including while streaming. Defaults to 512kb. You can disable this option with a value of 0 and implement a custom check in [`handle`](/docs/hooks#server-hooks-handle) if you need something more advanced. + +## Options + +The adapter can be configured with various options: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-node'; + +export default { + kit: { + adapter: adapter({ + // default options are shown + out: 'build', + precompress: false, + envPrefix: '' + }) + } +}; +``` + +### out + +The directory to build the server to. It defaults to `build` — i.e. `node build` would start the server locally after it has been created. + +### precompress + +Enables precompressing using gzip and brotli for assets and prerendered pages. It defaults to `false`. + +### envPrefix + +If you need to change the name of the environment variables used to configure the deployment (for example, to deconflict with environment variables you don't control), you can specify a prefix: + +```js +envPrefix: 'MY_CUSTOM_'; +``` + +``` +MY_CUSTOM_HOST=127.0.0.1 \ +MY_CUSTOM_PORT=4000 \ +MY_CUSTOM_ORIGIN=https://my.site \ +node build +``` + +## Custom server + +The adapter creates two files in your build directory — `index.js` and `handler.js`. Running `index.js` — e.g. `node build`, if you use the default build directory — will start a server on the configured port. + +Alternatively, you can import the `handler.js` file, which exports a handler suitable for use with [Express](https://github.com/expressjs/expressjs.com), [Connect](https://github.com/senchalabs/connect) or [Polka](https://github.com/lukeed/polka) (or even just the built-in [`http.createServer`](https://nodejs.org/dist/latest/docs/api/http.html#httpcreateserveroptions-requestlistener)) and set up your own server: + +```js +// @errors: 2307 7006 +/// file: my-server.js +import { handler } from './build/handler.js'; +import express from 'express'; + +const app = express(); + +// add a route that lives separately from the SvelteKit app +app.get('/healthcheck', (req, res) => { + res.end('ok'); +}); + +// let SvelteKit handle everything else, including serving prerendered pages and static assets +app.use(handler); + +app.listen(3000, () => { + console.log('listening on port 3000'); +}); +``` + +## Troubleshooting + +### Is there a hook for cleaning up before the server exits? + +There's nothing built-in to SvelteKit for this, because such a cleanup hook depends highly on the execution environment you're on. For Node, you can use its built-in `process.on(..)` to implement a callback that runs before the server exits: + +```js +// @errors: 2304 2580 +function shutdownGracefully() { + // anything you need to clean up manually goes in here + db.shutdown(); +} + +process.on('SIGINT', shutdownGracefully); +process.on('SIGTERM', shutdownGracefully); +``` \ No newline at end of file diff --git a/documentation/docs/25-build-and-deploy/50-adapter-static.md b/documentation/docs/25-build-and-deploy/50-adapter-static.md new file mode 100644 index 000000000000..cd2ce0566712 --- /dev/null +++ b/documentation/docs/25-build-and-deploy/50-adapter-static.md @@ -0,0 +1,186 @@ +--- +title: Static site generation +--- + +To use SvelteKit as a static site generator (SSG), use [`adapter-static`](https://github.com/sveltejs/kit/tree/master/packages/adapter-static). + +This will prerender your entire site as a collection of static files. If you'd like to prerender only some pages, you will need to use a different adapter together with [the `prerender` option](/docs/page-options#prerender). + +## Usage + +Install with `npm i -D @sveltejs/adapter-static`, then add the adapter to your `svelte.config.js`: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-static'; + +export default { + kit: { + adapter: adapter({ + // default options are shown. On some platforms + // these options are set automatically — see below + pages: 'build', + assets: 'build', + fallback: null, + precompress: false, + strict: true + }) + } +}; +``` + +...and add the [`prerender`](/docs/page-options#prerender) option to your root layout: + +```js +/// file: src/routes/+layout.js +// This can be false if you're using a fallback (i.e. SPA mode) +export const prerender = true; +``` + +> You must ensure SvelteKit's [`trailingSlash`](/docs/page-options#trailingslash) option is set appropriately for your environment. If your host does not render `/a.html` upon receiving a request for `/a` then you will need to set `trailingSlash: 'always'` to create `/a/index.html` instead. + +## Zero-config support + +Some platforms have zero-config support (more to come in future): + +- [Vercel](https://vercel.com) + +On these platforms, you should omit the adapter options so that `adapter-static` can provide the optimal configuration: + +```diff +/// file: svelte.config.js +export default { + kit: { +- adapter: adapter({...}), ++ adapter: adapter(), + } + } +}; +``` + +## Options + +### pages + +The directory to write prerendered pages to. It defaults to `build`. + +### assets + +The directory to write static assets (the contents of `static`, plus client-side JS and CSS generated by SvelteKit) to. Ordinarily this should be the same as `pages`, and it will default to whatever the value of `pages` is, but in rare circumstances you might need to output pages and assets to separate locations. + +### fallback + +Specify a fallback page for SPA mode, e.g. `index.html` or `200.html` or `404.html`. + +### precompress + +If `true`, precompresses files with brotli and gzip. This will generate `.br` and `.gz` files. + +### strict + +By default, `adapter-static` checks that either all pages and endpoints (if any) of your app were prerendered, or you have the `fallback` option set. This check exists to prevent you from accidentally publishing an app where some parts of it are not accessible, because they are not contained in the final output. If you know this is ok (for example when a certain page only exists conditionally), you can set `strict` to `false` to turn off this check. + +## SPA mode + +You can use `adapter-static` to create a single-page app or SPA by specifying a **fallback page**. + +> In most situations this is not recommended: it harms SEO, tends to slow down perceived performance, and makes your app inaccessible to users if JavaScript fails or is disabled (which happens [more often than you probably think](https://kryogenix.org/code/browser/everyonehasjs.html)). + +If you want to create a simple SPA with no prerendered routes, the necessary config looks like this: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-static'; + +export default { + kit: { + adapter: adapter({ + fallback: '200.html' + }), + prerender: { entries: [] } + } +}; +``` + +```js +/// file: src/routes/+layout.js +export const ssr = false; +``` + +You can also turn only part of your app into an SPA. + +Let's go through these options one by one: + +### Add fallback page + +The fallback page is an HTML page created by SvelteKit that loads your app and navigates to the correct route. For example [Surge](https://surge.sh/help/adding-a-200-page-for-client-side-routing), a static web host, lets you add a `200.html` file that will handle any requests that don't correspond to static assets or prerendered pages. We can create that file like so: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-static'; + +export default { + kit: { + adapter: adapter({ + fallback: '200.html' + }) + } +}; +``` + +> How to configure this behaviour does however depend on your hosting solution and is not part of SvelteKit. It is recommended to search the host's documentation on how to redirect requests. + +### Turn off prerendering + +When operating in SPA mode, you can omit the [`prerender`](/docs/page-options#prerender) option from your root layout (or set it to `false`, its default value), and only pages that have the `prerender` option set will be prerendered at build time. + +SvelteKit will still crawl your app's entry points looking for prerenderable pages. If `svelte-kit build` fails because of pages that can't be loaded outside the browser, you can set `config.kit.prerender.entries` to `[]` to prevent this from happening. (Setting `config.kit.prerender.enabled` to `false` also has this effect, but would prevent the fallback page from being generated.) + +You can also add turn off prerendering only to parts of your app, if you want other parts to be prerendered. + +### Turn off ssr + +During development, SvelteKit will still attempt to server-side render your routes. This means accessing things that are only available in the browser (such as the `window` object) will result in errors, even though this would be valid in the output app. To align the behavior of SvelteKit's dev mode with your SPA, you can [add `export const ssr = false` to your root `+layout`](/docs/page-options#ssr). You can also add this option only to parts of your app, if you want other parts to be prerendered. + +### Apache + +To run an SPA on [Apache](https://httpd.apache.org/), you should add a `static/.htaccess` file to route requests to the fallback page: + +``` + + RewriteEngine On + RewriteBase / + RewriteRule ^200\.html$ - [L] + RewriteCond %{REQUEST_FILENAME} !-f + RewriteCond %{REQUEST_FILENAME} !-d + RewriteRule . /200.html [L] + +``` + +## GitHub Pages + +When building for GitHub Pages, make sure to update [`paths.base`](/docs/configuration#paths) to match your repo name, since the site will be served from rather than from the root. + +You will have to prevent GitHub's provided Jekyll from managing your site by putting an empty `.nojekyll` file in your static folder. If you do not want to disable Jekyll, change the kit's `appDir` configuration option to `'app_'` or anything not starting with an underscore. For more information, see GitHub's [Jekyll documentation](https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll#configuring-jekyll-in-your-github-pages-site). + +A config for GitHub Pages might look like the following: + +```js +/// file: svelte.config.js +const dev = process.argv.includes('dev'); + +/** @type {import('@sveltejs/kit').Config} */ +const config = { + kit: { + paths: { + base: dev ? '' : '/your-repo-name', + }, + // If you are not using a .nojekyll file, change your appDir to something not starting with an underscore. + // For example, instead of '_app', use 'app_', 'internal', etc. + appDir: 'internal', + } +}; +``` diff --git a/documentation/docs/25-build-and-deploy/60-adapter-cloudflare.md b/documentation/docs/25-build-and-deploy/60-adapter-cloudflare.md new file mode 100644 index 000000000000..c3c9d5b451fa --- /dev/null +++ b/documentation/docs/25-build-and-deploy/60-adapter-cloudflare.md @@ -0,0 +1,86 @@ +--- +title: Cloudflare Pages +--- + +To deploy to [Cloudflare Pages](https://developers.cloudflare.com/pages/), use [`adapter-cloudflare`](https://github.com/sveltejs/kit/tree/master/packages/adapter-cloudflare). + +This adapter will be installed by default when you use [`adapter-auto`](/docs/adapter-auto), but adding it to your project is recommended so that `event.platform` is automatically typed. + +## Comparisons + +- `adapter-cloudflare` – supports all SvelteKit features; builds for [Cloudflare Pages](https://blog.cloudflare.com/cloudflare-pages-goes-full-stack/) +- `adapter-cloudflare-workers` – supports all SvelteKit features; builds for Cloudflare Workers +- `adapter-static` – only produces client-side static assets; compatible with Cloudflare Pages + +> Unless you have a specific reason to use `adapter-cloudflare-workers`, it's recommended that you use this adapter instead. Both adapters have equivalent functionality, but Cloudflare Pages offers features like GitHub integration with automatic builds and deploys, preview deployments, instant rollback and so on. + +## Usage + +Install with `npm i -D @sveltejs/adapter-cloudflare`, then add the adapter to your `svelte.config.js`: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-cloudflare'; + +export default { + kit: { + adapter: adapter() + } +}; +``` + +## Deployment + +Please follow the [Get Started Guide](https://developers.cloudflare.com/pages/get-started) for Cloudflare Pages to begin. + +When configuring your project settings, you must use the following settings: + +- **Framework preset** – None +- **Build command** – `npm run build` or `svelte-kit build` +- **Build output directory** – `.svelte-kit/cloudflare` +- **Environment variables** + - `NODE_VERSION`: `16` + +> You need to add a `NODE_VERSION` environment variable to both the "production" and "preview" environments. You can add this during project setup or later in the Pages project settings. SvelteKit requires Node `16.14` or later, so you should use `16` as the `NODE_VERSION` value. + +## Environment variables + +The [`env`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#parameters) object, containing KV/DO namespaces etc, is passed to SvelteKit via the `platform` property along with `context` and `caches`, meaning you can access it in hooks and endpoints: + +```js +// @errors: 7031 +export async function POST({ request, platform }) { + const x = platform.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x'); +} +``` + +To make these types available to your app, reference them in your `src/app.d.ts`: + +```diff +/// file: src/app.d.ts +declare namespace App { + interface Platform { ++ env?: { ++ YOUR_KV_NAMESPACE: KVNamespace; ++ YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace; ++ }; + } +} +``` + +> `platform.env` is only available in the production build. Use [wrangler](https://developers.cloudflare.com/workers/cli-wrangler) to test it locally + +## Notes + +Functions contained in the `/functions` directory at the project's root will _not_ be included in the deployment, which is compiled to a [single `_worker.js` file](https://developers.cloudflare.com/pages/platform/functions/#advanced-mode). Functions should be implemented as [server endpoints](https://kit.svelte.dev/docs/routing#server) in your SvelteKit app. + +The `_headers` and `_redirects` files specific to Cloudflare Pages can be used for static asset responses (like images) by putting them into the `/static` folder. + +However, they will have no effect on responses dynamically rendered by SvelteKit, which should return custom headers or redirect responses from [server endpoints](https://kit.svelte.dev/docs/routing#server) or with the [`handle`](https://kit.svelte.dev/docs/hooks#server-hooks-handle) hook. + +## Troubleshooting + +### Accessing the file system + +You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. diff --git a/documentation/docs/25-build-and-deploy/70-adapter-cloudflare-workers.md b/documentation/docs/25-build-and-deploy/70-adapter-cloudflare-workers.md new file mode 100644 index 000000000000..ad3ada052f78 --- /dev/null +++ b/documentation/docs/25-build-and-deploy/70-adapter-cloudflare-workers.md @@ -0,0 +1,113 @@ +--- +title: Cloudflare Workers +--- + +To deploy to [Cloudflare Workers](https://workers.cloudflare.com/), use [`adapter-cloudflare-workers`](https://github.com/sveltejs/kit/tree/master/packages/adapter-cloudflare-workers). + +Unless you have a specific reason to use this adapter, we recommend using [`adapter-cloudflare`](adapter-cloudflare) instead. + +> Requires [Wrangler v2](https://developers.cloudflare.com/workers/wrangler/get-started/). + +## Usage + +Install with `npm i -D @sveltejs/adapter-cloudflare-workers`, then add the adapter to your `svelte.config.js`: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-cloudflare-workers'; + +export default { + kit: { + adapter: adapter() + } +}; +``` + +## Basic Configuration + +This adapter expects to find a [wrangler.toml](https://developers.cloudflare.com/workers/platform/sites/configuration) file in the project root. It should look something like this: + +```toml +/// file: wrangler.toml +name = "" +account_id = "" + +main = "./.cloudflare/worker.js" +site.bucket = "./.cloudflare/public" + +build.command = "npm run build" + +compatibility_date = "2021-11-12" +workers_dev = true +``` + +`` can be anything. `` can be found by logging into your [Cloudflare dashboard](https://dash.cloudflare.com) and grabbing it from the end of the URL: + +``` +https://dash.cloudflare.com/ +``` + +> You should add the `.cloudflare` directory (or whichever directories you specified for `main` and `site.bucket`) to your `.gitignore`. + +You will need to install [wrangler](https://developers.cloudflare.com/workers/wrangler/get-started/) and log in, if you haven't already: + +``` +npm i -g wrangler +wrangler login +``` + +Then, you can build your app and deploy it: + +```sh +wrangler publish +``` + +## Custom config + +If you would like to use a config file other than `wrangler.toml`, you can do like so: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-cloudflare-workers'; + +export default { + kit: { + adapter: adapter({ config: '.toml' }) + } +}; +``` + +## Environment variables + +The [`env`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#parameters) object, containing KV/DO namespaces etc, is passed to SvelteKit via the `platform` property along with `context` and `caches`, meaning you can access it in hooks and endpoints: + +```js +// @errors: 7031 +export async function POST({ request, platform }) { + const x = platform.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x'); +} +``` + +To make these types available to your app, reference them in your `src/app.d.ts`: + +```diff +/// file: src/app.d.ts +declare namespace App { + interface Platform { ++ env?: { ++ YOUR_KV_NAMESPACE: KVNamespace; ++ YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace; ++ }; + } +} +``` + +> `platform.env` is only available in the production build. Use [wrangler](https://developers.cloudflare.com/workers/cli-wrangler) to test it locally + +## Troubleshooting + +### Accessing the file system + +You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. \ No newline at end of file diff --git a/documentation/docs/25-build-and-deploy/80-adapter-netlify.md b/documentation/docs/25-build-and-deploy/80-adapter-netlify.md new file mode 100644 index 000000000000..553f38b8e878 --- /dev/null +++ b/documentation/docs/25-build-and-deploy/80-adapter-netlify.md @@ -0,0 +1,114 @@ +--- +title: Netlify +--- + +To deploy to Netlify, use [`adapter-netlify`](https://github.com/sveltejs/kit/tree/master/packages/adapter-netlify). + +This adapter will be installed by default when you use [`adapter-auto`](/docs/adapter-auto), but adding it to your project allows you to specify Netlify-specific options. + +## Usage + +Install with `npm i -D @sveltejs/adapter-netlify`, then add the adapter to your `svelte.config.js`: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-netlify'; + +export default { + kit: { + // default options are shown + adapter: adapter({ + // if true, will create a Netlify Edge Function rather + // than using standard Node-based functions + edge: false, + + // if true, will split your app into multiple functions + // instead of creating a single one for the entire app. + // if `edge` is true, this option cannot be used + split: false + }) + } +}; +``` + +Then, make sure you have a [netlify.toml](https://docs.netlify.com/configure-builds/file-based-configuration) file in the project root. This will determine where to write static assets based on the `build.publish` settings, as per this sample configuration: + +```toml +[build] + command = "npm run build" + publish = "build" +``` + +If the `netlify.toml` file or the `build.publish` value is missing, a default value of `"build"` will be used. Note that if you have set the publish directory in the Netlify UI to something else then you will need to set it in `netlify.toml` too, or use the default value of `"build"`. + +### Node version + +New projects will use Node 16 by default. However, if you're upgrading a project you created a while ago it may be stuck on an older version. See [the Netlify docs](https://docs.netlify.com/configure-builds/manage-dependencies/#node-js-and-javascript) for details on manually specifying Node 16 or newer. + +## Netlify Edge Functions (beta) + +SvelteKit supports the beta release of [Netlify Edge Functions](https://docs.netlify.com/netlify-labs/experimental-features/edge-functions/). If you pass the option `edge: true` to the `adapter` function, server-side rendering will happen in a Deno-based edge function that's deployed close to the site visitor. If set to `false` (the default), the site will deploy to standard Node-based Netlify Functions. + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-netlify'; + +export default { + kit: { + adapter: adapter({ + // will create a Netlify Edge Function using Deno-based + // rather than using standard Node-based functions + edge: true + }) + } +}; +``` + +## Netlify alternatives to SvelteKit functionality + +You may build your app using functionality provided directly by SvelteKit without relying on any Netlify functionality. Using the SvelteKit versions of these features will allow them to be used in dev mode, tested with integration tests, and to work with other adapters should you ever decide to switch away from Netlify. However, in some scenarios you may find it beneficial to use the Netlify versions of these features. One example would be if you're migrating an app that's already hosted on Netlify to SvelteKit. + +### Redirect rules + +During compilation, redirect rules are automatically appended to your `_redirects` file. (If it doesn't exist yet, it will be created.) That means: + +- `[[redirects]]` in `netlify.toml` will never match as `_redirects` has a [higher priority](https://docs.netlify.com/routing/redirects/#rule-processing-order). So always put your rules in the [`_redirects` file](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file). +- `_redirects` shouldn't have any custom "catch all" rules such as `/* /foobar/:splat`. Otherwise the automatically appended rule will never be applied as Netlify is only processing [the first matching rule](https://docs.netlify.com/routing/redirects/#rule-processing-order). + +### Netlify Forms + +1. Create your Netlify HTML form as described [here](https://docs.netlify.com/forms/setup/#html-forms), e.g. as `/routes/contact/+page.svelte`. (Don't forget to add the hidden `form-name` input element!) +2. Netlify's build bot parses your HTML files at deploy time, which means your form must be [prerendered](https://kit.svelte.dev/docs/page-options#prerender) as HTML. You can either add `export const prerender = true` to your `contact.svelte` to prerender just that page or set the `kit.prerender.force: true` option to prerender all pages. +3. If your Netlify form has a [custom success message](https://docs.netlify.com/forms/setup/#success-messages) like `
` then ensure the corresponding `/routes/success/+page.svelte` exists and is prerendered. + +### Netlify Functions + +With this adapter, SvelteKit endpoints are hosted as [Netlify Functions](https://docs.netlify.com/functions/overview/). Netlify function handlers have additional context, including [Netlify Identity](https://docs.netlify.com/visitor-access/identity/) information. You can access this context via the `event.platform.context` field inside your hooks and `+page.server` or `+layout.server` endpoints. These are [serverless functions](https://docs.netlify.com/functions/overview/) when the `edge` property is `false` in the adapter config or [edge functions](https://docs.netlify.com/edge-functions/overview/#app) when it is `true`. + +```js +// @errors: 2705 7006 +/// file: +page.server.js +export const load = async (event) => { + const context = event.platform.context; + console.log(context); // shows up in your functions log in the Netlify app +}; +``` + +Additionally, you can add your own Netlify functions by creating a directory for them and adding the configuration to your `netlify.toml` file. For example: + +```toml +[build] + command = "npm run build" + publish = "build" + +[functions] + directory = "functions" +``` + +## Troubleshooting + +### Accessing the file system + +You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. \ No newline at end of file diff --git a/documentation/docs/25-build-and-deploy/90-adapter-vercel.md b/documentation/docs/25-build-and-deploy/90-adapter-vercel.md new file mode 100644 index 000000000000..81bc7d5954de --- /dev/null +++ b/documentation/docs/25-build-and-deploy/90-adapter-vercel.md @@ -0,0 +1,84 @@ +--- +title: Vercel +--- + +To deploy to Vercel, use [`adapter-vercel`](https://github.com/sveltejs/kit/tree/master/packages/adapter-vercel). + +This adapter will be installed by default when you use [`adapter-auto`](/docs/adapter-auto), but adding it to your project allows you to specify Vercel-specific options. + +## Usage + +Install with `npm i -D @sveltejs/adapter-vercel`, then add the adapter to your `svelte.config.js`: + +```js +// @errors: 2307 +/// file: svelte.config.js +import adapter from '@sveltejs/adapter-vercel'; + +export default { + kit: { + // default options are shown + adapter: adapter({ + // if true, will deploy the app using edge functions + // (https://vercel.com/docs/concepts/functions/edge-functions) + // rather than serverless functions + edge: false, + + // an array of dependencies that esbuild should treat + // as external when bundling functions + external: [], + + // if true, will split your app into multiple functions + // instead of creating a single one for the entire app + split: false + }) + } +}; +``` + +## Environment Variables + +Vercel makes a set of [deployment-specific environment variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) available. Like other environment variables, these are accessible from `$env/static/private` and `$env/dynamic/private` (sometimes — more on that later), and inaccessible from their public counterparts. To access one of these variables from the client: + +```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 + }; +} +``` + +```svelte +/// file: +layout.svelte + + +

This staging environment was deployed from {data.deploymentGitBranch}.

+``` + +Since all of these variables are unchanged between build time and run time when building on Vercel, we recommend using `$env/static/private` — which will statically replace the variables, enabling optimisations like dead code elimination — rather than `$env/dynamic/private`. If you're deploying with `edge: true` you _must_ use `$env/static/private`, as `$env/dynamic/private` and `$env/dynamic/public` are not currently populated in edge functions on Vercel. + +## Notes + +### Vercel functions + +Vercel functions contained in the `/api` directory at the project's root will _not_ be included in the deployment — these should be implemented as [server endpoints](https://kit.svelte.dev/docs/routing#server) in your SvelteKit app. + +### Node version + +Projects created before a certain date will default to using Node 14, while SvelteKit requires Node 16 or later. You can change that in your project settings: + +![Vercel project settings](https://github.com/sveltejs/kit/blob/master/packages/adapter-vercel/settings.png) + +## Troubleshooting + +### Accessing the file system + +You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. \ No newline at end of file diff --git a/documentation/docs/25-build-and-deploy/99-writing-adapters.md b/documentation/docs/25-build-and-deploy/99-writing-adapters.md new file mode 100644 index 000000000000..e496bbad0634 --- /dev/null +++ b/documentation/docs/25-build-and-deploy/99-writing-adapters.md @@ -0,0 +1,44 @@ +--- +title: 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](https://github.com/sveltejs/kit/tree/master/packages) to a platform similar to yours and copying it as a starting point. + +Adapters packages must implement the following API, which creates an `Adapter`: + +```js +// @filename: ambient.d.ts +type AdapterSpecificOptions = any; + +// @filename: index.js +// ---cut--- +/** @param {AdapterSpecificOptions} options */ +export default function (options) { + /** @type {import('@sveltejs/kit').Adapter} */ + const adapter = { + name: 'adapter-package-name', + async adapt(builder) { + // adapter implementation + } + }; + + return adapter; +} +``` + +The types for `Adapter` and its parameters are available in [types/index.d.ts](https://github.com/sveltejs/kit/blob/master/packages/kit/types/index.d.ts). + +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`, and `builder.writePrerendered` +- Output code that: + - Imports `Server` from `${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 [Request](https://developer.mozilla.org/en-US/docs/Web/API/Request) if necessary, calls the `server.respond(request, { getClientAddress })` function to generate a [Response](https://developer.mozilla.org/en-US/docs/Web/API/Response) and responds with it + - expose any platform-specific information to SvelteKit via the `platform` option passed to `server.respond` + - 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` +- 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]`. diff --git a/documentation/docs/25-build-and-deploy/meta.json b/documentation/docs/25-build-and-deploy/meta.json new file mode 100644 index 000000000000..528879bbebda --- /dev/null +++ b/documentation/docs/25-build-and-deploy/meta.json @@ -0,0 +1,3 @@ +{ + "title": "Build and deploy" +} diff --git a/packages/adapter-auto/README.md b/packages/adapter-auto/README.md index 6bc8e45dc025..c0e2ba93474c 100644 --- a/packages/adapter-auto/README.md +++ b/packages/adapter-auto/README.md @@ -1,19 +1,10 @@ # adapter-auto -Automatically chooses the adapter for your current environment, if possible. +Automatically chooses the SvelteKit adapter for your current environment, if possible. -## Supported environments +## Docs -The following environments are supported out-of-the-box, meaning a newly created project can be deployed on one of these platforms without any additional configuration: - -- [Cloudflare Pages](https://developers.cloudflare.com/pages/) via [adapter-cloudflare](../adapter-cloudflare) -- [Netlify](https://netlify.com/) via [adapter-netlify](../adapter-netlify) -- [Vercel](https://vercel.com/) via [adapter-vercel](../adapter-vercel) -- [Azure Static Web Apps](https://docs.microsoft.com/en-us/azure/static-web-apps/) via [svelte-adapter-azure-swa](https://github.com/geoffrich/svelte-adapter-azure-swa) - -## Community adapters - -Support for additional environments can be added in [adapters.js](adapters.js). To avoid this package ballooning in size, community-supported adapters should not be added as dependencies — adapter-auto will instead prompt users to install missing packages as needed. +[Docs](https://kit.svelte.dev/docs/adapter-auto) ## Changelog diff --git a/packages/adapter-cloudflare-workers/README.md b/packages/adapter-cloudflare-workers/README.md index d59cff039a6a..ab34b9418023 100644 --- a/packages/adapter-cloudflare-workers/README.md +++ b/packages/adapter-cloudflare-workers/README.md @@ -4,118 +4,9 @@ SvelteKit adapter that creates a Cloudflare Workers site using a function for dy **Requires [Wrangler v2](https://developers.cloudflare.com/workers/wrangler/get-started/).** Wrangler v1 is no longer supported. -_**Comparisons**_ +## Docs -- `adapter-cloudflare` – supports all SvelteKit features; builds for - [Cloudflare Pages](https://blog.cloudflare.com/cloudflare-pages-goes-full-stack/) -- `adapter-cloudflare-workers` – supports all SvelteKit features; builds for - Cloudflare Workers -- `adapter-static` – only produces client-side static assets; compatible with - Cloudflare Pages - -> **Note:** Cloudflare Pages' new Workers integration is currently in beta.
-> Compared to `adapter-cloudflare-workers`, `adapter-cloudflare` is the preferred approach for most users since building on top of Pages unlocks automatic builds and deploys, preview deployments, instant rollbacks, etc.
-> From SvelteKit's perspective, there is no difference and no functionality loss when migrating to/from the Workers and the Pages adapters. - -## Usage - -Install with `npm i -D @sveltejs/adapter-cloudflare-workers`, then add the adapter to your `svelte.config.js`: - -```js -import adapter from '@sveltejs/adapter-cloudflare-workers'; - -export default { - kit: { - adapter: adapter() - } -}; -``` - -## Basic Configuration - -This adapter expects to find a [wrangler.toml](https://developers.cloudflare.com/workers/platform/sites/configuration) file in the project root. It should look something like this: - -```toml -name = "" -account_id = "" - -main = "./.cloudflare/worker.js" -site.bucket = "./.cloudflare/public" - -build.command = "npm run build" - -compatibility_date = "2021-11-12" -workers_dev = true -``` - -`` can be anything. `` can be found by logging into your [Cloudflare dashboard](https://dash.cloudflare.com) and grabbing it from the end of the URL: - -``` -https://dash.cloudflare.com/ -``` - -> It's recommended that you add the `.cloudflare` directory (or whichever directories you specified for `main` and `site.bucket`) to your `.gitignore`. - -You will need to install [wrangler](https://developers.cloudflare.com/workers/wrangler/get-started/) and log in, if you haven't already: - -``` -npm i -g wrangler -wrangler login -``` - -Then, you can build your app and deploy it: - -```sh -wrangler publish -``` - -## Custom config - -If you would like to use a config file other than `wrangler.toml`, you can do like so: - -```js -import adapter from '@sveltejs/adapter-cloudflare-workers'; - -export default { - kit: { - adapter: adapter({ config: '.toml' }) - } -}; -``` - -## Environment variables - -The [`env`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#parameters) object, containing KV/DO namespaces etc, is passed to SvelteKit via the `platform` property along with `context` and `caches`, meaning you can access it in hooks and endpoints: - -```js -export async function POST({ request, platform }) { - const x = platform.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x'); -} -``` - -To make these types available to your app, reference them in your `src/app.d.ts`: - -```diff -/// -+/// - -declare namespace App { - interface Platform { -+ env?: { -+ YOUR_KV_NAMESPACE: KVNamespace; -+ YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace; -+ }; - } -} -``` - -> `platform.env` is only available in the production build. Use [wrangler](https://developers.cloudflare.com/workers/cli-wrangler) to test it locally - -## Troubleshooting - -### Accessing the file system - -You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. +[Docs](https://kit.svelte.dev/docs/adapter-cloudflare-workers) ## Changelog diff --git a/packages/adapter-cloudflare-workers/ambient.d.ts b/packages/adapter-cloudflare-workers/ambient.d.ts index e0ee9db199db..5978f0dd3850 100644 --- a/packages/adapter-cloudflare-workers/ambient.d.ts +++ b/packages/adapter-cloudflare-workers/ambient.d.ts @@ -1,12 +1,12 @@ -import { Cache, CacheStorage } from '@cloudflare/workers-types'; +import { CacheStorage } from '@cloudflare/workers-types'; declare global { namespace App { export interface Platform { - context?: { + context: { waitUntil(promise: Promise): void; }; - caches?: CacheStorage & { default: Cache }; + caches: CacheStorage; } } } diff --git a/packages/adapter-cloudflare-workers/files/entry.js b/packages/adapter-cloudflare-workers/files/entry.js index 7501777152a4..0969ba1bbf07 100644 --- a/packages/adapter-cloudflare-workers/files/entry.js +++ b/packages/adapter-cloudflare-workers/files/entry.js @@ -67,7 +67,12 @@ export default { // dynamically-generated pages return await server.respond(req, { - platform: { env, context, caches }, + platform: { + env, + context, + // @ts-expect-error lib.dom is interfering with workers-types + caches + }, getClientAddress() { return req.headers.get('cf-connecting-ip'); } diff --git a/packages/adapter-cloudflare-workers/index.d.ts b/packages/adapter-cloudflare-workers/index.d.ts index 260ec62b75f9..8b90611b73c3 100644 --- a/packages/adapter-cloudflare-workers/index.d.ts +++ b/packages/adapter-cloudflare-workers/index.d.ts @@ -1,3 +1,4 @@ import { Adapter } from '@sveltejs/kit'; +import './ambient.js'; export default function plugin(options: { config?: string }): Adapter; diff --git a/packages/adapter-cloudflare/README.md b/packages/adapter-cloudflare/README.md index ccfe906bcd1f..775351116cc0 100644 --- a/packages/adapter-cloudflare/README.md +++ b/packages/adapter-cloudflare/README.md @@ -1,97 +1,10 @@ # adapter-cloudflare -[Adapter](https://kit.svelte.dev/docs/adapters) for building SvelteKit applications on [Cloudflare Pages](https://developers.cloudflare.com/pages/) with [Workers integration](https://developers.cloudflare.com/pages/platform/functions). +[Adapter](https://kit.svelte.dev/docs/building-your-app) for building SvelteKit applications on [Cloudflare Pages](https://developers.cloudflare.com/pages/) with [Workers integration](https://developers.cloudflare.com/pages/platform/functions). -If you're using [adapter-auto](../adapter-auto), you don't need to install this — it's already included. +## Docs -_**Comparisons**_ - -- `adapter-cloudflare` – supports all SvelteKit features; builds for - [Cloudflare Pages](https://blog.cloudflare.com/cloudflare-pages-goes-full-stack/) -- `adapter-cloudflare-workers` – supports all SvelteKit features; builds for - Cloudflare Workers -- `adapter-static` – only produces client-side static assets; compatible with - Cloudflare Pages - -> **Note:** Cloudflare Pages' new Workers integration is currently in beta.
-> Compared to `adapter-cloudflare-workers`, this adapter will be the preferred approach for most users since building on top of Pages unlocks automatic builds and deploys, preview deployments, instant rollbacks, etc.
-> From SvelteKit's perspective, there is no difference and no functionality loss when migrating to/from the Workers and the Pages adapters. - -## Installation - -```sh -$ npm i --save-dev @sveltejs/adapter-cloudflare -``` - -## Usage - -You can include these changes in your `svelte.config.js` configuration file: - -```js -import adapter from '@sveltejs/adapter-cloudflare'; - -export default { - kit: { - adapter: adapter() - } -}; -``` - -## Deployment - -Please follow the [Get Started Guide](https://developers.cloudflare.com/pages/get-started) for Cloudflare Pages to begin. - -When configuring your project settings, you must use the following settings: - -- **Framework preset** – None -- **Build command** – `npm run build` or `svelte-kit build` -- **Build output directory** – `.svelte-kit/cloudflare` -- **Environment variables** - - `NODE_VERSION`: `16` - -> **Important:** You need to add a `NODE_VERSION` environment variable to both the "production" and "preview" environments. You can add this during project setup or later in the Pages project settings. SvelteKit requires Node `16.14` or later, so you should use `16` as the `NODE_VERSION` value. - -## Environment variables - -The [`env`](https://developers.cloudflare.com/workers/runtime-apis/fetch-event#parameters) object, containing KV/DO namespaces etc, is passed to SvelteKit via the `platform` property along with `context` and `caches`, meaning you can access it in hooks and endpoints: - -```js -export async function POST({ request, platform }) { - const x = platform.env.YOUR_DURABLE_OBJECT_NAMESPACE.idFromName('x'); -} -``` - -To make these types available to your app, reference them in your `src/app.d.ts`: - -```diff -/// -+/// - -declare namespace App { - interface Platform { -+ env?: { -+ YOUR_KV_NAMESPACE: KVNamespace; -+ YOUR_DURABLE_OBJECT_NAMESPACE: DurableObjectNamespace; -+ }; - } -} -``` - -> `platform.env` is only available in the production build. Use [wrangler](https://developers.cloudflare.com/workers/cli-wrangler) to test it locally - -## Notes - -Functions contained in the `/functions` directory at the project's root will _not_ be included in the deployment, which is compiled to a [single `_worker.js` file](https://developers.cloudflare.com/pages/platform/functions/#advanced-mode). Functions should be implemented as [server endpoints](https://kit.svelte.dev/docs/routing#server) in your SvelteKit app. - -The [`_headers` and `_redirects`](config files) files specific to Cloudflare Pages can be used for static asset responses (like images) by putting them into the `/static` folder. - -However, they will have no effect on responses dynamically rendered by SvelteKit, which should return custom headers or redirect responses from [server endpoints](https://kit.svelte.dev/docs/routing#server) or with the [`handle`](https://kit.svelte.dev/docs/hooks#server-hooks-handle) hook. - -## Troubleshooting - -### Accessing the file system - -You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. +[Docs](https://kit.svelte.dev/docs/adapter-cloudflare) ## Changelog diff --git a/packages/adapter-netlify/README.md b/packages/adapter-netlify/README.md index f6a34c470079..ccbd34426b0f 100644 --- a/packages/adapter-netlify/README.md +++ b/packages/adapter-netlify/README.md @@ -2,113 +2,11 @@ A SvelteKit adapter that creates a Netlify app. -If you're using [adapter-auto](../adapter-auto), you don't need to install this unless you need to specify Netlify-specific options, since it's already included. +If you're using [adapter-auto](https://kit.svelte.dev/docs/adapter-auto), you don't need to install this unless you need to specify Netlify-specific options, since it's already included. -## Installation +## Docs -```bash -npm i -D @sveltejs/adapter-netlify -``` - -You can then configure it inside of `svelte.config.js`: - -```js -import adapter from '@sveltejs/adapter-netlify'; - -export default { - kit: { - // default options are shown - adapter: adapter({ - // if true, will create a Netlify Edge Function rather - // than using standard Node-based functions - edge: false, - - // if true, will split your app into multiple functions - // instead of creating a single one for the entire app. - // if `edge` is true, this option cannot be used - split: false - }) - } -}; -``` - -Then, make sure you have a [netlify.toml](https://docs.netlify.com/configure-builds/file-based-configuration) file in the project root. This will determine where to write static assets based on the `build.publish` settings, as per this sample configuration: - -```toml -[build] - command = "npm run build" - publish = "build" -``` - -If the `netlify.toml` file or the `build.publish` value is missing, a default value of `"build"` will be used. Note that if you have set the publish directory in the Netlify UI to something else then you will need to set it in `netlify.toml` too, or use the default value of `"build"`. - -### Node version - -New projects will use Node 16 by default. However, if you're upgrading a project you created a while ago it may be stuck on an older version. See [the Netlify docs](https://docs.netlify.com/configure-builds/manage-dependencies/#node-js-and-javascript) for details on manually specifying Node 16 or newer. - -## Netlify Edge Functions (beta) - -SvelteKit supports the beta release of [Netlify Edge Functions](https://docs.netlify.com/netlify-labs/experimental-features/edge-functions/). If you pass the option `edge: true` to the `adapter` function, server-side rendering will happen in a Deno-based edge function that's deployed close to the site visitor. If set to `false` (the default), the site will deploy to standard Node-based Netlify Functions. - -```js -import adapter from '@sveltejs/adapter-netlify'; - -export default { - kit: { - adapter: adapter({ - // will create a Netlify Edge Function using Deno-based - // rather than using standard Node-based functions - edge: true - }) - } -}; -``` - -## Netlify alternatives to SvelteKit functionality - -You may build your app using functionality provided directly by SvelteKit without relying on any Netlify functionality. Using the SvelteKit versions of these features will allow them to be used in dev mode, tested with integration tests, and to work with other adapters should you ever decide to switch away from Netlify. However, in some scenarios you may find it beneficial to use the Netlify versions of these features. One example would be if you're migrating an app that's already hosted on Netlify to SvelteKit. - -### Using Netlify Redirect Rules - -During compilation, redirect rules are automatically appended to your `_redirects` file. (If it doesn't exist yet, it will be created.) That means: - -- `[[redirects]]` in `netlify.toml` will never match as `_redirects` has a [higher priority](https://docs.netlify.com/routing/redirects/#rule-processing-order). So always put your rules in the [`_redirects` file](https://docs.netlify.com/routing/redirects/#syntax-for-the-redirects-file). -- `_redirects` shouldn't have any custom "catch all" rules such as `/* /foobar/:splat`. Otherwise the automatically appended rule will never be applied as Netlify is only processing [the first matching rule](https://docs.netlify.com/routing/redirects/#rule-processing-order). - -### Using Netlify Forms - -1. Create your Netlify HTML form as described [here](https://docs.netlify.com/forms/setup/#html-forms), e.g. as `/routes/contact.svelte`. (Don't forget to add the hidden `form-name` input element!) -2. Netlify's build bot parses your HTML files at deploy time, which means your form must be [prerendered](https://kit.svelte.dev/docs/page-options#prerender) as HTML. You can either add `export const prerender = true` to your `contact.svelte` to prerender just that page or set the `kit.prerender.force: true` option to prerender all pages. -3. If your Netlify form has a [custom success message](https://docs.netlify.com/forms/setup/#success-messages) like `` then ensure the corresponding `/routes/success.svelte` exists and is prerendered. - -### Using Netlify Functions - -With this adapter, SvelteKit endpoints are hosted as [Netlify Functions](https://docs.netlify.com/functions/overview/). Netlify function handlers have additional context, including [Netlify Identity](https://docs.netlify.com/visitor-access/identity/) information. You can access this context via the `event.platform.context` field inside your hooks and `+page.server` or `+layout.server` endpoints. These are [serverless functions](https://docs.netlify.com/functions/overview/) when the `edge` property is `false` in the adapter config or [edge functions](https://docs.netlify.com/edge-functions/overview/#app) when it is `true`. - -```js -// +page.server.js -export const load = async (event) => { - const context = event.platform.context; - console.log(context); // shows up in your functions log in the Netlify app -}; -``` - -Additionally, you can add your own Netlify functions by creating a directory for them and adding the configuration to your `netlify.toml` file. For example: - -```toml -[build] - command = "npm run build" - publish = "build" - -[functions] - directory = "functions" -``` - -## Troubleshooting - -### Accessing the file system - -You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. +[Docs](https://kit.svelte.dev/docs/adapter-netlify) ## Changelog diff --git a/packages/adapter-node/README.md b/packages/adapter-node/README.md index d02c8465e8b8..100a2687a4bb 100644 --- a/packages/adapter-node/README.md +++ b/packages/adapter-node/README.md @@ -2,190 +2,9 @@ [Adapter](https://kit.svelte.dev/docs/adapters) for SvelteKit apps that generates a standalone Node server. -## Usage +## Docs -Install with `npm i -D @sveltejs/adapter-node`, then add the adapter to your `svelte.config.js`: - -```js -// svelte.config.js -import adapter from '@sveltejs/adapter-node'; - -export default { - kit: { - adapter: adapter() - } -}; -``` - -## Deploying - -You will need the output directory (`build` by default), the project's `package.json`, and the production dependencies in `node_modules` to run the application. Production dependencies can be generated with `npm ci --prod` (you can skip this step if your app doesn't have any dependencies). You can then start your app with - -```bash -node build -``` - -Development dependencies will be bundled into your app using `rollup`. To control whether a given package is bundled or externalised, place it in `devDependencies` or `dependencies` respectively in your `package.json`. - -## Environment variables - -In `dev` and `preview`, SvelteKit will read environent variables from your `.env` file (or `.env.local`, or `.env.[mode]`, [as determined by Vite](https://vitejs.dev/guide/env-and-mode.html#env-files).) - -In production, `.env` files are _not_ automatically loaded. To do so, install `dotenv` in your project... - -```bash -npm install dotenv -``` - -...and invoke it before running the built app: - -```diff --node build -+node -r dotenv/config build -``` - -### `PORT` and `HOST` - -By default, the server will accept connections on `0.0.0.0` using port 3000. These can be customised with the `PORT` and `HOST` environment variables: - -``` -HOST=127.0.0.1 PORT=4000 node build -``` - -### `ORIGIN`, `PROTOCOL_HEADER` and `HOST_HEADER` - -HTTP doesn't give SvelteKit a reliable way to know the URL that is currently being requested. The simplest way to tell SvelteKit where the app is being served is to set the `ORIGIN` environment variable: - -``` -ORIGIN=https://my.site node build -``` - -With this, a request for the `/stuff` pathname will correctly resolve to `https://my.site/stuff`. Alternatively, you can specify headers that tell SvelteKit about the request protocol and host, from which it can construct the origin URL: - -``` -PROTOCOL_HEADER=x-forwarded-proto HOST_HEADER=x-forwarded-host node build -``` - -> [`x-forwarded-proto`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Proto) and [`x-forwarded-host`](https://developer.mozilla.org/en-US/docs/Web/HTTP/Headers/X-Forwarded-Host) are de facto standard headers that forward the original protocol and host if you're using a reverse proxy (think load balancers and CDNs). You should only set these variables if your server is behind a trusted reverse proxy; otherwise, it'd be possible for clients to spoof these headers. - -If `adapter-node` can't correctly determine the URL of your deployment, you may experience this error when using [form actions](https://kit.svelte.dev/docs/form-actions): - -> Cross-site POST form submissions are forbidden - -### `ADDRESS_HEADER` and `XFF_DEPTH` - -The [RequestEvent](https://kit.svelte.dev/docs/types#public-types-requestevent) object passed to hooks and endpoints includes an `event.getClientAddress()` function that returns the client's IP address. By default this is the connecting `remoteAddress`. If your server is behind one or more proxies (such as a load balancer), this value will contain the innermost proxy's IP address rather than the client's, so we need to specify an `ADDRESS_HEADER` to read the address from: - -``` -ADDRESS_HEADER=True-Client-IP node build -``` - -> Headers can easily be spoofed. As with `PROTOCOL_HEADER` and `HOST_HEADER`, you should [know what you're doing](https://adam-p.ca/blog/2022/03/x-forwarded-for/) before setting these. - -If the `ADDRESS_HEADER` is `X-Forwarded-For`, the header value will contain a comma-separated list of IP addresses. The `XFF_DEPTH` environment variable should specify how many trusted proxies sit in front of your server. E.g. if there are three trusted proxies, proxy 3 will forward the addresses of the original connection and the first two proxies: - -``` -, , -``` - -Some guides will tell you to read the left-most address, but this leaves you [vulnerable to spoofing](https://adam-p.ca/blog/2022/03/x-forwarded-for/): - -``` -, , , -``` - -Instead, we read from the _right_, accounting for the number of trusted proxies. In this case, we would use `XFF_DEPTH=3`. - -> If you need to read the left-most address instead (and don't care about spoofing) — for example, to offer a geolocation service, where it's more important for the IP address to be _real_ than _trusted_, you can do so by inspecting the `x-forwarded-for` header within your app. - -### `BODY_SIZE_LIMIT` - -The maximum request body size to accept in bytes including while streaming. Defaults to 512kb. You can disable this option with a value of 0 and implement a custom check in [`handle`](https://kit.svelte.dev/docs/hooks#server-hooks-handle) if you need something more advanced. - -## Options - -The adapter can be configured with various options: - -```js -// svelte.config.js -import adapter from '@sveltejs/adapter-node'; - -export default { - kit: { - adapter: adapter({ - // default options are shown - out: 'build', - precompress: false, - envPrefix: '' - }) - } -}; -``` - -### out - -The directory to build the server to. It defaults to `build` — i.e. `node build` would start the server locally after it has been created. - -### precompress - -Enables precompressing using gzip and brotli for assets and prerendered pages. It defaults to `false`. - -### envPrefix - -If you need to change the name of the environment variables used to configure the deployment (for example, to deconflict with environment variables you don't control), you can specify a prefix: - -```js -envPrefix: 'MY_CUSTOM_'; -``` - -``` -MY_CUSTOM_HOST=127.0.0.1 \ -MY_CUSTOM_PORT=4000 \ -MY_CUSTOM_ORIGIN=https://my.site \ -node build -``` - -## Custom server - -The adapter creates two files in your build directory — `index.js` and `handler.js`. Running `index.js` — e.g. `node build`, if you use the default build directory — will start a server on the configured port. - -Alternatively, you can import the `handler.js` file, which exports a handler suitable for use with [Express](https://github.com/expressjs/expressjs.com), [Connect](https://github.com/senchalabs/connect) or [Polka](https://github.com/lukeed/polka) (or even just the built-in [`http.createServer`](https://nodejs.org/dist/latest/docs/api/http.html#httpcreateserveroptions-requestlistener)) and set up your own server: - -```js -// my-server.js -import { handler } from './build/handler.js'; -import express from 'express'; - -const app = express(); - -// add a route that lives separately from the SvelteKit app -app.get('/healthcheck', (req, res) => { - res.end('ok'); -}); - -// let SvelteKit handle everything else, including serving prerendered pages and static assets -app.use(handler); - -app.listen(3000, () => { - console.log('listening on port 3000'); -}); -``` - -## Troubleshooting - -### Is there a hook for cleaning up before the server exits? - -There's nothing built-in to SvelteKit for this, because such a cleanup hook depends highly on the execution environment you're on. For Node, you can use its built-in `process.on(..)` to implement a callback that runs before the server exits: - -```js -function shutdownGracefully() { - // anything you need to clean up manually goes in here - db.shutdown(); -} - -process.on('SIGINT', shutdownGracefully); -process.on('SIGTERM', shutdownGracefully); -``` +[Docs](https://kit.svelte.dev/docs/adapter-cloudflare) ## Changelog diff --git a/packages/adapter-static/README.md b/packages/adapter-static/README.md index 281d96c60007..42a06f0f6b01 100644 --- a/packages/adapter-static/README.md +++ b/packages/adapter-static/README.md @@ -2,182 +2,9 @@ [Adapter](https://kit.svelte.dev/docs/adapters) for SvelteKit apps that prerenders your entire site as a collection of static files. It's also possible to create an SPA with it by specifying a fallback page which renders an empty shell. If you'd like to prerender only some pages and not create an SPA for those left out, you will need to use a different adapter together with [the `prerender` option](https://kit.svelte.dev/docs/page-options#prerender). -## Usage +## Docs -Install with `npm i -D @sveltejs/adapter-static`, then add the adapter to your `svelte.config.js`... - -```js -// svelte.config.js -import adapter from '@sveltejs/adapter-static'; - -export default { - kit: { - adapter: adapter({ - // default options are shown. On some platforms - // these options are set automatically — see below - pages: 'build', - assets: 'build', - fallback: null, - precompress: false, - strict: true - }) - } -}; -``` - -...and add the [`prerender`](https://kit.svelte.dev/docs/page-options#prerender) option to your root layout: - -```js -// src/routes/+layout.js - -// This can be false if you're using a fallback (i.e. SPA mode) -export const prerender = true; -``` - -> ⚠️ You must ensure SvelteKit's [`trailingSlash`](https://kit.svelte.dev/docs/page-options#trailingslash) option is set appropriately for your environment. If your host does not render `/a.html` upon receiving a request for `/a` then you will need to set `trailingSlash: 'always'` to create `/a/index.html` instead. - -## Zero-config support - -Some platforms have zero-config support (more to come in future): - -- [Vercel](https://vercel.com) - -On these platforms, you should omit the adapter options so that `adapter-static` can provide the optimal configuration: - -```diff -export default { - kit: { -- adapter: adapter({...}), -+ adapter: adapter(), - } - } -}; -``` - -## Options - -### pages - -The directory to write prerendered pages to. It defaults to `build`. - -### assets - -The directory to write static assets (the contents of `static`, plus client-side JS and CSS generated by SvelteKit) to. Ordinarily this should be the same as `pages`, and it will default to whatever the value of `pages` is, but in rare circumstances you might need to output pages and assets to separate locations. - -### fallback - -Specify a fallback page for SPA mode, e.g. `index.html` or `200.html` or `404.html`. - -### precompress - -If `true`, precompresses files with brotli and gzip. This will generate `.br` and `.gz` files. - -### strict - -By default, `adapter-static` checks that either all pages and endpoints (if any) of your app were prerendered, or you have the `fallback` option set. This check exists to prevent you from accidentally publishing an app where some parts of it are not accessible, because they are not contained in the final output. If you know this is ok (for example when a certain page only exists conditionally), you can set `strict` to `false` to turn off this check. - -## SPA mode - -You can use `adapter-static` to create a single-page app or SPA by specifying a **fallback page**. - -> In most situations this is not recommended: it harms SEO, tends to slow down perceived performance, and makes your app inaccessible to users if JavaScript fails or is disabled (which happens [more often than you probably think](https://kryogenix.org/code/browser/everyonehasjs.html)). - -If you want to create a simple SPA with no prerendered routes, the necessary config looks like this: - -```js -// svelte.config.js -import adapter from '@sveltejs/adapter-static'; - -export default { - kit: { - adapter: adapter({ - fallback: '200.html' - }), - prerender: { entries: [] } - } -}; -``` - -```js -// src/routes/+layout.js -export const ssr = false; -``` - -You can also turn only part of your app into an SPA. - -Let's go through these options one by one: - -### Add fallback page - -The fallback page is an HTML page created by SvelteKit that loads your app and navigates to the correct route. For example [Surge](https://surge.sh/help/adding-a-200-page-for-client-side-routing), a static web host, lets you add a `200.html` file that will handle any requests that don't correspond to static assets or prerendered pages. We can create that file like so: - -```js -// svelte.config.js -import adapter from '@sveltejs/adapter-static'; - -export default { - kit: { - adapter: adapter({ - fallback: '200.html' - }) - } -}; -``` - -> How to configure this behaviour does however depend on your hosting solution and is not part of SvelteKit. It is recommended to search the host's documentation on how to redirect requests. - -### Turn off prerendering - -When operating in SPA mode, you can omit the [`prerender`](https://kit.svelte.dev/docs/page-options#prerender) option from your root layout (or set it to `false`, its default value), and only pages that have the `prerender` option set will be prerendered at build time. - -SvelteKit will still crawl your app's entry points looking for prerenderable pages. If `svelte-kit build` fails because of pages that can't be loaded outside the browser, you can set `config.kit.prerender.entries` to `[]` to prevent this from happening. (Setting `config.kit.prerender.enabled` to `false` also has this effect, but would prevent the fallback page from being generated.) - -You can also add turn off prerendering only to parts of your app, if you want other parts to be prerendered. - -### Turn off ssr - -During development, SvelteKit will still attempt to server-side render your routes. This means accessing things that are only available in the browser (such as the `window` object) will result in errors, even though this would be valid in the output app. To align the behavior of SvelteKit's dev mode with your SPA, you can [add `export const ssr = false` to your root `+layout`](https://kit.svelte.dev/docs/page-options#ssr). You can also add this option only to parts of your app, if you want other parts to be prerendered. - -### Apache - -To run an SPA on [Apache](https://httpd.apache.org/), you should add a `static/.htaccess` file to route requests to the fallback page: - -``` - - RewriteEngine On - RewriteBase / - RewriteRule ^200\.html$ - [L] - RewriteCond %{REQUEST_FILENAME} !-f - RewriteCond %{REQUEST_FILENAME} !-d - RewriteRule . /200.html [L] - -``` - -## GitHub Pages - -When building for GitHub Pages, make sure to update [`paths.base`](https://kit.svelte.dev/docs/configuration#paths) to match your repo name, since the site will be served from rather than from the root. - -You will have to prevent GitHub's provided Jekyll from managing your site by putting an empty `.nojekyll` file in your static folder. If you do not want to disable Jekyll, change the kit's `appDir` configuration option to `'app_'` or anything not starting with an underscore. For more information, see GitHub's [Jekyll documentation](https://docs.github.com/en/pages/setting-up-a-github-pages-site-with-jekyll/about-github-pages-and-jekyll#configuring-jekyll-in-your-github-pages-site). - -A config for GitHub Pages might look like the following: - -```js -const dev = process.argv.includes('dev'); - -/** @type {import('@sveltejs/kit').Config} */ -const config = { - ... - kit: { - ... - paths: { - base: dev ? '' : '/your-repo-name', - }, - // If you are not using a .nojekyll file, change your appDir to something not starting with an underscore. - // For example, instead of '_app', use 'app_', 'internal', etc. - appDir: 'internal', - } -}; -``` +[Docs](https://kit.svelte.dev/docs/adapter-cloudflare) ## Changelog diff --git a/packages/adapter-vercel/README.md b/packages/adapter-vercel/README.md index 5a5e8a2c1b62..372dec3f27dc 100644 --- a/packages/adapter-vercel/README.md +++ b/packages/adapter-vercel/README.md @@ -2,83 +2,11 @@ A SvelteKit adapter that creates a Vercel app. -If you're using [adapter-auto](../adapter-auto), you don't need to install this unless you need to specify Vercel-specific options, since it's already included. +If you're using [adapter-auto](https://kit.svelte.dev/docs/adapter-auto), you don't need to install this unless you need to specify Vercel-specific options, since it's already included. -## Usage +## Docs -Add `"@sveltejs/adapter-vercel": "next"` to the `devDependencies` in your `package.json` and run `npm install`. - -Then in your `svelte.config.js`: - -```js -import vercel from '@sveltejs/adapter-vercel'; - -export default { - kit: { - // default options are shown - adapter: vercel({ - // if true, will deploy the app using edge functions - // (https://vercel.com/docs/concepts/functions/edge-functions) - // rather than serverless functions - edge: false, - - // an array of dependencies that esbuild should treat - // as external when bundling functions - external: [], - - // if true, will split your app into multiple functions - // instead of creating a single one for the entire app - split: false - }) - } -}; -``` - -## Environment Variables - -Vercel makes a set of [deployment-specific environment variables](https://vercel.com/docs/concepts/projects/environment-variables#system-environment-variables) available. Like other environment variables, these are accessible from `$env/static/private` and `$env/dynamic/private` (sometimes — more on that later), and inaccessible from their public counterparts. To access one of these variables from the client: - -```js -// +layout.server.js -import { VERCEL_COMMIT_REF } from '$env/static/private'; - -/** @type {import('./$types').LayoutServerLoad} */ -export function load() { - return { - deploymentGitBranch: VERCEL_COMMIT_REF - }; -} -``` - -```svelte - - - -

This staging environment was deployed from {data.deploymentGitBranch}.

-``` - -Since all of these variables are unchanged between build time and run time when building on Vercel, we recommend using `$env/static/private` — which will statically replace the variables, enabling optimisations like dead code elimination — rather than `$env/dynamic/private`. If you're deploying with `edge: true` you _must_ use `$env/static/private`, as `$env/dynamic/private` and `$env/dynamic/public` are not currently populated in edge functions on Vercel. - -## Notes - -### Vercel functions - -Vercel functions contained in the `/api` directory at the project's root will _not_ be included in the deployment — these should be implemented as [server endpoints](https://kit.svelte.dev/docs/routing#server) in your SvelteKit app. - -### Node version - -Projects created before a certain date will default to using Node 14, while SvelteKit requires Node 16 or later. You can change that in your project settings: - -![Vercel project settings](settings.png) - -## Troubleshooting - -### Accessing the file system - -You can't access the file system through methods like `fs.readFileSync` in Serverless/Edge environments. If you need to access files that way, do that during building the app through [prerendering](https://kit.svelte.dev/docs/page-options#prerender). If you have a blog for example and don't want to manage your content through a CMS, then you need to prerender the content (or prerender the endpoint from which you get it) and redeploy your blog everytime you add new content. +[Docs](https://kit.svelte.dev/docs/adapter-cloudflare) ## Changelog diff --git a/packages/kit/types/ambient.d.ts b/packages/kit/types/ambient.d.ts index 57d62ce63eb7..8a81037954c4 100644 --- a/packages/kit/types/ambient.d.ts +++ b/packages/kit/types/ambient.d.ts @@ -40,7 +40,7 @@ declare namespace App { export interface PageData {} /** - * If your adapter provides [platform-specific context](https://kit.svelte.dev/docs/adapters#supported-environments-platform-specific-context) via `event.platform`, you can specify it here. + * If your adapter provides [platform-specific context](https://kit.svelte.dev/docs/adapters#platform-specific-context) via `event.platform`, you can specify it here. */ export interface Platform {} } diff --git a/sites/kit.svelte.dev/package.json b/sites/kit.svelte.dev/package.json index a374c460c258..fa89f6627b0d 100644 --- a/sites/kit.svelte.dev/package.json +++ b/sites/kit.svelte.dev/package.json @@ -3,7 +3,7 @@ "version": "0.0.1", "scripts": { "update": "node scripts/check-doc-links.js && node scripts/types", - "dev": "npm run update && vite dev", + "dev": "vite dev", "build": "npm run update && vite build", "prebuild": "test \"$CI\" = true && npx pnpm install --store=node_modules/.pnpm-store || echo skipping pnpm install", "preview": "vite preview",