I Tried to Build a WebApp Without Spinners & Loaders Using Replicache

Is Replicache the Future of Web Development? Was it good? Let’s find out!

Fernando Doglio
Bits and Pieces
Published in
9 min readDec 12, 2022

--

Photo by ThisisEngineering RAEng on Unsplash

When we’re building web applications, there is usually one constant: waiting time.

It of course depends on what you’re building and how much interaction you have with other systems or the back-end of your app. But whenever you’re sending data out from the client, you usually, have to wait and that wait tends to translate into some kind of visual indicator to your users (be it a progress bar, a loading icon, a spinning wheel, you name it).

Replicache, on the contrary, claims you can build a full web application, without the need to deal with those waiting times.

Not only that, but as an added bonus, Replicache-based applications are supposed to work great for collaborative actions, like having your UI update based on what other users are doing.

In this article, I’ll try Replicache and let you decide for yourself if it is what you need for your next app or not.

So what is Replicache?

Replicache is a framework that allows you to connect your data model and your UI with a back-end that takes care of handling data transactions.

That “handling” translates into your UI being completely aware of what’s happening after every action taken by any user, and it does it all through what I can only assume, are sockets.

This means they deal with data transfers and updates much faster than you’d normally be able to do through HTTP. Thus eliminating the need for any kind of waiting indicator.

Actions like saving a new record, will happen instantly and the UI in charge of listing the records, or even displaying new ones will automatically be notified. So any user who needs to be aware of it, will receive the update.

How easy is Replicache to use?

Well, that’s a tricky one. In this article I’m going to show you how you can interact with their code and add new features to an existing app.

That said, while the premise of instant-updates sounds fantastic, doing it requires a bit of an infrastructure that normal web apps don’t have. That means that if you’re thinking about integrating Replicache into your existing application, you’ll probably have a hard time doing it, because you’ll have to refactor all your business logic.

If on the other hand, you’re looking to get started from scratch, then getting started with one of their templates might be a good idea.

At least so you have the basic infra in place, and then you can grow the app in any direction you want.

As you’re going to see in a minute, we have to incorporate the concepts of transactions and mutators into our logic, and if you’re not already dealing with those, then your back-end code might get affected.

Let’s see what it would be like to add a new feature to an existing Replicache-based application.

Getting started with Replicache

For this example, I’m going to use the pre-built to-do app, and for that, all we need is the following line of code: npx degit rocicorp/replicache-todo my-todo-app

Once the folder is created and the files are ready, the next step is to install dependencies with the good old npm install from within the new folder.

With the standard steps out of the way, the next thing is to get a license key. Don’t worry though, you don’t have to sign-up through their site or anything. Unless you’re looking to create a massive app and yo work for a very big company, you can use Replicache for free.

In our case, all you have to do is run the following command: npx replicache get-license

That command will ask you a couple of questions, like your name, your company’s name and an email. And as a result, you’ll get the actual license key.

You’ll have to export that value as an environment variable called NEXT_PUBLIC_REPLICACHE_LICENSE_KEY . You can export it with the export command before starting the app, or you can create a .env file in the root of the app, and let Next read it (which it does by default).

By now, you have a working To-Do app that looks like this:

This app lets you:

  1. Create new tasks
  2. Mark them as “done”
  3. And delete the tasks.

You can also filter by status. That said, we’re going to be adding the ability to track how much time you’ve been working on a single task.

This is what the end result will look like:

So let’s get coding!

Updating our data model

The first thing we want to do, is to update our data model. This is partially because our app is using TypeScript and partially because we now have to start thinking like we’re dealing with a SQL database. Every time we want to change the structure of our models, we’ll have to update the model’s definition. Because every time we’ll want to do any operation with our data, we’ll have to turn it into a transaction around it.

The model we want to change in located in the src/todo.ts file. And by default it has two types defined: Todo and TodoUpdate

Since we’re looking to record how much time we spend working on a task, we’ll have to record every time we start and pause working on it. The UI will let us do it through a Play/Pause button that we’ll add, but the data model doesn’t support this as of now.

So we’ll have to modify the Todo type to add a list of start/stop events. We’ll also add a field indicating our first ever working event, to power the “… since…” part on the above screenshot.

