Rink Web 2

August 7, 2020

I recently spent a few days working on a rewrite for Rink Web, as the old interface had not aged well and was very difficult to maintain. The tech it was built on is also fundamentally incompatible with my goals, which was to make Rink Web into a progressive web app (PWA).

Project Overview

The basic idea was to compile rink-core to Web Assembly and then write some type of frontend application in Typescript. I had not decided what framework I wanted to use when I started the project.

There were a few requirements I had for whatever framework I decided to use:

  • It needed to at least have a path forward for both supporting an offline PWA as well as supporting server side rendering.
  • I wanted to avoid webpack and create-react-app. These tools are very cumbersome, and when they break it's hard to know what went wrong. I could never get Web Workers to work with webpack, much less Rust.

Initially I'd started hashing something out using Parcel and lit-element. I like Parcel a lot because it kind of just works without requiring hours of tinkering with config files. However, the path forward with lit-element didn't seem great, it would be really hard to do anything other than a client-only SPA with it.

Once I had some basic frontend code hashed out, I started working on rink-js which is a JS binding to rink-core. I used wasm-bindgen for this and it worked out really well.

The PR with the changes can be found here. It has 79 commits, which added 12 000 and removed 3000 lines of code across 120 files.

About Sapper

I ended up using Sapper for the actual app, which is a frontend and backend framework that uses Svelte. Sapper's main focus is on building apps that support server-side rendering (SSR) seamlessly and hydrate the DOM client side instead of re-rendering the whole page. From using it so far, it does that really well.

Svelte is another reactive UI framework, similar to React and lit-element. It's a bit different from both of them though, in that it's actually a compiler that processes your components. Component files are named with a *.svelte extension and the top level is actually HTML rather than JS, so a basic component ends up looking like this:

<script lang="typescript">
  let count: number = 0;

  function handleClick() {
    count += 1;
  }
</script>

<style>
  button {
    background-color: rgb(200, 100, 100);
  }
</style>

<p>Current value: {count}.</p>
<button on:click={handleClick}>
  Increment
</button>

The website for Svelte has a lot more examples.

Sapper is a framework that takes advantage of the compile step involved in turning these component definitions into actual code. It actually compiles each component twice: Once for the client side, and once in a server-side rendering context.

It also has some opinionated views on how routing in a framework should work. It actually has you specify routes by having a folder src/routes/ where the file structure determines how the route will work. For example, the route /query/[input] corresponds to src/routes/query/[input].svelte in Rink.

Overall it still has some rough edges. At the time of writing, Typescript support in Svelte only landed 2 weeks ago. I ran into a lot of issues while developing Rink Web, but almost all of them I did manage to get past.

It also actually has to integrate with whatever bundler you use, due to being a compiler. As of writing, Sapper only supports webpack and Rollup. I went with Rollup for Rink.

I've been really happy with how quickly I can throw apps together using these tools, it's something I haven't really found with anything else. And as if that wasn't good enough on its own, I get SSR nearly for free, and don't have to worry about shipping a massive JavaScript blob.

This Blog

After releasing the new Rink Web, I went and redid this blog to use Sapper instead of Jekyll. Part of why I never write blog posts is that every time I want to, I have to install a huge pile of Ruby tooling, and it's always really painful to get working.

I actually lost the copy of the Git repo which had my most recent blog post before this, from 2018. I had to find an HTML to Markdown converter to restore it.

It took about a day to rewrite the blog tooling, and I think it was worth it. I get a lot more control over how it looks and things like Markdown processing.