Migrating from Vue 2 to Svelte

Migrating from Vue 2 to Svelte

After using Vue 2 as our front-end framework for almost two years, it was announced that this support would no longer be maintained, so we decided to migrate to a new framework. But which one to choose: Vue 3 or Svelte?

Please note that our goals after the migration were also to improve our developer experience especially type checking, performance, and building time. We didn't consider React because it would have taken too much time to learn, and it doesn't offer an out-of-the-box solution, as opposed to Vue and Svelte. Besides, the latters share the same concepts of single file components: logic (JavaScript), structure (HTML), and style (CSS) in the same file.

So we conducted some research and finally settled with Svelte. Here's an explanation of why and how.

 a) Svelte Versus Vue 3

Better retention ratio for Svelte. For our new front end, we had to choose from two frameworks available on the market, namely Svelte and Vue 3. Below is an illustration of the different frameworks' retention ratios (would use again / (would use again + would not use again)) over the past five years. Data were collected among developers in the field for the State of JS survey, and we can see that Svelte came in the 2nd position while Vue 3 only made it to the 4th.

In 2021 Svelte was in the 2nd position and Vue 3 in 4th position (source: State of JS)

This shows us that there are way more developers who used Svelte in the past that would be willing to use it again than not.

Better typing for Svelte.

Vue2 Vue3 Svelte
Component-level typing Yes Yes Yes
Cross-component typing No Yes Yes
Typed events No No Yes

Svelte offers a better typing experience with easier components' designing processes and built-in typed events, making it very user-friendly for us.

Restricted global access. With Svelte, it is possible to import enums from other files and use them in the template, which is not the case for Vue 3.

Escape Benchmark about frontend stack

Syntax. Personally, I find Svelte syntax more elegant and user-friendly than Vue. You can check the code blocks below and see them for yourself.

Svelte

<script>
    let firstName = "";
    let town = "";
    $: fullName = "Full name: " + firstName + ' ' + lastName;
    const reset = () => {
        firstName = "";
        lastName = "";
    }
</script>
<main>
    <div>
        <label>First name</label>
        <input type="text" bind:value={firstName}>
        <label>Last name</label>
        <input type="text" bind:value={lastName}>
        <button on:click={reset}>Reset</button>
    </div>
    <div>
        {fullName}
    </div>
</main>
<style>
  main{
    background-color: white;
  }
</style>

Vue

<template>
  <main>
    <label>First name </label>
    <input type="text" v-model="firstName"/>
    <label>Last name </label>
    <input type="text" v-model="lastName"/>
    <div>
        Full name: {{fullName}} 
    </div>
    <button @click="handleReset">Reset</button>
  </main>
</template>
<script setup>
import { ref, computed } from 'vue'
const firstName = ref('')
const lastName = ref('')

const fullName = computed(() => { return firstName.value + " " + lastName.value; })

function handleReset() {
    firstName.value = ""
    lastName.value = ""
}
</script>
<style scoped>
main{
  background-color: white;
}
</style>

No extra HTML div <template>. In Svelte you can directly write your own HTML.

Style is automatically scoped in Svelte, which is a good point for maintainability and helps to avoid CSS side effects. The style of each component is isolated to affect only the component, not its parents nor its children.

No computed properties are required to update data. In Svelte, it feels more like coding in pure javascript. You only have to focus on writing an arrow function:

const reset = () => {firstName = "";lastName = "";}

Only single brackets are necessary in Svelte

//Svelte
{fullName}

//Vue
{{fullName}}

Please note that this analysis is based on the specific code templates above and does not intend to give a detailed explanation of the frameworks' differences. For further information, feel free to look online.

Simpler to add pure js plugins. Below is an example of a syntax highlighting integration use case with Svelte and Prism.js:

// Prism.svelte
<script>
	import Prism from 'prismjs';

	export let code;
	export let lang = 'javascript';
</script>

<pre><code class="language-{lang}">{@html
	Prism.highlight(code, Prism.languages[lang], lang)
}</code></pre>
// App.svelte
<script>
	import Prism from './Prism.svelte';
	let code = 'export const hello =\n\t(name) => {console.log(`Hello ${name}!`)};';
