Reda Lemeden

Reda Lemeden

Indie Developer & Designer

Picking up Svelte

In this latest installment of my static site generation escapades, I will pick up Svelte, a relatively new Web framework (2016) with an increased focus on developer experience and performance.

My dissatisfaction with Gatsby has left me looking for alternatives, including writing my own in Swift—a daunting task given the long list of features I need to support for this website. I also considered Eleventy, Next.js, Hugo, and Gridsome, but none made the right blend of compromises for my use case, nor allowed configuration to remedy that.

One of the main selling points of Svelte is how it does away with the virtual DOM approach popularized by React.js. Instead, the framework generates vanilla JavaScript during build time, which in turn directly manipulates the DOM as the application state changes on the client. This means that your production code will be depedency-free and will have a smaller resource footprint as a result.

I previously hadn’t considered Svelte for static site generation, but SvelteKit changed that. SvelteKit is the official Svelte application framework and comes with support for all kinds of rendering acronyms approaches, and in any combination within the same app: server-side rendering (SSR), static site generation (SSG), and client-side rendering (CSR). My guess is that if it ends up working out for SSG, there is a high chance I will come back to it for other projects that require SSR or CSR.

Hands-on with Svelte

So to kick things off, I started out with the official guide. It’s quite broad and largely irrelevant for static site generation, but gives a good overview of how Svelte is different from the rest. Next I tried to go through the sections that are more relevant to the task at hand, namely the SSG and Static sites sections. That in turn took me to the adapters guide where I learned more about adapter-static and how it can make SvelteKit more tailored for static site generation.

While going through all these guides, I was pleasantly surprised to learn that both routing and hydration are optional and can be turned off, effectively removing all JS from the final output; a basic amenity the Gatsby team refuses to provide, leaving developers no choice but to come up with all sorts of hacks. Better yet, Svelte allows for these decisions to be made on a per-page basis, giving the developer full control over where and when to use these features.

After this brief documentation survey, I felt like it’s time to get my feet wet. I started by generating a blank app using the command borrowed from the Getting Started section:

pnpm init svelte@next my-app

Note that I am using pnpm instead of npm (more on the motivations in their own words). I encountered issues with it when used alongside React and Gatsby, but I am more than willing to give it another go with Svelte as part of this evaluation.

After I answered some setup wizard questions, I ran pnpm run dev -- --open to preview the output and make sure everything is fine and dandy. The next logical step for this evaluation was to try the syntax for disabling both hydration and routing as mentioned earlier—and it turns out it’s rather straightforward:

<!-- In index.svelte -->
<script context="module">
  export const hydrate = false;
  export const router = false;

I then proceeded to swap the @sveltejs/adapter-auto in devDependencies with @sveltejs/adapter-static then ran pnpm install again. I also needed to update this line in svelte.config.js:

- import adapter from '@sveltejs/adapter-auto';
+ import adapter from '@sveltejs/adapter-static';

After making these changes, I ran pnpm run build and checked the build/index.html file to ensure that it doesn’t import any JavaScript, which it didn’t. The HTML output looked like this—omitting the head and the top div:

<main class="svelte-g04a0w"><div class="container svelte-g04a0w"><h1 class="svelte-g04a0w">Homepage</h1>
    <hr class="svelte-g04a0w">
    <p class="svelte-g04a0w">This is my new SvelteKit app.</p></div>

If you’re like me, the svelte-g04a0w class littering the markup would have certainly grabbed your attention. This is a common approach in modern front-end tooling to ensure that styling remains scoped to a single page-component, but I still largely prefer to work with good ol’ fashioned global CSS when it comes to static websites.

<!-- In index.svelte -->
  main {
    font-family: sans-serif;

Removing this style block in index.svelte and re-running pnpm run build gets rid of these scope classes altogether in the final output. Also starting with Svelte v3.34.0 it looks like you can modify the class naming convention though the cssHash svelte.compile option if you still want to use component-scoped CSS.

After this spike, I spent another 10 minutes following the tutorial, before stopping half way when I realized that I’m not particularly interested in state or props at this stage.

And this about wraps up my first foray into Svelte. This brief experience has left me with a very good impression, and I will do my best to share some more about it in the coming weeks!