Construction zone street sign

How to add a progress bar to Shopify Hydrogen

March 28, 2022

Shopify's Hydrogen framework is currently in open beta and I'm working on a proof of concept to rebuild a site that's currently a React/Liquid hybrid for a large Shopify Plus retailer.

While building I noticed that there was no indication when you navigate from one page to another. Since Hydrogen is mainly server-side rendered with the awesome power of Vite, there is still a noticeable delay between when the user clicks a link and when the page refreshes. Without any feedback, the site feels sluggish. The Hydrogen team is on the task, but for now, there's a simple workaround that will be ok for most pages that don't rely on slow data fetching. It might not be obvious how to build it so I thought I'd write a quick post about it.

Create a progress bar component

You'll want to place this progress bar in a component that renders on every page. Something like App.server.jsx or Layout.server.jsx. Shopify provides a way to find out if the server is currently doing some work to render your components using the useServerState hook. But you can only use that hook in .client.jsx components.

So the first thing you need to do is create a client component, call it Progressbar.client.jsx and import the hook there. Add some simple Tailwind CSS styles (comes bundled with Hydrogen by default) and you have a decent start for a progress bar. I followed this quick blog post by Katsiaryna (Kate) Lupachova and adapted it to Tailwind. I also changed the progress bar background to be the colours of the Ukrainian flag 🇺🇦 Unless you want to show support for Ukraine simply change the background gradient style to match your site.

Progressbar.client.jsx
import { useServerState } from '@shopify/hydrogen/client'

export function Progressbar() {
  const {pending} = useServerState();
  return (
    <div className='absolute z-50 top-0 h-1 w-full bg-transparent'>
      <div 
        role="progressbar" 
        className={`
          h-full 
          ${pending ? 'w-full bg-gradient-to-r from-yellow-400 to-blue-500' : 'w-0'} 
          transition-[width] 
          duration-500 
          ease-in-out
        `}/>
    </div>
  );
}

Note that the above is a very primitive progress bar. It doesn't truly indicate progress, but the 500 ms transition duration makes it feel like it does as most pages should load within that. You can experiment with the duration if you have slower page loads.

Now all you need to do is import and use this component in one of the components that load on every page.

Improvements

As noted above this progress bar is very primitive. Adding true progress is fairly simple but the current Hydrogen implementation doesn't provide enough information to implement it yet.

The Hydrogen team is also working on a better way to show progress or otherwise improve page transition UX, so this blog post may soon become obsolete. But until then, I hope you've found it useful.