Sessions is temporarily moving to YouTube, check out all our new videos here.

Ladda: A New Library for Client-Side Caching

Gernot Hoeflechner and Peter Crona speaking at viennaJS in July, 2017
Great talks, fired to your inbox 👌
No junk, no spam, just great talks. Unsubscribe any time.

About this talk

Ladda is a library that used in production at Small Improvements to tackle caching. Watch what it can do, plus examples of why and how you can use Ladda.


My name is Gernot, this is Peter, we are coming from Berlin, working at a startup called Small Improvements. I am originally from Austria, that's why I asked Roland if we could check out what's happening in the JavaScript community in Vienna, and thank you for accepting us, and thanks for giving us the opportunity to talk to you. We want to introduce you to today to a client-side API caching library called Ladda, which is a project we've been working on at Small Improvements and which we've recently open sourced. We will structure this talk in the following way. First we talk about a naive solution to caching, and the caching problem in itself. Then we want to show you how you solve the problem of caching by using Ladda, and we will give you a couple of arguments of why we think that Ladda is a good idea. It might also be interesting for you to use. With that said, I give the word to Peter, who will introduce you to why caching at all. - Yeah, so actually the outline was slightly a lie, but for a good reason, because before jumping into the how it's important to consider the why. So why bother with caching? I mean there are many reasons for introducing caching, but the two ones that stick out the most for me are performance, improving performance, and saving data. So, we lost the slides. Thank you. Yeah, I'm a Linux user, not sure how to use this. So, we're ready for the how. How do we introduce caching, how do we build caching? So these four lines of code, it's actually everything you need. If it's not in the cache, put it in the cache, and return it from the cache. If it's already in the cache, just return it from the cache. So you might think this is a fairly simple piece of code, few execution paths, why not just use this? And I would say for a small project, it's totally fine to use this, it doesn't really matter much, you probably shouldn't use anything more complex. But in a large project, it becomes a bit more interesting. As the code base grows, this four lines of code tends to spread across your code base quite a lot. You often end up with a mess. So by introducing caching to your application, you often increase the complexity of your application. When talking about complexity, it's important to distinguish between accidental and essential complexity. So essential complexity is really complexity inherent to the problem you're trying to solve. So you can't really do anything about it, because you want to solve your problem. Accidental complexity on the other hand, that's something really nice, because that's your playground to apply all your creativity. That's something that you can reduce, and actually that's something that you should try to reduce as much as possible, because in one sense that's really what good code is about. You want to get rid of this accidental complexity so that the code communicates the solution to the problem you are trying to solve. So how would caching look in its ideal form? Well, it wouldn't look at all. It would be invisible, like on the right side here. So if you want to get the users for example, you would call get users, and yeah, that would be it. So let's look at these examples in a large code base. The first one you've already seen, but there's the slide again. And just three lines of code less, but it becomes quite a lot clearer in a large code base. So by switching to this shorter version, we reduce the application complexity. The only problem is that if you would do that directly, then you would lose the caching, which is kind of a bad deal. Of course you can simplify if you remove stuff. So how would all of this look with Ladda? How would you introduce caching with Ladda? Well, the application code actually is just a simple function call. So from reading this, you can't see that there's any caching going on. Ladda will just magically ensure that when you call this function then it will be taken from the cache if it should, or put into the cache if it should. Magic, that's kind of a key word for configuration. Unfortunately, that's the case in Ladda as well, couldn't get around that. So, Ladda exposes a build function, which takes a configuration object. This configuration object is really just a bunch of entity configurations, where each entity configuration needs to have at least an API specified. So how does the API look? Well, the API is just a bunch of API functions, where each function must return a promise. Probably they do some HTTP requests, so probably you already have this in your code. In addition to the function, you need to specify the CRUD operation that they are performing, because that's how Ladda can figure out what to do with the cache. Ladda puts some requirements on this as well, so every API function that belongs to a specific API, or is associated with a specific entity configuration, must operate on this entity. So for example, the user entity, you can't suddenly add a get course method in this, so you can't mix get users and get course but you need to just operate on one entity. So let's look at it all together. The application code, just normal function calls, some configuration, and decorate your hopefully existing API functions. A good question to ask is, did we actually gain anything here, or did we just move the complexity around? I would argue for that we did gain something, and that's the whole point. So this piece, this is for me a separate layer. And what do I mean with layer? Well let's look at it a bit differently. So, the circle part is the API layer. So the API layer is not allowed to have any dependency on your application, it doesn't know anything at all about your application. What this means is that as you develop your application, you don't have to care at all about the API layer, because it doesn't know anything about your code, so you can't really break it, whatever you do. The application, on the other hand, it has to depend on the API layer, because that's kind of the whole point, you want to use it. But remember, I showed you this piece of code in the application, which was just a normal function called get users. If you look at that piece of code, you can't really say if it's caching of it's just a completely normal API function. So it means that from your application code's perspective, it could have been without caching. So basically, we managed to introduce caching without raising the complexity of your application, because the code could be as well without caching. This is kind of an awesome thing, because it's a bit like having the cake and being able to eat it. Yeah, I mean I'm really excited about this, so it's a bit tricky for me to, it's hard for me to find words how to express how awesome it is, so I will just hand over to Gernot here to tell you about some of the benefits following from this. - Thank you, Peter. So from what Peter just said, there are really certain traits that follow as a consequence. Through the separation of concerns, Ladda is basically a quick in and quick out solution, which was something was very important for us when we edit this. So you can start to introduce it by just decorating a couple of API functions, and your application code can stay the same. The quick out part is just as important to us. If you want to remove it, you remove your decorations and Ladda is gone, but your application code can stay the same. A change of removing Ladda will not spread all across your application. Connected to this is that it's also framework agnostic. Ladda is basically just a wrapper around a bunch of API functions, a bunch of vanilla JavaScript API functions. So it doesn't matter whether you use it with Angular, React, Vue, whatever you want. This is actually something that is happening to us at Small Improvements, we have a large Angular code base there, which has now migrated to React, and we can now use this layer without having to deal with some kind of out of sync data state or something like that. As it's agnostic, both can just start using it. Ladda also offers you several other features of course. Every time you talk about caching, your enemy number one is stale data really, you need to invalidate your cache at certain moments, and Ladda offers you several mechanisms to do this in a declarative way. I show you one of these ways. We have here configuration that holds two different entities, one is an activity stream, the other is a user, and here we just, by adding this one line, we declare that every time something in the user changes we want to invalidate the activity stream, so you an think of an activity stream that wants to show that a user profile just got edited or something like this. This one declarative line will already do this for you, and will instruct Ladda to invalidate at the right time. Another important feature to us in Ladda is its plugin system. Basically everything in Ladda is a plugin. You can think of it as a reduce operation across several plugins, even the core functionality, the CRUD operations and the invalidation, they are already implemented as a plugin, and there are several more plugins already around, like a logger, a denormalizer, an observable plugin or bindings for React. But it could also be your plugin of course. It's meant to be extended, we want that the core stays slim and additional functionality is really provided through plugins, through extension. To document this a little further, what you can do with plugins, I want to present you one, which is my current favourite as well, it's the observable plugin. You can see here how our plugin is wired into Ladda, we just import this observable plugin and then pass it in an array of plugins to a second argument to Ladda's build function, and this plugin really patches every read operation, in this case, activityStream, which has a getLatest read operation, and adds a createObservable method to it. And this creates an observer to which we can subscribe, it's like a regular subscription API, also common in Args.js for example. You subscribe and get then a feed of activities that always is called and updated whenever something changes here in that respect. If we combine this, for example, with the Ladda React bindings, we end up with something like this. So withData is your higher order component from this package, and in withData we can specify what kind of data we want to provide to our presentational component. Here we say we want to observe something called user. The properties to this component contains a user ID and we can then say api.user.getById, and create an observable for this particular user ID. Our presenter in the bottom then, will just receive this user whenever it's ready, to be fetched, and now you have to imagine that there would be some kind of code editing this user, and in the end we can just call updateUser, and this update operation will then update the state for us, and through the observable we get really notified when it happens. This kind of means that we don't need to manage all this server side states on our client, which is a huge win, which typically contains a lot of boilerplate, it's very repetitive. This is kind of a workflow in a more visual way. We have our container, which is really this withData component that provides data to the presenter. The presenter triggers a change through Ladda, which is really just a layer on top of your API. We then can observe changes so that the container passes new data to the presenter and we have an actual visual change in the API. Ladda is also dependency free. It's a very tiny, tiny framework, not framework, library. Very tiny package, and really shouldn't bloat, your probably already quite large JavaScript application. It also has 100% test coverage. We know this is a little bit of a feelgood number, but we also kind of tried to really write good tests, because if this part in your system breaks, you are probably in trouble, so Ladda has a test ratio of 1:2.5, so a lot of tests, really. Another good reason is that this is a library which is actually used somewhere, so it's not just like our weekend project, fun, side project, it's really built to solve a real-world problem in a real-life application, and there's a whole team maintaining this little library. With that said, we hope you got some idea what Ladda is, and let's quickly summarise the key points again. It's a client-side API caching library, and it allows you to introduce caching without really raising the accidental complexity in your application code. At its core, it's just one build function that takes a configuration and returns you a bunch of decorated API functions. The key principle is that it has a quick in and out, so you can just start to gradually include this in your application without necessarily changing stuff all over the place. And it's heavily built with a plugins-first mentality. It's not meant to solve everyone's problem, but it's meant to provide you with tools so that you can solve your own problem in some kind of good way. Plugin API is also richly documented. That's it from our side. Thank you for listening, you can learn more and also just try it out by going to our ladda-js organisation, where you will find a fairly rich documentation and several example applications that show you in action what's happening here. There is of course also a next release coming soon with further goodies. Thank you again.