Comparing Svelte and Stencil JS Frameworks

June 12, 2019 ยท 4 minute read

Writing a blog is a great excuse to explore some new and unfamiliar technology. In this post I will explore two new(er) JavaScript frameworks, Stencil and Svelte.

As of writing this post. Svelte is at version 3.4.4 and Stencil is at version 1.0.0. Both projects seem actively worked on based on GitHub activity.

Both frameworks are web compiler frameworks. Meaning, they take some source input and generate some minified optimized version in JavaScript, HTML, and CSS.

Stencil

Stencil was created and is maintained by the Ionic Framework team. The focus is on using web standards, like custom web components, and not the opinions of a particular framework or build tools.

Since it generates standard web components, the components can be used in any JavaScript framework. It leverages modern browser APIs like Custom Elements. It supports IE11 and up.

Stencil also provides support for TypeScript and JSX. Here is an example component.

Example component. TypeScript + JSX = TSX

import { Component, Prop } from '@stencil/core';

@Component({
  tag: 'my-first-component',
})
export class MyComponent {

  // Indicate that name should be a public property on the component
  @Prop() name: string;

  render() {
    return (
      <p>
        My name is {this.name}
      </p>
    );
  }
}

Usage

<my-first-component name="Max"></my-first-component>

See learning resources for more guides and tutorials.

Svelte

Svelte seems like it has been around longer since it is at version 3. Some of the features of Svelte are:

.svelte files are very similar to Vue single file components. A .svelte file can have 3 sections a script tag with the business logic, a style tag with CSS, and finally markup.

The markup, or template section, differs from a Vue component because you don't need a root level element.

Here is an example component. I went through the tutorial in their documentation and combined all the parts I found useful or interesting into a compact example.

<script>
  import Nested from './Nested.svelte';

  let msg = 'A string with <strong>HTML</strong>';
  let things = ['dog', 'cat', 'bear', 'frog'];

  let count = 0;
  function handleClick() {
    count += 1;
  }
  // reactive statement
  // code is run when count changes
  $: console.log(`the count is ${count}`);
</script>

<style>
  button {
    color: white;
    background-color: blue;
  }
</style>

<p>{@html msg}</p>

<button on:click={handleClick}>
	Clicked {count} {count === 1 ? 'time' : 'times'}
</button>

{#if count > 10}
  <p>count &gt; 10</p>
{:else if count > 5}
  <p>count &gt; 5</p>
{:else}
  <p>count &lt; 5</p>
{/if}

<ul>
  {#each items in item}
    <li>{item}</li>
  {/each>
</ul>

<Nested title="nested"/>
<!-- Nested.svelte -->

<script>
  // export props and give it a default (optional)
  export let title = 'Title';
</script>

<p>{title}</p>

Svelte works with the following build tools.

For generating larger projects, similar to the Vue CLI, see Sapper. It supports routing, server-side rendering, and code-splitting.

Bundle Size Comparisons

I thought it would be interesting to compare the outputs of each of these frameworks with the Real World App. I went to the demo page of each implementation and compared the network statistics in the network tab in my browser's dev tools (Firefox).

Comparison Bar Chart
RealWorld App
FrameworkNumber of JS FilesJS bundle size (KB)%
Svelte743.544
Stencil10120.0612
Other Frameworks
Angular8551.9754
React/Redux11,024.00100
Vue6218.1321
Elm190.529

Network Charts From Dev Tools

Svelte Asset Size
Svelte Asset Size
Stencil Asset Size
Stencil Asset Size
Angular Asset Size
Angular Asset Size
React Asset Size
React Asset Size
Vue Asset Size
Vue Asset Size
Elm Asset Size
Elm Asset Size

A great future side project would be to generate these statistics for all the implementations of the RealWorld App. After scraping the project's REAMDE for the projects, you could use something like Selenium to hit each demo page and gather all the stats.

Conclusion

The new generation of JS frameworks seem more focused on bundle size. I thought nothing would be able to beat Elm's bundle size. Svelte proved me wrong.

After a brief look at these two frameworks, I would use Svelte as a replacement for Vue. It seems to provide a similar API.

I would use Stencil if I was concerned about sharing my component with the JS community and needed it to work across any JS framework.