-
-
Notifications
You must be signed in to change notification settings - Fork 2.2k
Docs for the new API #5810
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Merged
Merged
Docs for the new API #5810
Changes from all commits
Commits
Show all changes
9 commits
Select commit
Hold shift + click to select a range
a8c0ed9
Update routing
dummdidumm 47743b0
update layouts/error
dummdidumm c8d0f76
remove obsolete option
dummdidumm e6877f7
updates to file names in various places
dummdidumm af84f79
update loading docs
dummdidumm 560a728
update sapper migration
dummdidumm f02fd25
missed some
dummdidumm 52c6acf
clarify depends API
dummdidumm f613088
Update documentation/docs/03-routing.md
Rich-Harris File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Large diffs are not rendered by default.
Oops, something went wrong.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -6,7 +6,7 @@ So far, we've treated pages as entirely standalone components — upon navigatio | |
|
|
||
| But in many apps, there are elements that should be visible on _every_ page, such as top-level navigation or a footer. Instead of repeating them in every page, we can use _layout_ components. | ||
|
|
||
| To create a layout that applies to every page, make a file called `src/routes/__layout.svelte`. The default layout (the one that SvelteKit uses if you don't bring your own) looks like this... | ||
| To create a layout that applies to every page, make a file called `src/routes/+layout.svelte`. The default layout (the one that SvelteKit uses if you don't bring your own) looks like this... | ||
|
|
||
| ```html | ||
| <slot></slot> | ||
|
|
@@ -15,7 +15,7 @@ To create a layout that applies to every page, make a file called `src/routes/__ | |
| ...but we can add whatever markup, styles and behaviour we want. The only requirement is that the component includes a `<slot>` for the page content. For example, let's add a nav bar: | ||
|
|
||
| ```html | ||
| /// file: src/routes/__layout.svelte | ||
| /// file: src/routes/+layout.svelte | ||
| <nav> | ||
| <a href="/">Home</a> | ||
| <a href="/about">About</a> | ||
|
|
@@ -28,17 +28,17 @@ To create a layout that applies to every page, make a file called `src/routes/__ | |
| If we create pages for `/`, `/about` and `/settings`... | ||
|
|
||
| ```html | ||
| /// file: src/routes/index.svelte | ||
| /// file: src/routes/+page.svelte | ||
| <h1>Home</h1> | ||
| ``` | ||
|
|
||
| ```html | ||
| /// file: src/routes/about.svelte | ||
| /// file: src/routes/about/+page.svelte | ||
| <h1>About</h1> | ||
| ``` | ||
|
|
||
| ```html | ||
| /// file: src/routes/settings.svelte | ||
| /// file: src/routes/settings/+page.svelte | ||
| <h1>Settings</h1> | ||
| ``` | ||
|
|
||
|
|
@@ -51,7 +51,7 @@ Suppose we don't just have a single `/settings` page, but instead have nested pa | |
| We can create a layout that only applies to pages below `/settings` (while inheriting the root layout with the top-level nav): | ||
|
|
||
| ```html | ||
| /// file: src/routes/settings/__layout.svelte | ||
| /// file: src/routes/settings/+layout.svelte | ||
| <h1>Settings</h1> | ||
|
|
||
| <div class="submenu"> | ||
|
|
@@ -67,7 +67,7 @@ We can create a layout that only applies to pages below `/settings` (while inher | |
| Some parts of your app might need something other than the default layout. For these cases you can create _named layouts_... | ||
|
|
||
| ```svelte | ||
| /// file: src/routes/__layout-foo.svelte | ||
| /// file: src/routes/+layout-foo.svelte | ||
| <div class="foo"> | ||
| <slot></slot> | ||
| </div> | ||
|
|
@@ -76,132 +76,120 @@ Some parts of your app might need something other than the default layout. For t | |
| ...and then use them by referencing the layout name (`foo`, in the example above) in the filename: | ||
|
|
||
| ```svelte | ||
| /// file: src/routes/[email protected] | ||
| <h1>I am inside __layout-foo</h1> | ||
| /// file: src/routes/my-special-page/+page@foo.svelte | ||
| <h1>I am inside +layout-foo</h1> | ||
| ``` | ||
|
|
||
| Named layouts are very powerful, but it can take a minute to get your head round them. Don't worry if this doesn't make sense all at once. | ||
|
|
||
| #### Scoping | ||
|
|
||
| Named layouts can be created at any depth, and will apply to any components in the same subtree. For example, `__layout-foo` will apply to `/x/one` and `/x/two`, but not `/x/three` or `/four`: | ||
| Named layouts can be created at any depth, and will apply to any components in the same subtree. For example, `+layout-foo` will apply to `/x/one` and `/x/two`, but not `/x/three` or `/four`: | ||
|
|
||
| ```bash | ||
| src/routes/ | ||
| ├ x/ | ||
| │ ├ __layout-foo.svelte | ||
| │ ├ [email protected] # ✅ page has `@foo` | ||
| │ ├ [email protected] # ✅ page has `@foo` | ||
| │ └ three.svelte # ❌ page does not have `@foo` | ||
| └ [email protected] # ❌ page has `@foo`, but __layout-foo is not 'in scope' | ||
| │ ├ +layout-foo.svelte | ||
| │ ├ one/+page@foo.svelte # ✅ page has `@foo` | ||
| │ ├ two/+page@foo.svelte # ✅ page has `@foo` | ||
| │ └ three/+page.svelte # ❌ page does not have `@foo` | ||
| └ four/+page@foo.svelte # ❌ page has `@foo`, but +layout-foo is not 'in scope' | ||
| ``` | ||
|
|
||
| #### Inheritance chains | ||
|
|
||
| Layouts can themselves choose to inherit from named layouts, from the same directory or a parent directory. For example, `x/y/__layout@root.svelte` is the default layout for `/x/y` (meaning `/x/y/one`, `/x/y/two` and `/x/y/three` all inherit from it) because it has no name. Because it specifies `@root`, it will inherit directly from the nearest `__layout-root.svelte`, skipping `__layout.svelte` and `x/__layout.svelte`. | ||
| Layouts can themselves choose to inherit from named layouts, from the same directory or a parent directory. For example, `x/y/+layout@root.svelte` is the default layout for `/x/y` (meaning `/x/y/one`, `/x/y/two` and `/x/y/three` all inherit from it) because it has no name. Because it specifies `@root`, it will inherit directly from the nearest `+layout-root.svelte`, skipping `+layout.svelte` and `x/+layout.svelte`. | ||
|
|
||
| ``` | ||
| src/routes/ | ||
| ├ x/ | ||
| │ ├ y/ | ||
| │ │ ├ __layout@root.svelte | ||
| │ │ ├ one.svelte | ||
| │ │ ├ two.svelte | ||
| │ │ └ three.svelte | ||
| │ └ __layout.svelte | ||
| ├ __layout.svelte | ||
| └ __layout-root.svelte | ||
| │ │ ├ +layout@root.svelte | ||
| │ │ ├ one/+page.svelte | ||
| │ │ ├ two/+page.svelte | ||
| │ │ └ three/+page.svelte | ||
| │ └ +layout.svelte | ||
| ├ +layout.svelte | ||
| └ +layout-root.svelte | ||
| ``` | ||
|
|
||
| > In the case where `__layout-root.svelte` contains a lone `<slot />`, this effectively means we're able to 'reset' to a blank layout for any page or nested layout in the app by adding `@root`. | ||
| > In the case where `+layout-root.svelte` contains a lone `<slot />`, this effectively means we're able to 'reset' to a blank layout for any page or nested layout in the app by adding `@root`. | ||
|
|
||
| If no parent is specified, a layout will inherit from the nearest default (i.e. unnamed) layout _above_ it in the tree. In some cases, it's helpful for a named layout to inherit from a default layout _alongside_ it in the tree, such as `__layout-root.svelte` inheriting from `__layout.svelte`. We can do this by explicitly specifying `@default`, allowing `/x/y/one` and siblings to use the app's default layout without using `x/__layout.svelte`: | ||
| If no parent is specified, a layout will inherit from the nearest default (i.e. unnamed) layout _above_ it in the tree. In some cases, it's helpful for a named layout to inherit from a default layout _alongside_ it in the tree, such as `+layout-root.svelte` inheriting from `+layout.svelte`. We can do this by explicitly specifying `@default`, allowing `/x/y/one` and siblings to use the app's default layout without using `x/+layout.svelte`: | ||
|
|
||
| ```diff | ||
| src/routes/ | ||
| ├ x/ | ||
| │ ├ y/ | ||
| │ │ ├ __layout@root.svelte | ||
| │ │ ├ one.svelte | ||
| │ │ ├ two.svelte | ||
| │ │ └ three.svelte | ||
| │ └ __layout.svelte | ||
| ├ __layout.svelte | ||
| -└ __layout-root.svelte | ||
| +└ __layout[email protected] | ||
| │ │ ├ +layout@root.svelte | ||
| │ │ ├ one/+page.svelte | ||
| │ │ ├ two/+page.svelte | ||
| │ │ └ three/+page.svelte | ||
| │ └ +layout.svelte | ||
| ├ +layout.svelte | ||
| -└ +layout-root.svelte | ||
| +└ +layout[email protected] | ||
| ``` | ||
|
|
||
| > `default` is a reserved name — in other words, you can't have a `__layout-default.svelte` file. | ||
| > `default` is a reserved name — in other words, you can't have a `+layout-default.svelte` file. | ||
|
|
||
| ### Error pages | ||
|
|
||
| If a page fails to load (see [Loading](/docs/loading)), SvelteKit will render an error page. You can customise this page by creating `__error.svelte` components alongside your layouts and pages. | ||
| If a page fails to load (see [Loading](/docs/loading)), SvelteKit will render an error page. You can customise this page by creating `+error.svelte` components alongside your layouts and pages. | ||
|
|
||
| For example, if `src/routes/settings/notifications/index.svelte` failed to load, SvelteKit would render `src/routes/settings/notifications/__error.svelte` in the same layout, if it existed. If not, it would render `src/routes/settings/__error.svelte` in the parent layout, or `src/routes/__error.svelte` in the root layout. | ||
| For example, if `src/routes/settings/notifications/+page.svelte` failed to load, SvelteKit would render `src/routes/settings/notifications/+error.svelte` in the same layout, if it existed. If not, it would render `src/routes/settings/+error.svelte` in the parent layout, or `src/routes/+error.svelte` in the root layout. | ||
|
|
||
| > SvelteKit provides a default error page in case you don't supply `src/routes/__error.svelte`, but it's recommended that you bring your own. | ||
| > SvelteKit provides a default error page in case you don't supply `src/routes/+error.svelte`, but it's recommended that you bring your own. | ||
|
|
||
| If an error component has a [`load`](/docs/loading) function, it will be called with `error` and `status` properties: | ||
| An error component has no access to data retrieval mechanisms like pages or layouts to ensure nothing further can go wrong. You can use the [page store](/docs/modules#$app-stores-page) to display the status code and error message: | ||
|
|
||
| ```html | ||
| <script context="module"> | ||
| /** @type {import('@sveltejs/kit').Load} */ | ||
| export function load({ error, status }) { | ||
| return { | ||
| props: { | ||
| title: `${status}: ${error.message}` | ||
| } | ||
| }; | ||
| } | ||
| </script> | ||
|
|
||
| <script> | ||
| export let title; | ||
| import { page } from '$app/stores'; | ||
| </script> | ||
|
|
||
| <h1>{title}</h1> | ||
| <h1>{$page.status}</h1> | ||
| <p>{$page.error.message}</p> | ||
| ``` | ||
|
|
||
| > Layouts also have access to `error` and `status` via the [page store](/docs/modules#$app-stores) | ||
| > Layouts also have access to `error` and `status` via the same page store | ||
| > | ||
| > Server-side stack traces will be removed from `error` in production, to avoid exposing privileged information to users. | ||
|
|
||
| You can further handle unexpected errors on the server using the [handleError](/docs/hooks#handleerror) hook. | ||
|
|
||
| #### 404s | ||
|
|
||
| Nested error pages are only rendered when an error occurs while rendering a specific page. In the case of a request that doesn't match any existing route, SvelteKit will render a generic 404 instead. For example, given these routes... | ||
|
|
||
| ``` | ||
| src/routes/ | ||
| ├ __error.svelte | ||
| ├ +error.svelte | ||
| ├ marx-brothers/ | ||
| │ ├ __error.svelte | ||
| │ ├ chico.svelte | ||
| │ ├ harpo.svelte | ||
| │ └ groucho.svelte | ||
| │ ├ +error.svelte | ||
| │ ├ chico/+page.svelte | ||
| │ ├ harpo/+page.svelte | ||
| │ └ groucho/+page.svelte | ||
| ``` | ||
|
|
||
| ...the `marx-brothers/__error.svelte` file will _not_ be rendered if you visit `/marx-brothers/karl`. If you want to render the nested error page, you should create a route that matches any `/marx-brothers/*` request, and return a 404 from it: | ||
| ...the `marx-brothers/+error.svelte` file will _not_ be rendered if you visit `/marx-brothers/karl`. If you want to render the nested error page, you should create a route that matches any `/marx-brothers/*` request, and throw a 404 from it: | ||
|
|
||
| ```diff | ||
| src/routes/ | ||
| ├ __error.svelte | ||
| ├ +error.svelte | ||
| ├ marx-brothers/ | ||
| │ ├ __error.svelte | ||
| +│ ├ [...path].svelte | ||
| │ ├ chico.svelte | ||
| │ ├ harpo.svelte | ||
| │ └ groucho.svelte | ||
| ``` | ||
|
|
||
| ```svelte | ||
| /// file: src/routes/marx-brothers/[...path].svelte | ||
| <script context="module"> | ||
| /** @type {import('./__types/[...path]').Load} */ | ||
| export function load({ params }) { | ||
| return { | ||
| status: 404, | ||
| error: new Error(`Not found: /marx-brothers/${params.path}`) | ||
| }; | ||
| } | ||
| </script> | ||
| │ ├ +error.svelte | ||
| +│ ├ [...path]/+page.js | ||
| │ ├ chico/+page.svelte | ||
| │ ├ harpo/+page.svelte | ||
| │ └ groucho/+page.svelte | ||
| ``` | ||
|
|
||
| ```js | ||
| /// file: src/routes/marx-brothers/[...path]/+page.js | ||
| import { error } from '@sveltejs/kit'; | ||
| /** @type {import('./$types').Load} */ | ||
| export function load({ params }) { | ||
| throw error(404, `Not found: /marx-brothers/${params.path}`); | ||
| } | ||
| ``` | ||
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
Uh oh!
There was an error while loading. Please reload this page.