</script>

<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/prism/1.28.0/themes/prism-dark.min.css" integrity="sha512-Njdz7T/p6Ud1FiTMqH87bzDxaZBsVNebOWmacBjMdgWyeIhUSFU4V52oGwo3sT+ud+lyIE98sS291/zxBfozKw==" crossorigin="anonymous" referrerpolicy="no-referrer" />

<Prism {code} />

Try on the REPL

Compiling code without virtual DOM. The main difference between Svelte and Vue is the reduction of the layers' number between the browser and the app, which results in more optimized and faster task completion.

Automatic updates. With the help of declared variables, Svelte can automatically update your data. That way, you don't have to wait for changes to be reflected in your virtual structure, resulting in a better user experience.

 b) Svelte also has its cons

Of course, Svelte has its shortcomings such as a relatively small community since it only came out in 2019. But as more and more developers may pick up on its qualities and user-friendly contents, support as well as the community may develop and grow in the future. There are already regular and very well-explained updates that are easily accessible on Github.

Therefore, after reviewing the results of this analysis, we decided to move forward with Svelte & Svelte Kit even though SvelteKit was still in active development at the time of the migration. (See below)

Escape Benchmark about frontend stack

Which method did we choose to process the migration?

When: We chose to proceed with the migration in August when fewer people were using the app.

Time length: It took us two weeks to migrate all the files from Vue to Svelte.

The number of developers: Two front-end developers worked full-time for two weeks alongside another developer who worked full-time for one week, so that's three developers involved.

Workflow: First, we used Notion tool to attribute our tickets to the team’s developers. Then, we started by creating our new components in Storybook, and finally, each developer was given a number of pages to rewrite in Svelte.

As a startup, it was simpler to migrate because we didn't have a thousand files to rewrite, so we could perform quickly. However, we took the risk to start our migration to SvelteKit when it was still in active development, and that resulted in us having to make big-breaking changes only one month after the move. But the SvelteKit professional and knowledgeable team provided us with a command (npx svelte-migrate routes) and a very well-explained migration guide that truly helped us adapt quickly to the new update.

In addition, in September, the SvelteKit team announced that the framework had finally entered its release candidate phase, which means its stability is now guaranteed!

Files & components organisation:

The "folder-based routing" of SvelteKit brought us a lot. We can split the pages into sub-pages so standard variables' names, such as "loading", "submit", etc... can be reused. Besides, layouts are directly integrated into the associated routes, which is simpler to access due to increased organization within the tree.

So what did we gain?

In addition to the benefits mentioned above, some other additional key factors deserve to be explored:

Increased and smoother performance. Once compiled, we can appreciate the application's lightweight. This increases loading speed compared to other frameworks, which embed a "runtime" alongside the application's logic code.

Better developer experience. SvelteKit uses Vite bundler, which is a new generation of JavaScript build tool that draws upon the availability of ES Modules in the browser and compile-to-native bundler to bring the best developer experience you can have from the most recent JavaScript technologies.

Faster code execution. It has no virtual DOM, and that's one layer less to execute in order to make a change on the page.

Up and running Server-side Rendering (SSR). In case of end users not having a good internet connection or javascript enabled, the platform will still be running efficiently with the help of the SSR, as users will still be able to load webpages while losing interactivity.

Concise and easy-to-understand code. Svelte makes it possible to use more readable and maintainable, component-oriented code by grouping together in the same file: logic (JavaScript), structure (HTML) and style (CSS). The particularity is that all these elements are compiled in a .svelte file

Fixed type checking. Since we migrated to Svelte, we have managed to solve our initial issues with type checking. Indeed, we previously had to handle recurrent notifications, and it is no longer the case today. No more annoying Sentry errors are showing up. (see below)

Example of Sentry errors bot notifications on our Discord

All in all, the aforementioned benefits and gains make our developer experience much more enjoyable so we can focus on releasing better and faster features on our Escape platform, and that's a big advantage for the end users 😊

Food for thoughts

💡 Wanna learn more about code quality? Read our blog article "GraphQL errors: the Good, the Bad and the Ugly".