Creating a Magento Theme With Next.js and GraphQL

Feb. 12, 2019 • 4 mins 30 secs

At the end of 2018, Magento released the 2.3.0 version of their e-commerce framework with a new GraphQL API. Traditionally, Magento themes are created with PHP templates, similar to WordPress. However, with the new GraphQL API and PWA Studio, new themes can be created in JavaScript frontend frameworks like React and Vue. To experiment with the API, I have created an open source theme called Basil using React, Next.js and Apollo. Here is a preview of the theme with Magento’s sample catalog. The theme is very experimental so it needs code cleanup and responsive styling, but it allowed me to explore how a theme could be created this way. It does not use any PWA Studio components because I wanted to see what it would take to build a frontend from scratch. Here are my thoughts and impressions about the whole process.

Deciding on a Framework

There are a ton of options for frontend JavaScript frameworks so I tried to narrow down my choices using two requirements: it must have easy server side rendering for SEO (crucial for e-commerce) and it must support GraphQL. In the end, I tried three frameworks Nuxt.js (Vue), Ember with Fastboot and Next.js (React). Ember actually had my favorite development experience. The code generation CLI and easy templating were a big draw, however, its GraphQL support was wanting. The best Ember GraphQL plugin could not support loading states. Nuxt.js’s GraphQL integration was lacking as well. It was too difficult to get the GraphQL data to load when rendering on the server. In the end, I chose Next.js because of Apollo’s excellent React integration and because Next’s server rendering is top notch. Next will render the whole React component tree with the necessary GraphQL data before outputting the HTML on the server.

I like GraphQL

Basil was the first time I have seriously used GraphQL and the development experience was great. The queries are really easy to write and I like that you can store them in files for reuse. It really simplifies retrieving data because you can write queries in a GraphQL client like Insomnia and the fields will be auto-populated as you type based on the schema returned from Magento. In React, Apollo makes GraphQL easy by supplying a Query component that you can use to wrap your JSX and your template will be automatically supplied the query results. Here is an example:

<Query query={PRODUCT_QUERY}>
    {(response) => {
        if (response.error) return <div>Error</div>;
        if (response.loading) return <div>Loading...</div>;

        let product = response.data.product;
        return (
            <div class="product__name">{product.name}</div>
        );
    }}
</Query>

Routing was a Pain

Magento has a unique routing system because any path underneath the root could map to a category, product or content page. For example, opening /backpack on a Magento site could take you to a product named Backpack, a category for Backpacks or a content page about backpacks. It is all determined by how the catalog is configured in Magento’s database. To allow for this routing on the frontend client, I had to set up a special wildcard route that would accept any URL path and then query Magento’s urlResolver to figure out if the page should display a product, category or content component. Unfortunately, that means two queries have to be run for each catalog page. A framework like Gatsby might be a better option for a small catalog since it can generate a frontend page for each URL in a build step.

I Wish Unit Testing React Was Easier

One of the features of Ember I liked was that it came with a unit testing setup and a framework for performing integration tests. Next and React have plenty of examples of how to set up Jest (a test runner), but there is little documentation about good ways to integration test a component that renders HTTP results. I set up Enzyme to help with component rendering and analyzing, but still have not built out a way to mock the GraphQL server for more extensive tests.

Viability for Magento

Unfortunately, I do not think it is time to make production frontends this way for Magento. Magento’s GraphQL endpoints are lacking and will not be fleshed out until later this year. Currently, to build a cart and checkout, you would have to fallback on the old REST API. I think it would be better to wait until the GraphQL API has better frontend coverage. Even when it does cover the checkout, it will still be missing some of the smaller Magento features like related products and wish lists. Magento is still working on their frontend solution, PWA Studio, as well. When it is feature complete, PWA Studio will be another option as a basis for a JavaScript frontend.

Final Thoughts

The new GraphQL support is exciting because it will allow Magento developers to make modern and unique frontend experiences. However, there is a lot of development to be accomplished before it is production ready. While I will miss the simplicity of PHP templates, the performance and capabilities that JavaScript frameworks provide will make them popular for many merchants. Plus, it will make it much easier to introduce frontend developers to the Magento ecosystem.

Let me know if you have any questions about my experience with making Basil. Also, check out the GitHub repo and the online preview and let me know what you think!