What’s next for Hydrogen
October 31, 2022
The February ‘23 release of Hydrogen will bring significant advancements in developer experience and performance, and a suite of new tools specific to Shopify storefronts. Much of what’s unlocked is thanks to leveraging Remix (now a part of Shopify!) as a foundation to our stack.
Today we’ll dive into the four core changes coming to Hydrogen: data loading, routing, error handling, and mutations.
Each month, we’ll provide more details around what you can expect from Hydrogen 2, including a newly built demo store that takes full advantage of our improved architecture and expands the example set to a broad range of advanced features.
Here’s a quick look at some of the exciting advancements coming to Hydrogen 2:
- Optimistic UI: Improving perceived performance dramatically by instantly reflecting user interface updates after an interaction (e.g. adding to cart)
- Nested Routes: Only re-render the parts of the page that need to change when shoppers browse your site, further improving performance as well as enabling encapsulated error boundaries in case things go wrong.
- Progressive Enhancement: Enabling Hydrogen sites to function well without JavaScript brings a number of benefits: to SEO with better crawling, to accessibility with better screen reader support, to user experience especially on mobile and low powered devices, and to performance with interactivity becoming possible before the page hydrates.
- Drop-in Pagination: Making it easy to handle cursor-based pagination with GraphQL. Including built-in support for infinite scrolling, scroll restoration, history management (i.e. not breaking the back button), memory management and garbage collection—all with peak performance.
- Improved Technical SEO: Enabling simple configuration and robust support for all critical metadata, including improved sitemap and product feed support, as well as improved crawlability for all engines and user agents—so all of your links look great in search, shared on Twitter, posted in Slack, and DM’d in your group chat.
- Performant Pixels: Simple handling of third party analytics pixels without impacting performance, and upcoming support for the Web Pixel API.
- Improved TypeScript Support: Improved types for all Hydrogen components and queries, added type support for the Storefront API, and further improvements to IntelliSense support and VS Code tooling.
- Incremental Adoption: We’re improving support for incrementally adopting Hydrogen from the Online Store when using Oxygen, making it easier, faster, and more secure with improved scale and bot protection.
- A lot more Shopify: admin redirect management built-in, discount links, B2B, Search & Discovery, Shop Pay Installments, subscriptions, and so much more.
Our Goal
Created as the missing developer toolkit for next-generation headless commerce on Shopify, Hydrogen was designed to let developers focus on building, instead of plumbing; providing a strong foundation that leverages the best in edge-computing, and embraces the web platform and the server/client model.
We built Hydrogen because we believe that end-to-end integration throughout the entire stack can unlock a step change in how developers build dynamic, personal, and performant storefronts—taking full advantage of Shopify’s global scale, shopper network, and integration partners.
The First Quarter of Hydrogen
Hydrogen launched our first general availability release at our recent Summer Edition to a resounding response, with thousands of developers now building storefronts on Hydrogen. Since then, we’ve made big improvements to the developer experience, performance, and capabilities of Hydrogen; with a number of quality of life improvements and new features. Our community has been contributing too, with a special shout out to Kevin Carrabine for bringing provider mocking to Hydrogen.
With a number of merchants now live at a global scale, we’ve also been able to gather some incredible real world feedback; with a focus on furthering the advancements we’ve made on developer experience and performance, and going much deeper into the commerce toolset.
Remixing Hydrogen
We first met the Remix team in 2021 to start talking about how we might collaborate. We were using React Router in Hydrogen (also made by Remix), but we were unable to leverage it properly with our implementation of React Server Components.
This May, we gave a talk at Remix Conf announcing Hydrogen UI—a package we’re building to bring the best parts of Hydrogen to other frameworks like Remix.
Today, we’re excited to announce that Remix has joined Shopify! Sharing all of the same design principles and philosophies, and supporting a number of the key technologies we were looking to provide in the Hydrogen stack—we’re excited for all of the ways we’ll be able to bring the best of both worlds together in the coming months.
For those using Remix for other projects, Remix will remain an independent and open source framework, joining a number of other OSS initiatives at Shopify—now able to be even more ambitious in pursuing our shared aim of pushing the web forward. You can learn more on our engineering blog, and on Remix’s blog.
Upcoming Changes, Motivations, and Proposed Designs
Leveraging Remix, Hydrogen will be going even deeper into the storefront toolkit, unlocking a number of new capabilities—some of which we mentioned up top and will be sharing more about soon. It will also help improve some existing parts of Hydrogen that are core to performance, productivity, and fun. Today we’ll dive into a few key challenges we’ve heard from developers and faced ourselves, and how we’re aiming to tackle them moving forwards; specifically:
- Data loading
- Routing
- Error handling
- Mutations & State
If you’re building on Hydrogen today and wondering what this means for you, we expect that more than 90% of your code will stay the same, with provided guides and tools to help with the rest. Below we’ll get into the core changes that are coming, the motivations behind them, and our planned designs.
Data Loading
When Hydrogen was announced in 2021, we talked about our bet on React Server Components, and the promise we saw in a better division of labor between server and client, as well as the opportunities RSC created around code co-location and composability.
While we’re excited for the future of RSC long term, as a critical dependency, it presented a number of challenges that became performance risks for our developers, and bottlenecks for our progress.
With Remix, we’ve been able to realize the same design principles and goals we set out with, achieving both fresh and fast data by leaning into edge computing and modern server caching strategies. The core difference is in moving our queries to route-level data loaders that run on the server instead of React Server Components.
We’ve found that keeping a clear separation around where your server is doing the work, and worrying less about how your server and client components might mix together, has resulted in a simpler developer experience that’s less prone to mistakes. We also heard from a number of developers that with most of their pages requiring some level of interactivity, the mental model of routes in a .server file, with interactive components in .client components became repetitive and error prone.
Here’s a quick look at how this pattern looks in action compared with RSC & useShopQuery:
Queries Today
import {
useShopQuery,
CacheShort,
useRouteParams,
useLocalization,
gql
} from "@shopify/hydrogen";
export default function Product() {
const {handle} = useRouteParams();
const {language: {isoCode: languageCode}} = useLocalization();
const {data} = useShopQuery({
query: gql`
query Product($handle: String!, $language: LanguageCode) @inContext(language: $language) {
product: product(handle: $handle) {
id
title
}
}
`,
variables: {
language: languageCode,
handle,
},
cache: CacheShort(),
preload: true,
});
const {product} = data;
// ...
}
Future Queries
import {json, useLoaderData} from '@remix-run/oxygen';
import invariant from 'tiny-invariant';
import {CacheShort} from '@shopify/hydrogen-remix';
export async function loader({
params: {handle},
context: {storefront, language}
}) {
const productQuery = storefront.query({
query: gql`
query Product($handle: String!, $language: LanguageCode) @inContext(language: $language) {
product: product(handle: $handle) {
id
title
}
}
`,
variables: {
handle,
language,
},
// New: Optionally filter your data before it is returned from the loader.
filter(data, errors) {
invariant(data.product, 'No product found');
return data.product;
},
cache: CacheShort(),
});
// You can also shape your data here prior to returning it to the route.
return json({
product: await productQuery,
});
}
export default function Product() {
const {product} = useLoaderData();
// …
}
This strategy now makes it easier to manipulate your data to fit your desired shape, to filter out problematic requests and provide more helpful error messages, and to safeguard against performance issues like request waterfalls. Remix removes the need for most providers built in Hydrogen, making global state management easier, and preventing re-rendering gotchas.
We’ve been in close collaboration with the React core team since we began, and we’re looking forward to what RSC will mean for our partner ecosystem in the future. However, based on the feedback we’ve had from developers on Hydrogen today, and the challenges they’ve faced in production, we believe that Remix’s data loading pattern provides the ideal solution for the performance and resiliency of our merchants’ websites.
Routing
With React Router not supporting RSC in Hydrogen, we ended up implementing our own declarative and file based router; with a declarative API similar to React Router’s, and a file-based API similar to Next.js, and added support for dynamic request routing on the server.
While there were some exciting opportunities our solution opened up, it critically missed granular error boundaries and nested routing. This meant that it was hard to contain errors in your code to their component, if a server component failed to fetch or render data. It also meant that page to page transitions relied on caching and prefetching to feel fast; but the entire page would need to be sent over the wire and hydrated each time, not just the parts that changed. Lastly, while we liked the ergonomics of the declarative router, it became confusing to have two sources of truth for what defined your routes and we saw most developers lean solely on file-based routing.
Remix’s router introduced an innovative approach to nested routing, and an upcoming API supporting React 18 Streaming that complemented Hydrogen’s with a simple way to prioritize your streaming data. While there are a couple of syntactical differences in how you name your files, they mostly follow the same logic, with Remix adding a number of nice benefits on top.
Routing Files Today
src
└── components
├── Layout.server.jsx
└── NotFound.server.jsx
└── App.server.jsx
└── routes
├── index.jsx
├── about.server.jsx
└── collections
├── index.server.jsx
└── [handle].server.jsx
└── products
├── index.server.jsx
└── [handle].server.jsx
└── index.server.jsx
Future Routing Files
app
├── root.jsx
└── routes
├── index.jsx
├── about.jsx
├── collections
│ ├── index.jsx
│ └── $handle.jsx
├── products
│ ├── index.jsx
│ └── $handle.jsx
└── $.jsx
With the “root” route, there’s a more intuitive way to provide a consistent layout component for the shell of your website; and a catch-all route with “$” means pages like your 404 get a dedicated place in your file structure instead of being referenced inside App.server
Here’s a stripped down look at how nested routing works in the context of a product listing/collection page:
root.jsx
import { Outlet } from "@remix-run/react";
export default function Root() {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body>
<Header />
<CartDrawer />
<main>
<Outlet />
</main>
<Footer />
</body>
</html>
);
}
First up we have the root route, in this basic example it’s used as the layout for the site. The key component to Nested Routes is the <Outlet />. That’s where every child of a parent route will be rendered, and so as you navigate between pages, only the parts of the page within that Outlet will need to re-render.
In this example, a shared header, cart drawer, and footer stay as is. Now let’s look at the Collection page itself.
collection.jsx
import { Outlet } from "@remix-run/react";
export default function Collection() {
return (
<>
<Sidebar />
<Outlet />
</>
);
}
A common pattern for collections is having a sidebar where you may want to sub-navigate by product types, or filter by colors or sizes. As your user clicks on new filters, we want to change the list of products and any differing marketing material — but we don’t want to re-render either the global navigation sections, or this new sidebar, so we’ll add another outlet component.
Now, the actual collection page itself is only responsible for the product grid, pagination, and any additional marketing content… and with the upcoming pagination components from Hydrogen, that now becomes dead simple to get right.
Error handling and loading fallbacks
Now, if something goes wrong, you want to contain the issues as much as possible, and provide helpful messages that turn a potentially negative customer experience into a positive one.
Thanks to nested error boundaries only the parts of the page related to the issue will respond differently—everything around it works as you’d expect.
With robust support for linting, TypeScript, and unit testing, Hydrogen makes it much easier to spot bugs before they ship… but mistakes are a reality of development. Error boundaries allow you to craft each message and fallback UI for individual parts of each page related to distinct fetch requests, and allow you to craft the message for whatever status code you want to throw.
When you combine this with the upcoming Streaming support and defer API and the ability to get data from parent routes without Providers—things get very powerful without getting complicated. For example, let’s consider our collection page and assume that the desire we’re after looks like this:
You may have queries to the Storefront API for product, collection data, and the customer account; a query to another provider for search; and a query to a CMS for your marketing banners. Today, if any of those queries went wrong, or if you made a mistake in how you handled data, you could end up with a page like this:
Now with React Router’s Streaming and Nested Route error boundary APIs, you can granulary configure each of the different parts of your app, all with different caching options.
Getting creative, we could silently fail if the Wishlist Banner returns an unauthorized header, or fallback to an evergreen piece of creative if the CMS’s marketing banner isn’t returned in time. If the shopper came from a link to an old collection that you’ve since taken down, you might even want to respond by recommending related collections or products instead of a 404.
With the upcoming features of Hydrogen, you can make sure that there are no dead ends on the path to purchase and provide highly dynamic experiences.
Mutations & state
The most important pieces of building a high converting storefront are in ensuring that the purchase path is as performant as possible, that shoppers can easily pick back up where they left off, and that they can easily share links with their friends when they want to recommend a product. And yet, they’re some of the hardest things to get right.
While we’ve added features like a RSC-based mutation API and a Form component, they’re not as full featured as we’d like, and since it’s such a new concept it can be confusing to understand how they work. Interactions with a server need to complete before the shopper can see an update, making it challenging to work with the cart. Setting and parsing the URL for a collection page can also be a challenge when it comes to implementing cursor based pagination and infinite scrolling; especially if you want to make it work without requiring JavaScript.
Remix’s useMatches, useSearchParams and useFetcher are incredibly elegant and powerful ways to revalidate data on the server while keeping the URL the source of truth.
In the upcoming Hydrogen cart, not only will all actions move to the server, removing client-side JavaScript, but it will also support Optimistic UI making add-to-carts feel instantaneous.
The Hydrogen Pagination component will provide simple and flexible APIs for working with paginated Storefront API queries like product grids, search results, and order history. Setting up infinite scrolling on a collection page will finally be easy to do well—the URL is updated for you automatically, while keeping the back button and scroll restoration working properly, so when you click into a product and then swipe back, you’re right where you left off. If you share the link with a friend, they’ll even land on the same grid of products you’re looking at when you stopped scrolling.
The Future of Hydrogen
Stacking on top of Oxygen, along with the Storefront API and Shopify’s CDN, every core part of your Hydrogen app is served at the edge—as close as possible to your customers, no matter where they are around the world. Not only does this mean your website will run as fast as possible, but you’ll also be able to provide deeply personalized experiences to your customers.
From proactively answering “where’s my order”, to auto-selecting and filtering for the right size, to integrating with CDPs and experimentation platforms for a truly personalized experience; Hydrogen will unlock brand new frontiers of ecommerce.
In the coming weeks and months, we will continue to release details around how Hydrogen will evolve to leverage Remix. Hydrogen will go even deeper in supporting the unique behaviors and requirements of commerce, focusing on performance and best practices—making the easy way the right way.
From there, we’ll be making major improvements in how Hydrogen integrates with Shopify, the ecosystem, and powerful platforms like Shop. We’ll take all of our learnings from the various ways developers integrated services into builds to make it painless and performant for merchants and app partners to create seamless storefront integrations.
By removing more and more of the undifferentiated heavy lifting of commerce, we want to enable every merchant and every developer to focus entirely on what makes their business and shopping experience unique and exciting.
This is just the beginning. We’re designing Hydrogen to adapt and evolve at the pace of the internet while providing an intuitive and fluid experience, unlocking new categories of opportunities on the web and beyond.
Get building
Spin up a new Hydrogen app in minutes.
See documentation