How we built Hydrogen, a React framework for building custom storefronts
shopify.engineering
shopify.engineering
To me, though, especially with hooks, React creates a bizarrely deep object tree that is impossible to reason about in comparison with pretty much every other tooling that exists.
- a cheap developer
I can’t stand it and find all the promotion on it to be promising far more than it delivers. It’s heavier, slower, less comprehensive, and less comprehensible than either Vue, Svelte, or most Vanilla JS implementations of component-oriented sites that I’ve seen.
Every single thing about React bothers me, from hooks to JSX (which is so much worse than meaningful templates), and I’d rather use something that makes me happy.
On the rest of it, I’d agree that a lot of the JavaScript-based pure templating languages don’t really work well, but IMO that has more to do with JavaScript than the templating languages. I find EEX (Elixir), ERB (Ruby), and Jinja (Django-ish, plus others), Liquid (Ruby / Shopify), and Text Templates (Go) to all be pretty good for what they do — and most of them are templating languages that can be applied to HTML, but are not HTML "native" templating languages (even though some have HTML "native" variants, e.g., HTML templates for Go).
Millions of people and companies do. For mostly one reason: Getting started is incredibly simple. React's surface area is incredibly narrow. Almost anything in it is just JavaScript. Hooks or Classes? Syntax inside JSX? Just normal JavaScript. With hooks, there are basically two that can do 99% of what you want to do.
> which is so much worse than meaningful templates
Why? There is a zero bullshit approach here. No magic syntax. No "v-for" or two way binding. No receiver patters or context parameters.
Amen. I have zero interest in learning Yet Another Template DSL ever again. React won the framework wars because it's just javascript.
Create react app drags in about a million dependencies, and I’ve never met somebody able to make a react app work without it. That’s not “simple” in my book, create-react-app is a tool that so many people are dependent on that it deforms a lot of architectures to avoid having to modify it, using proxies etc
How so? You just need to call createRoot and you have react working.
The reason why people use CRA is that it comes with all the tooling required for modern webdev, such as webpack, babel, eslint, prettier, jest, etc pre-configured for you.
Setting up all these tools takes quite a bit of time, but that's not react specific. You would want those same tools for any frontend project regardless of react.
I’ve done react “from scratch” with manual configuration of the build toolchain, without a builder or template app (there's a lot of each around, CRA isn't the only one.)
It's not particularly difficult, but there's no payoff (in any real world use case I’ve had so far) for the extra work.
JSX is 1,000% magic syntax, and anyone telling you otherwise is trying to sell you something.
It looks, feels, and acts wrong in ways that Svelte or Vue templates (and most other templating systems) don’t, to me.
And the whole thing about hooks is a punt from the developers of React saying that they couldn’t figure out a more humane way of smartly figuring out reactive dependencies. The whole trick of figuring out why you have an update loop (and specifying those dependencies) is work that the tooling should be able to figure out for me. What use is one-way binding if I have to specify my update dependencies at least twice in every hook (once in the hook logic and once in the dependency list)?
And you’re right: React’s surface area is narrow, which does not justify the framework’s bundle size or it’s painful developer semantics. Both Vue2 and Vue3 provide more than React does with bundle sizes that are ⅔ as large. Svelte’s runtime, when needed, is even smaller. What excuse does the React team have for causing so much lost developer productivity and wasting bundle sizes? At least Preact has the excuse that it’s a much smaller runtime bundle.
I look at React code and I see cries for help from people stuck in an abusive relationship with their development tools, when there are so many better choices out there. Including plain old vanilla JS (which is increasingly an option from my perspective).
That said, I’d much rather deal with React than Flutter and Dart any day. React still ultimately compiles to real components for the platform, whereas Flutter can’t even pretend to be a good citizen of any platform.
Your entire argument is arguing for React, not against it.
It makes no sense that you complain about magic then ask why dependencies need to be passed into hooks. How do you think other libraries avoid that quirk? Magic. Computed properties in Vue are opaque build time magic. Templates are build time magic. React is the only library that doesn't have build time magic that you need to treat as a black box.
> It looks, feels, and acts wrong in ways that Svelte or Vue templates (and most other templating systems) don’t, to me.
My biggest example of this (and it drives me crazy) is when mixing Typescript generics in TSX files: you often have to do ridiculous boilerplate like `<T extends any>` because otherwise `<T>` would be recognized as JSX and blow up the syntax tree. Hoorah for the context-sensitive grammar.
Typescript is what "No magic syntax" looks like: all it takes to get usable javascript is to parse the TS AST, remove the TS specific nodes, and serialize the tree back to text. There are a few exceptions like enums but they're not core features and you can go your entire career without needing them. Meanwhile the JSX ecosystem is full of crap like emotion and styled-components that need babel plugins to support features like component selectors. SMH
IMO, Vue 3 has made a mistake buying into the whole hooks nonsense, and I find it less usable than Vue 2. On the other hand, Vue 3’s implementation is more comprehensible than React’s.
Idk, I found the svelte reactivity model a little confusing.
After working for a few years in reactive frameworks like Vue and Svelte, I feel I am longing for the simplicity of React now.
Vue really got it's act together in many ways from very start. Single file components are super ergonomic. I don't feel React ever nailed that with at least 10x different solutions. That and global state with VueX is so natural compared to, again, 10x different solutions in React.
Vue is a delight in many ways. I'm just currently seething over some issues I had with it's reactive state - and that's where I'm really siding with React. I could go on but I know it's a total rant.
In many ways, Svelte 3 feels like what Vue 3 should have been. The whole way that hooks works feels ugly and inelegant.
Same thing any time WordPress does anything notable.
Teams make tech decisions based on multiple factors. Sometimes the ones like "bizarrely deep object tree that is impossible to reason about" are found to be less important. Because at the end of the day websites are for the wider public audience, who aren't affected by bike shedding
I agree with you about jQuery. It had its place. It’s painful to encounter now, especially since it can screw up any other framework that you want to put into a website.
The components I work on and write are all narrow in scope, self-contained and completely testable with no crazy side effects + minimal global scope.
The easy path on React is small functional components.
You can upgrade a 7 year old React app with very little fuss. Unfortunately, you cannot say the same about Vue or any of the modern libraries. They also have no track record to indicate they will exist 10 years down the line, but I'm pretty sure my React apps will still be fine.
That being said, I'm very excited about SolidJS[1] and the other modern libraries that use JSX.
I’m exceedingly unexcited about anything that uses JSX, which is a blight on the landscape.
My life has been made a lot easier since I ditched Webpack for Vite. Faster build times, way less complexity, cleanly breaks up projects into small .js files on a per-route basis etc.
[0]: https://shopify.dev/custom-storefronts/oxygen [1]: https://github.com/lagonapp/serverless/
[0]: https://blog.cloudflare.com/workers-for-platforms/ [1]: https://shopify.dev/custom-storefronts/oxygen/worker-runtime...
Does that mean you want to roll out your own runtime in the future?
VanillaJS is very advanced nowadays.
I am a backend developer and lightly familiar with what React bring in frontend development. I have not familiarity with Nextjs.
Given what I know, where does Hydrogen fits into the picture? Why shouldn't I stick to sever side rendered pages when developing Shopify app?
Thanks!
"Why shouldn't I stick to server side rendered pages?"
Hydrogen is still server rendered. Server components themselves never execute in the browser.
Can you elaborate on what the difference is between Hydrogen and a custom theme? Other than the tooling and template language I’m struggling to understand the conceptual differences.
Custom themes allow you to template on top of the Shopify front end, giving you less control.
We're working to align with Vercel on improving the conventions of server modules (e.g. dropping the filename suffix): https://github.com/reactjs/rfcs/pull/189#issuecomment-111648... and we anticipate to release future versions of Hydrogen and Next.js that use something like boundary annotations instead.
To say this though, I prefer the file extensions bit, e.g. `.client.ts` and `.server.ts` over directives. Directives aren't super discoverable at a glance, and I think will lend themselves to a lot more headache in terms of engineering practice.
I realize its better for compilers probably, but it hinders DX for large applications IMO.
This makes it "transparent" to the developer but retains the file naming approach, best of both worlds?
[0]: https://devblogs.microsoft.com/typescript/announcing-typescr...
According to this mutation, you must renew the access token before it expires (presumably for just another 24 hours). So I don't think this solves the issue -- we want users to stay logged in for more than 24 hours -- aka logged in for like a month by checking a "keep me logged in" box.
https://shopify.dev/api/storefront/2022-04/mutations/custome...
What is the strategy for this basic use case?
Take a look at the hydrogen demo store, auth is implemented using the customer access token and Hydrogen’s CookieSessionStorage:
It looks like a very competent solution but would like to hear from actual users
As for hosting, you can deploy to Shopify's Oxygen platform (Worker-based), or any other deployment platform that supports Node.js or v8 Worker runtimes.
Vercel is my go-to choice to deploy my apps and it seems you are trying to support them too.
We have a working prototype of Hydrogen deploying to Vercel, and we need to formalize it into our official documentation: https://github.com/frandiox/hydrogen-vercel-edge
"hydrogen" has quite a specific meaning as a chemical element.
Shopify:Hydrogen might work, but why? It gives no clue about it's function, goals, or anything.
How about Shopify-React? Reactify? Shopiract? Use your brain, as I'm always telling my kids.
The name happens to pair nicely with Oxygen, our hosting platform: https://shopify.dev/custom-storefronts/oxygen
These names work great for internal servers or services. Only.
They're good names. Obviously if there is ever ambiguity, one would simply say "Shopify Hydrogen" or "Shopify Oxygen".
As if everything else isn't named with other random words... React, express, moment, chalk, gulp, path, jest, morgan, passport, and countless others. That's just npm packages. Rust? Elixir? Go???
Turns out we name things whatever we want and it doesn't pollute the global namespace because context exists.
We're meant to invent new words for everything? Talk about pollution... We definitely need more words like Shopiract! /s
The periodic table of elements and Greek and Roman gods provides a nice list of cool sounding words that have likely been used elsewhere. Pick a random element. I'm positive even something like potassium is used somewhere.
Not sure if anyone noticed but "react" is a single common English word but somehow I never had any problem searching for it
-it's so popular millions of people use it, or
-it's so unpopular you know the entire userbase
The middle ground is the problem. For example a few years back I had a persistent bug/crash with Pix (mint's default image viewer then). Nothing on git or stack, and search engines didn't know what to do with it. "Pix image viewer" helped but not by a lot. I still don't know if it ever got fixed.
We tend to refer to the whole thing as the Shopify H2O stack.
I really like it, but I also named it. I can confirm brain was used, but maybe the wrong one.
> Use your brain, as I'm always telling my kids.
Proceeds to be mean.
Classic troll move op.