Releases

Lightning Fast Headless Commerce with Vendure and Remix

Michael Bromley
Michael Bromley

Friday, June 9th 2023

Remix is a new full-stack JavaScript framework which focuses on web standards, modern web app UX, and which promises to help you build better websites. In this post we’ll explore how Remix is ideally suited to headless commerce.

First of all, if you don’t know the term “headless commerce”, it just means e-commerce applications where the storefront communicates with the commerce backend via an API. Vendure is one such “headless” server - it deals with all the product, order & customer data and logic, and the storefront interacts with it via its GraphQL API.

I’ve been aware of Remix for a while, but it was only after reading their blog post comparing Remix to Next.js that I really sat up and paid attention. I soon discovered that it could be an ideal framework on which to build a headless commerce storefront:

  • it supports server-rendering by default

  • it ships minimal Javascript to the browser, keeping initial loads fast

  • it has native support for prefetching to speed up page loads

  • it encourages graceful error handling

  • it runs on edge servers (more on this later)

In fact, I was so impressed with what I saw that I decided to make Vendure an official sponsor of the inaugural Remix Conf!

React made simple

As a React newbie, I wasn’t sure what I was letting myself in for - I’ve dabbled with Next.js, but I’m not afraid to admit that some of the more advanced uses of hooks still confuse me. I was really happy to discover that the whole design of Remix meant I very rarely needed to reach for anything more complex than useState!

For the initial proof of concept I had the help of a React-savvy friend to get things started, and after sharing my progress on Twitter I got some invaluable tips from Kent from the Remix team (shout out to Kent for his incredible work supporting and boosting the Remix community!)

https://a.storyblok.com/f/192301/610x425/68282a404c/kent-tweet.webp

After that I found I was able to move quickly, even with my limited React experience! The more notoriously complex aspects of building a React app - wrangling build tools, dealing with state management libraries - seem to be completely side-stepped by Remix’s opinionated approach to the app-building experience.

Effortless server rendering

E-commerce is the archetypal example of the need for server-side rendering (SSR) of web applications. Why? Because ensuring that search engine crawlers can read our pages is essential to driving traffic to our shop. Back in the early days of JavaScript web apps, we had some interesting solutions to this problem - anyone else remember using headless Chrome to crawl our sites and generate static HTML files? On the other hand, build-time static site generators like Gatsby can become difficult to scale to stores with hundreds or thousands of products.

Thankfully, most modern JS frameworks have some kind of built-in support for SSR. Remix is a great example of this. The server and client code exists in the same file and passing data from the server to the client is a matter of returning an object from the loader function.

Not only does this approach make your pages SEO-ready by default, it also allows you to limit the browser bundle to only that code strictly needed on the client. This can massively reduce the amount of JavaScript sent to the browser, significantly reducing load times and speeding up the storefront experience.

Bye-bye client libraries

Since Remix is a full-stack framework, it is able to load data directly from a database rather than requiring an HTTP API like most front end frameworks. I was curious to see how it would work with Vendure’s GraphQL API as a data source.

I was very pleasantly surprised to find that it works really well! I would usually reach for a full-featured GraphQL client with a normalized cache like Apollo Client or Urql, but by fully embracing the Remix way, plain old fetch worked perfectly. The usual issues of client state getting out of sync (which I typically solved with a normalized client cache) are solved by Remix’s method of revalidating any data that might have changed.

Not only does this significantly simplify data handling, it also completely removes the need to ship any kind of GraphQL client library to the browser!

Living on the Edge

Since a Remix app is both a server and a client application, we can’t just host it like a simple static website. It actually executes JavaScript when a new request comes in. So how do we host it?

One option is to run it as a traditional Express app. But due to the smart platform-agnostic design of Remix, it can run in any Node.js server like Vercel, Netlify or AWS Architect. Furthermore, it can run on non-Node.js platforms like Cloudflare Workers or Deno Deploy.

Cloudflare Workers is a particularly exciting technology - it allows you to run code at “the edge” - which means a network of servers distributed all around the world. So if a customer in Sydney visits your store, they will be served by a Cloudflare server right there in Sydney. Likewise in Vienna, Lagos, Seattle or any of the 250+ locations worldwide. This can dramatically reduce the latency of requests, making your storefront lightning fast (as you’ll see in the demo below!).

Show me!

Yes, the video above is in real-time!

The Vendure server is a default installation running on a $5 Digital Ocean droplet backed by SQLite. No special caching or performance tricks - just a completely vanilla install.

The Remix storefront is running on Cloudflare Pages. It feels like a static website, but it’s fully dynamic.

The combination of Remix’s performance-first design running at the edge really has to be seen to be believed. Try it for yourself!


Special thanks to Edo Rivai for doing the initial work on the Remix storefront repo - your React expertise got me started in the right direction! Also thanks is due to Conor Burns & Timur Dogan of 0xcb.dev who first got it running on Cloudflare Pages .