With all of that, the new data model looks like this:

This is what I added to the Todo type:

  • workingOnIt is a boolean attribute that we’ll use to quickly understand if we’re working on this task or not.
  • workingWindows is going to be the list of start/pause events I mentioned before.
  • startedOn is going to have the first time we ever started working on this task.
  • currentWorkingOn will contain the starting timestamp of the current working window. Once we pause it again, we’ll use this value as the init attribute of the new window.

And of course, the WorkingWindow type will only contain the starting and ending timestamps of a specific working period.

Let’s now go to the other side of things and look at the UI changes that we have to implement.

Did you like what you read? Consider subscribing to my FREE newsletter where I share my 2 decades’ worth of wisdom in the IT industry with everyone. Join “The Rambling of an old developer” !

Updating the UI

Before we dive into the actual logic to implement, let’s look at the UI, which will determine exactly what we need from our logic.

These images show you how the UI is changing. We need to add the message underneath each task, yes, but we also need to add the “play” and “pause” buttons next to the “X”.

All of that will be done on the src/components/todo-item.tsx file. You can look at the full source code of this file here, but the following is an extract of it, with the required added code:

You can see on line 10, the new “Play/Pause” button is using the workingOnIt attribute to determine which class to use.

And then on line 13, we add the message, which also depends on whether the workingOnIt flag is set to true or false .

Now this gives us 2 more functions: workingTime and toggleWorkingOnIt . The first one is simply iterating over the tasks’ workingWindows and adding the time difference between init and end . It’s just VanillaJS and you can read the full source code here.

But the toggle function is what we care about, because it updates the data, which means, we interact with Replicache.

This is what it looks like:

That’s it, just one line, we call the onWorkingOnIt function and we pass an object with an id and the attribute we’re looking to update.

But wait, where is the onWorkingOnIt function coming from?

Let’s take a look at the business logic.

Writing the Replicache-based logic

That function, onWorkingOnIt is received as a prop on our component and is coming all the way from the src/app.tsx file. In that file, we define several functions that then get passed down through the component tree.

So let’s take a look at what that function looks like:

As always, you can read the full source code here.

This function can do one of two things: we can either start working on a task, or pause our work.

If we’re starting to work on it, I’ll first check if I have the startedOn attribute set, if it’s not, I’ll set it and move on. Notice I did call the isStarted mutator method. We’ll look into them in a second, but just know that those are methods that query our data.

I’m also saving the current timestamp inside the currentWorkingOn attribute of our task. That value will be used later on when we stop working on it.

Now, what happens if we’re pausing our work on a task? Well, we need to create a new working window (using the value we previously saved inside currentWorkingOn ) and we need to add it to the list of working windows.

The problem with that? This toggle function we have doesn’t receive that information, instead, we need to query our data. Lines 11 and 12 take care of that.

We finally update the data on line 19, with the call to updateTodo .

Writing mutators

While the toggle function does all the interesting things, we’re still dealing with some Replicache magic when we have to interact with the data storage layer.

We do that through mutator functions, and they’re all located inside the src/mutators.ts file.

In my case, I’m adding 3 new read-only functions that look like this:

They all do pretty much the same time, they get the actual Todo through the tx.get method, and then they return the required attribute. You can take a look at the rest of the mutator functions here.

Just know that if you have to query the data or update it somehow, you’ll have to define your mutators here.

And the end result looks like this:

I know the example looks like I skipped over some parts, but I didn’t. Once you have a working application with Replicache, like the Todo app of this example, adding more logic to it, is quite easy!

And the results are remarkable.

What did you think about it? Will you try it on your next app?

Build apps with reusable components like Lego

Bit’s open-source tool help 250,000+ devs to build apps with components.

Turn any UI, feature, or page into a reusable component — and share it across your applications. It’s easier to collaborate and build faster.

Learn more

Split apps into components to make app development easier, and enjoy the best experience for the workflows you want:

Micro-Frontends

Design System

Code-Sharing and reuse

Monorepo

--

--

I write about technology, freelancing and more. Check out my FREE newsletter if you’re into Software Development: https://fernandodoglio.substack.com/