Lithe 2: From Scratch


I've written a little Rust, but never professionally, so I'm sure what I write is going to be ugly to those in the know. But it compiles, which is half the battle.

Before starting this project let's take a quick peek at the Svelte repo. Oh, huh, looks like the compiler smaller than I would have thought, weighing in at only ~800KB (if you include the runtime), but 800KB of code to rewrite is still fairly massive for a weekend warrior like myself. So, for my initial attempt I crafted the world's smallest svelte app:

<span>Hello world!</span>

<span>Goodbye!</span>

I ran that through a recent Svelte compiler to get:

/* generated by Svelte v3.44.3 */
import {
 SvelteComponent,
 detach,
 element,
 init,
 insert,
 noop,
 safe_not_equal,
 space,
} from "svelte/internal";

function create_fragment(ctx) {
 let span0;
 let t1;
 let span1;

 return {
  c() {
   span0 = element("span");
   span0.textContent = "Hello world!";
   t1 = space();
   span1 = element("span");
   span1.textContent = "Goodbye";
  },
  m(target, anchor) {
   insert(target, span0, anchor);
   insert(target, t1, anchor);
   insert(target, span1, anchor);
  },
  p: noop,
  i: noop,
  o: noop,
  d(detaching) {
   if (detaching) detach(span0);
   if (detaching) detach(t1);
   if (detaching) detach(span1);
  },
 };
}

class Component extends SvelteComponent {
 constructor(options) {
  super();
  init(this, options, null, create_fragment, safe_not_equal, {});
 }
}

Alright, seems simple enough. What if I just write a very very very basic compiler that parses the DOM tree looking for Elements and then spits out the resultant JavaScript as it chugs along? If we merge all the compilation steps we avoid running through the file multiple times, a plus for performance. So I gave it a shot, and got something that produced exactly the same output, but only for the simplest cases. After, I realized that, while this approach would yield something very very fast, doing everything in one step made the program fairly difficult to change. I think I'd be better off sacrificing just a little performance in exchange for modularity. Let's shelve this attempt for now and try something more traditional.


Recommended reading

Lithe 1: The Motivation

Svelte is like Rust for me in that I had heard good things for years before I even gave it a try.

Svelte is like Rust for me in that I loved it immediately.

It's really very simple to write in, the basic idea is engaging, and after trying it I wanted so badly for it to succeed. For context I have professional experience with vanilla JavaScript, React, and Angular. After transitioning a small app from Angular to Svelte, here were my takeaways…

Lithe 3: A Rewrite

What if I just copied the Svelte compiler, written in TypeScript, changed all of the file extensions from .ts to .rs, and fixed all the bugs? It'd be a slog, sure, but at the end of the day I'd have a compiler that was very nearly the same, but presumably more performant.

This attempt I gave a real try, spending maybe three nights just chugging away. What I got was just more and more errors, which was fairly disheartening. I also realized just how different Rust is, and that a 1-to-1 rewrite would result in something that wouldn't be as ideal as it could be. For example, take this very simple TypeScript class…