Migrating Breaking Changes in SvelteKit
Tags: svelte, sveltekit
Published: 2022-08-29 18:16:38

---
title: Migrating Breaking Changes in SvelteKit
published: true
description: There have been a lot of changes in the SvelteKit ecosystem recently. Find out more about routing changes, new layouts, the Vite CLI, and how to migrate your app.
tags: svelte, sveltekit
cover_image: https://cdn.sanity.io/images/o0o2tn5x/production/5fecd6c47a9bbcaf0aa6a38510b31bb58ef97e06-2400x1260.png
# Use a ratio of 100:42 for best results.
canonical_url: https://www.netlify.com/blog/migrating-breaking-changes-in-sveltekit/
---

SvelteKit has gone through a few breaking changes recently including an entire [routing overhaul](#so-long-file-based-routing), changes to the [load API](#removing-confusion-on-load), and a switch to the [Vite CLI](#all-in-on-vite). If you’ve used it in the past, it may look quite a bit different than it used to. Just looking at the [August updates](https://svelte.dev/blog/whats-new-in-svelte-august-2022), there were **ten** breaking changes. It’s a lot to keep up with, so this post will review the biggest breaking changes and navigate you through migrating an app to get it up to date.

## So Long File Based Routing

By far the biggest change in SvelteKit is doing away with file-based routing. There is still a `routes` directory where you will create your routes, but they are now directory based and require a `+` prefix to generate a route. 

### Routing The Old Way

Before, any file added to the `routes` directory would create a route at that name. This made it difficult to colocate files without more confusing syntax. Double underscores, `__` indicated a layout or error route, and a single underscore, `_` would skip creating it as a route. Things were messy and nothing was grouped together.

```
📂 src
└ 📂 routes
  ├ 📄 index.svelte
  ├ 📄 about.svelte
  ├ 📄 __layout.svelte
  ├ 📄 __layout-nested.svelte
  ├ 📄 __error.svelte
  └ 📂 nested-route
    └ 📄 _component-for-nested.svelte  
    └ 📄 index@nested.svelte
```

### Routing The New Way

Now all routes are directory based, other than the home or root route, all new routes need to be in a folder. The old `index.svelte` has gone away in favor of `+page.svelte` to indicate you are deliberately creating a route. You also no longer need the underscore, `_`, to colocate a component to a route. It’s much clearer what route each file is attached to in the new routing structure.

```
📂 src
└ 📂 routes
  ├ 📄 +page.svelte
  ├ 📄 +layout.svelte
  ├ 📄 +error.svelte
  └  📂 about
     ├ 📄 coc.svelte
     ├ 📄 +page.svelte
     └ 📄 +layout.svelte
```

### Resources
To find out more about why these changes happened, there are some really good conversations that happened on GitHub and the documentation walks through the new setup.

- [Routing Docs](https://kit.svelte.dev/docs/routing)

- [RFC Discussion on Changes](https://github.com/sveltejs/kit/discussions/5748)

- [Overview of Routing Changes](https://github.com/sveltejs/kit/discussions/5774#discussioncomment-3294867)

- [Comment from Rich on Routing Changes](https://github.com/sveltejs/kit/discussions/5748#discussioncomment-3282732)

## Layout Overhaul

Layouts in Svelte have gone through a major overhaul. No longer do multiple layouts live in the root of the routes directory, then naming them on a file such as `index@nested.svelte`. Basic layouts are now `+layout.svelte` files and will inherit from the root layout no matter how nested they are. 

### Layouts The Old Way

```
📂 src
└ 📂 routes
  ├ 📄 index.svelte
  ├ 📄 __layout.svelte
  ├ 📄 __layout-nested.svelte
  └ 📂 nested-route
    └ 📄 index@nested.svelte
```

### Layouts The New Way

```
📂 src
└ 📂 routes
  ├ 📄 +page.svelte
  ├ 📄 +layout.svelte
  └  📂 about
     ├ 📄 +page.svelte
     └ 📄 +layout.svelte // will inherit the src/routes/+layout.svelte layout
```

### Group Layouts

There is also a new convention to share layouts with a folder wrapped in parenthesis`()`called a group directory. Group directories do not affect the URL pathname of the nested routes, it essentially acts as a root route. A `+page.svelte` file can be added to a `(group)` directory root if the `/` or home route should be the group. Since layouts inherit all the way down, you may want to use a different layout in a nested route. To do that we can still use the named layout syntax of `+page@nested.svelte` where nested is the name of the layout you wish to use. To opt out of a layout entirely and reset it, create a `+layout@.svelte` file in the directory by the `+page.svelte` file that needs reset.

```
📂 src
└ 📂 routes
  ├ 📄 +layout.svelte
  └  📂 (marketing) // group routes
     ├ 📂 about
       ├ 📂 embed
         ├ 📄 +page.svelte
         └ 📄 +layout@(marketing).svelte // this will skip the about layout
       └ 📄 +layout.svelte
     ├ 📂 coc
       ├ 📄 +page.svelte
       └ 📄 +layout@.svelte //this will opt out of all layouts
     ├ 📄 +page.svelte // lives at / not /marketing
     └ 📄 +layout.svelte
```

### Resources
These changes were not the most straightforward and even the documentation is a little difficult to parse right now, but it is there. I found the discussion of the changes on GitHub to be more helpful and easier to understand.

- [Layout Docs](https://kit.svelte.dev/docs/routing#layout)

- [Advanced Layout Docs](https://kit.svelte.dev/docs/advanced-routing#advanced-layouts)

- [RFC Discussion on Changes](https://github.com/sveltejs/kit/pull/6174)

## Removing Confusion on Load

The load function is how a SvelteKit route receives outside data, such as from a database or 3rd party API. Before there was always confusion around whether the `load` function ran on the server or the client and was never clear if secrets were leaking through to the client. The `load` function has now moved out of the `.svelte` file and into an *endpoint* file. 

### Load The Old Way

Before, the load function lived in the `context="module"` script tag inside of the `.svelte` file or the data for the route was magically returned from an endpoint. Not all that long ago, another change occurred to the way data was loaded into a component. While the official name was **page endpoints**, us diehards kept fighting for the obviously cooler sounding **shadow endpoints**. These automagically loaded the data from the endpoint directly into the `.svelte` route by returning the data and then exporting a prop of the same name in the route.

```
📂 src
└ 📂 routes
  ├ 📄 index.svelte
  ├ 📄 index.js
  ├ 📄 about.svelte
  ├ 📄 about.js
  ├ 📄 __layout.svelte
  ├ 📄 __layout-nested.svelte
  ├ 📄 __error.svelte
  └ 📂 nested-route
    ├ 📄 index.js
    └ 📄 index@nested.svelte
```

```jsx
// in a .svelte route
<script context="module">
  export const load = () => {
    let propName = "arbitrary data"
    return {
      props: {
	propName
      }
    }
  }
</script>

<script>
  export let propName
</script>

<h1>Use the {propName}</h1>
```

### Load The New Way

Now the `load` function has moved into the endpoint file and the magical loading of data into the `.svelte` file still exists and passes to the route with the `data` prop. There are two new files you can use to load data into a route. The `+page.js` (or `+page.ts` for TypeScript) runs on the server during server-side rendering and again in the client when client-side navigating. There is also a `+page.server.js` that will **only** run on the server making it safe for API keys and secure SDKs you don’t want leaked to the client. You also no longer need to return the data inside of a props object. You determine where that data loads, either only on the server or both the server and client. In the `+page.svelte` route file, the prop is simply named `data` now.

```
📂 src
└ 📂 routes
  ├ 📄 +page.svelte
  ├ 📄 +page.js
  ├ 📄 +layout.svelte
  ├ 📄 +error.svelte
  └  📂 about
     ├ 📄 +page.svelte
     ├ 📄 +page.server.js
     └ 📄 +layout.svelte
```

```jsx
// in a +page.js or +page.server.js endpoint
// copy over your load function from before
export const load = () => {
  let propName = "arbitrary data"
  return {
    // remove the props object 
    propName
  }
}
```

```jsx
// in a +page.svelte route
<script>
  export let data
</script>

<h1>Use the {data.propName}</h1>
```

### Page Behavior

The exports that dictated a pages behavior have also moved from the `<script context="module">` into the endpoint file `+page.js`.

- `export const prerender = true` or `false` overrides [config.kit.prerender.default](https://kit.svelte.dev/docs/configuration#prerender)
- `export const hydrate = true` or `false` overrides [config.kit.browser.hydrate](https://kit.svelte.dev/docs/configuration#browser)
- `export const router = true` or `false` overrides [config.kit.browser.router](https://kit.svelte.dev/docs/configuration#browser)

### Resources
Here are some links to the documentation for the new endpoint files and loading data.

- [+page.js Docs](https://kit.svelte.dev/docs/routing#page-page-js)

- [+page.server.js Docs](https://kit.svelte.dev/docs/routing#page-page-server-js)

- [Loading Data Docs](https://kit.svelte.dev/docs/load)

## All in on Vite

SvelteKit has gone all in on the Vite ecosystem by pulling out the Vite config and becoming a Vite plugin. Way back in the day SvelteKit ran on Snowpack. They made the decision to switch after Vite version 2 came out in 2021 and added support for other frameworks besides Vue. That was just the underlying build tool and SvelteKit was still passing along the Vite configuration through its own `svelte.config.js` file and using its own `sveltekit` CLI command for running the dev and build scripts. This was using an experimental method and the goal was to move to a more standard way that frameworks typically interact with Vite, through a plugin. This allows for first-party support for tools like Vitest and Storybook that look for a Vite config file. With the new changes, SvelteKit is just a Vite project that uses the `@sveltejs/kit/vite` plugin and switched to the Vite CLI for the dev and build scripts. There is now a `vite.config.js` file at the root of a SvelteKit project, that includes the plugin along with any other [Vite configuration](https://vitejs.dev/config/).

### Vite The Old Way

```jsx
// svelte.config.js
import adapter from '@sveltejs/adapter-auto';
import preprocess from 'svelte-preprocess';

/** @type {import('@sveltejs/kit').Config} */
const config = {
// Consult https://github.com/sveltejs/svelte-preprocess
// for more information about preprocessors
preprocess: preprocess(),

  kit: {
    adapter: adapter(),
    vite: {
      // vite config stuff
    }
  };

export default config;
```

```json
// package.json
{
  "scripts": {
    "dev": "svelte-kit dev",
    "build": "svelte-kit build",
    "preview": "svelte-kit preview",
  }
}
```

### Vite The New Way

```jsx
// vite.config.js
import { sveltekit } from '@sveltejs/kit/experimental/vite';

export default {
  plugins: [ sveltekit() ]
};
```

```json
// package.json
{
  "scripts": {
	  "dev": "vite dev",
	  "build": "vite build",
	  "preview": "vite preview",
  }
}
```

## Migrating Changes

With big change always comes a lot of frustration for users. The maintainers of SvelteKit took this in mind and created an entire [migration guide](https://github.com/sveltejs/kit/discussions/5774) and a command, `npx svelte-migrate routes`, that attempts to make a lot of the changes for you. The script will rename the files inside the routes directory, comments out anything in a context module script tag, and throws errors to tell you to update to the `data` prop. However, no tool can take care of everything and there **will** still be manual changes that need to updated.  Depending on how long it’s been since you’ve upgraded, you may have several things to change. Here are the overview steps to follow.

1. Remove old lock files and node_modules.
    
    ```bash
    rm -rf node_modules package-lock.json # or yarn-lock or pnpm-lock
    ```
    
2. Update dependencies through your package manager.
    
    ```bash
    npm i # or yarn or pnpm
    ```
    
3. Run the migration command. The routes will be renamed and placed in the new directory structure and endpoint files will attempt to move to the appropriate type.
    
    ```bash
    npx svelte-migrate routes
    ```
    
4. Update any props in `+page.svelte` files to `data`.
    
    ```jsx
    - export let propName
    + export let data
    ```
    
5. Remove any `<script context="module">` stuff over to an endpoint file.
      ```jsx
    // in a +page.js or +page.server.js endpoint
    // copy over your load function from the .svelte file
    export const load = () => {
        let propName = "arbitrary data"
        return {
          // remove the props object 
          propName
        }
    }
    ```  

    
6. Make sure your scripts have been updated to the Vite CLI in the `package.json`.
    
    ```json
    // package.json
    {
      "scripts": {
        "dev": "vite dev",
        "build": "vite build",
        "preview": "vite preview",
      }
    }
    ```
    
7. Try to run it! 
    
    ```jsx
    npm run dev # or yarn or pnpm
    ```
    

These steps are just a general overview of the biggest changes. Depending on when you last upgraded, there may be other steps to follow. SvelteKit errors are pretty good and may help walk you through any other changes you need to make. There may also be unique situations in your app that will need more work. With the addition of the `+page.server.js` file, ensure you are loading your data where you need it. This will hopefully get you most of the way there.

### Resources
To find out more information about the migration, check out the migration guide and you can always view the most recent updates in the SvelteKit Docs.

- [Migration Guide](https://github.com/sveltejs/kit/discussions/5774)
- [SvelteKit Docs](https://kit.svelte.dev/docs/introduction)

## Moving Forward

With so many changes lately in SvelteKit, a lot of us are hoping to see the light at the end of the tunnel soon. Let’s hope these rapid changes mean we are getting close to 1.0. Hopefully this post helped bridge the gap to the latest changes. Go forth and migrate!

### Other Resources
Here are a few extra resources to continue getting up to date with everything in SvelteKit.

- [Newsletter August Updates in Svelte](https://svelte.dev/blog/whats-new-in-svelte-august-2022)

- [Project Structure](https://kit.svelte.dev/docs/project-structure)

- [Routing Changes Discussion](https://kit.svelte.dev/docs/project-structure)

- [Layout Changes Discussion](https://github.com/sveltejs/kit/pull/6174)

A few podcasts have been talking about the recent changes. If you prefer listening to reading check out these Svelte Radio and SyntaxFM episodes.

- Svelte Radio - [SvelteKit is changing Fast](https://www.svelteradio.com/episodes/sveltekit-is-changing-fast)
- Svelte Radio - [Let’s talk about Routing with Rich Harris](https://www.svelteradio.com/episodes/lets-talk-routing-with-rich-harris)
- SyntaxFM - [Supper Club x Rich Harris, Author of Svelte](https://syntax.fm/show/499/supper-club-rich-harris-author-of-svelte)