Code Splitting in Alpine.js
I've recently published a library called Async Alpine that adds asynchronous or lazy loading of components to Alpine.js! It can help you write faster, more efficient sites using Alpine.js. Check out my Async Alpine blog post for more info!
How I use Alpine.js
x-data attribute of your component. This is great if there's not a huge amount going on, but you can't import other libraries or transpile modern syntax, and it lacks the syntax and formatting help that writing in
.js files provides.
For these more complex components, you can write them as a JS function and declare them with
I tend to write basic components inline but use JS components for anything with more than a couple variables/methods.
Recent tools like Astro and Slinkity take this a step further, allowing the developer to specify when a component should load. In many cases few users will ever scroll down to see a component at the bottom of a long page. We may want to load a component like that only when a user scrolls down far enough to be likely to view it.
Custom implementations have existed for a while, but these tools are the first I've seen to bring it to modern component-based JS libraries.
Alpine component loading
Back to Alpine, when they declare components with
Alpine.data() people often bundle them into a single JS file. Alpine needs to register components before it runs, meaning the easiest solution is a single bundle and we definitely don't have the fine control like with Astro/Slinkity. This is back to our issue with loading code that might never be used.
Code Splitting in Alpine.js
One way we can handle loading components asynchronously in Alpine is by taking control of when Alpine runs components. When it starts Alpine scans through the entire DOM and finds elements with the
x-data attribute and runs them. If we rename
x-data to something else in our code, then Alpine won't see and run it.
We'd need to consider the other Alpine attributes like
@click and a handful of other Alpine functionalities.
Once we've renamed those attributes and Alpine has started, we can control when we add the components again. We load the component when we'd like to based on certain conditions, use
Alpine.data() to prepare it and then rename the attributes back again. Alpine will pick up on the change, see the component and run it as normal.
With that we have a lightweight way to load components on-demand!
That's a minimal setup that does the basics, but we could go a lot further to add different loading strategies and to support the standard Alpine syntax. I've done that work and released it as a library called Async Alpine!
I've written another post focusing on it more—Async Alpine — Asynchronous Alpine component loading—and you can find more info about Async Alpine on GitHub
It came out of wanting Astro/Slinkity style loading for Alpine components, and I've been working on it the past couple of months. With more control over component loading I could build faster, more efficient websites without changing the syntax of a library I was familiar with. It has advanced loading options including immediately, on idle, when visible, using a media query, DOM events or any combination of those.
It's still in development and will need more testing before I'd consider it stable, but I've used it on several production websites with great success. If you're familiar with Alpine I'd encourage you to give it a try and see how it works for you!