Next.js, GraphQL, Recoil, MUI and More: A New Web Stack Reviewed
In our recent website redesign we took the opportunity to revamp our entire technology stack. We introduced pieces including Next.js, GraphQL, MUI (Material UI), and TypeScript. We enhanced existing parts of our stack we know and love like React, Node.js and Kubernetes. Redesigning and rebuilding a website is a challenging endeavor on its own and introducing a new set of frameworks into the mix certainly didn't make life easier. Some technology choices really paid off while others could have been made differently. Rebuilding the front end from scratch illuminated pros and cons of each. This post aims to share the experience we had implementing these new technologies.
Static Site Generation with Next.js
Previously we used a homemade project that essentially provided Create React App server side. The project was a hack that wasn't scalable and it was inevitable that we'd eventually adopt Next.js.
Choosing Next.js was a great decision that has paid off enormously. Among many features, we especially found its static site generation to be greatly useful. Although SSR provides great benefits, we were able to build our website serverless with getStaticProps
and getStaticPaths
.
API Orchestration with GraphQL
Another choice that proved its great value was to adopt GraphQL as an API orchestration layer. Combined with TypeScript and Apollo, implementing a GraphQL server just felt right given its declarative nature. Expectations are explicitly defined as GraphQL essentially provides built-in documentation.
Apollo Client was an excellent addition with its React Hooks useQuery
and useMutation
. Its out-of-the-box caching capability, refetch functions and loading states reduce the need for unnecessary global state.
Material Design with MUI (Material UI)
MUI is another framework we were considering for a while. Although the framework has been significantly commercialized as of recent, I'm not gonna "knock the hustle". MUI offers a Figma UI kit which was greatly helpful and key in our redesign process, however at the time of this writing an individual license costs $69.
Choosing MUI was one decision that could have been made differently. We decided to use Linaria for its zero runtime CSS. Combining Next.js with MUI and Linaria was a bit painstaking and while running Next.js in dev mode, styles appear somewhat broken on certain pages until you do a hard refresh. The root of the issue is unclear, although it could be more about the Linaria / Next.js combo.
Also, MUI just released a major version (version 5). Although they provide a migration guide and codemods, the upgrade has become a bit impossible for us. I wish the version 5 release wasn't so giant and they would have pieced out the changes. The main contributor of this open challenge is the move from JSS to Emotion. If I could go back in time, I would have just used the styling engine the component library itself uses as much as I really wanted to use Linaria.
The pros supersede the cons in our choice to use MUI. The framework provides elegant components, elaborate documentation and examples in both JS and TypeScript. When adopting a component library it's important to make the right accompanying decisions including theming and styling, which is where we went wrong.
Global State with Recoil
We intentionally rely on global state very minimally in our Next.js app. GraphQL and local state with React Hooks give us most of what we need. Some scenarios give us no choice but to utilize global state. Overall, Recoil has been a great choice for us in global state management. Compared to Redux song and dance - Recoil has been a breath of fresh air. Recoil provides a simple API that just makes sense when working the newest landscape of React, including Hooks.
High Availability with Kubernetes and Digital Ocean
Kubernetes is a technology we've used since the beginning of Foo, but I wanted to take this opportunity to continue with my praise of it. We've reworked our infrastructure several times and switched to Digital Ocean hosting from AWS. So far, so good with Digital Ocean. It differs from AWS slightly in pricing (better from our experience) and better UI's when you login to the dashboard. Our service runs 1,000s of Lighthouse audits a day which is a resource killer in terms of CPU and memory. Kubernetes has helped us maintain a stable service that we can continue to scale and grow.
Conclusion
Overall I don't regret any decision we made in choosing new pieces of our stack, but if I could go back in time I would tweak a few things. I hope this post helps illuminate some of the good, bad and ugly regarding these newer technologies.