Simple notes from Migrating to PlusKit

“PlusKit” is my affectionate name for the Great SvelteKit Redesign of 2022. I was a little apprehensive at the amount of work and learning curve there would be, but it took about 1 hour all told (for admittedly a very simple sveltekit app like swyxkit).

You can see the final PR here: sw-yx#88/

What follows are just raw notes for “simple” sveltekit users like me. I want to stress that this is an incomplete list - however, I guess that if a “simple” usecase required these refactors, then they are the essential ones that most people will run into.

Run the migrate script

npx svelte-migrate routes

image

This is pretty straightforward - the migration script moves your code around and sometimes indiscriminately - in some cases you may have to move back some code (by uncommenting it back in) and in others you may have to refactor return signatures and imports. I found all the @migration hints to give enough warning - I solely looked at the @migration hints and that was sufficient.

image

Follow the instructions, but you’ll want to upgrade your sveltekit version as well: npm i @sveltejs/kit@1.0.0-next.423.

The 4 kinds of refactors

Static imports

Since we no longer have <script context="module">, if you did some static imports in a layout/page component, you’ll need to just move that into a <script>:

// src/routes/__layout.svelte -> src/routes/+layout.svelte
- <script context="module">
-  	import { MY_TWITTER_HANDLE, MY_YOUTUBE, REPO_URL, SITE_TITLE } from '$lib/siteConfig';
- </script>

<script>
	import '../tailwind.css';
	import Nav from '../components/Nav.svelte';
+ 	import { MY_TWITTER_HANDLE, MY_YOUTUBE, REPO_URL, SITE_TITLE } from '$lib/siteConfig';
</script>

This was fairly easy.

Special page values

Now that we don’t have load() in a page, we dont have access to url, status, or error from load(). Pull them from the page store instead:

// src/routes/__error.svelte -> src/routes/+error.svelte
- <script context="module">
- 	/** @type {import('@sveltejs/kit').ErrorLoad} */
- 	export function load({ url, error, status }) {
- 		return {
- 			props: { error, status, url }
- 		};
- 	}
- </script>

<script>
-	export let url;
-	export let status;
-	export let error;

+  import { page } from '$app/stores';

-	let message = offline ? 'Find the internet and try again' : error?.message;
+	let message = offline ? 'Find the internet and try again' : $page.error?.message;

-	let title = offline ? 'Offline' : status;
-	if (status === 404) {
+	let title = offline ? 'Offline' : $page.status;
+	if ($page.status === 404) {
		title = 'Page not found :(';
		message = 'Sorry! If you think this URL is broken, please let me know!';
	}

</script>


-	{#if status === 404}
-		<p class="">There is no post at the slug <code>{url.pathname}</code>.</p>
-		<p><a href={'/ideas/?filter=' + url.pathname.slice(1)}>Try searching for it here!</a></p>
+	{#if $page.status === 404}
+		<p class="">There is no post at the slug <code>{$page.url.pathname}</code>.</p>
+		<p><a href={'/ideas/?filter=' + $page.url.pathname.slice(1)}>Try searching for it here!</a></p>
...

You’ll want to look up what you can get from the Page store but otherwise it’s also pretty straightforward.

Refactor return values

I think this took the most time for me. There a few refactors to do:

  • Refactoring error values
  • Refactoring return values and headers for pages
  • Refactoring return values and headers for API routes

See migration docs.

Refactoring Errors:

// before: page.svelte
-			if (res.status > 400) {
-				return {
-					status: res.status,
-					error: await res.text()
-				};
-			}

// after: +page.js
+ import { error } from '@sveltejs/kit';
// ...
+		if (res.status > 400) {
+			throw error(res.status, await res.text())
+		}

Refactoring return values and headers (using the new setHeaders api):

// src/routes/[slug]/+page.js
-	export async function load({ params, fetch }) {
-		    const slug = params.slug;
-		    let res = null;
-		    res = await fetch(`/api/blog/${slug}.json`);
-		    return {
-			    props: {
-				    json: await res.json(),
-				    slug,
-				    REPO_URL
-			    },
-			    cache: {
-				    maxage: 60 // 1 minute
-			    }
-		    };

+ export async function load({ params, fetch, setHeaders }) {
+		const slug = params.slug;
+		let res = null;
+		    res = await fetch(`/api/blog/${slug}.json`);
+		    setHeaders({
+			    'cache-control': 'public, max-age=60'
+		    });
+		    return {
+			      json: await res.json(),
+			      slug,
+			      REPO_URL
+		    }

This refactor looks slightly different for API routes:

// src/routes/api/blog/[slug].json
-	try {
-		data = await getContent(slug);
-		return {
-			body: JSON.stringify(data),
-			headers: {
-				'Cache-Control': `max-age=0, s-maxage=${60}` // 1 minute.. for now
-			}
-		};
-	} catch (err) {
-		return {
-			status: 404,
-			body: err.message
-		};
-	}

+ import { error } from '@sveltejs/kit';
// ...
+		data = await getContent(slug).catch(err => error(404, err.message));
+		return new Response(JSON.stringify(data), {
+			headers: {
+				'Cache-Control': `max-age=0, s-maxage=${60}`
+			}
+		});

SvelteKit has a little json helper for the new Response(JSON.stringify stuff, so the last part simplifies to:

import { error, json } from '@sveltejs/kit';
// ...
		data = await getContent(slug).catch(err => error(404, err.message));
		return json(data, {
			headers: {
				'Cache-Control': `max-age=0, s-maxage=${60}`
			}
		});

data props

Per docs, we now no longer have individual export let declarations for a +page.svelte - everything comes into export let data and the types are supposed to flow from its corresponding +page.js:

+	/** @type {import('./$types').PageData} */
+	export let data;

	/** @type {import('$lib/types').ContentItem} */
-	export let json; // warning: if you try to destructure content here, make sure to make it reactive, or your page content will not update when your user navigates
+	$: json = data.json; 

(in practice I found PageData to still be any here but I am assuming those are growing pains)

Done

There are more smaller changes to handle (I dont use stuff, I don’t use session, I dont have a +page.server.js, etc), but the above was all that affected me and so I guess will be the major ones to take care of for most people, hence me writing this up. All told, about 400 lines of code affected for me.

image

Once again, you can see the final PR here: sw-yx#88/


    Tagged in: #svelte #sveltekit #changelog

    Reactions: 🎉 1
    Loading comments...

    Subscribe to the newsletter

    Get emails from me about Lorem ipsum dolor sit, amet consectetur adipisicing elit. Libero, ducimus..

    5,432 subscribers including my Mom – 123 issues

    Latest Posts

    Search and see all posts