Headless with Magento 2

For about half a year to one year, the community is buzzing on headless Magento. For newcomers, it is a little bit hard to grasp why this is needed. Or what it actually involves. And it seems different people decide on the concept for different reasons. Let's dive a little bit in the details of what and how.

What is headless Magento?

The term headless is something I have heard before with automated browser tests (where you script the actions a browser would take to, for instance, add a product to cart). Going headless with browser tests means that you run a browser in a non-graphical environment (in Linux terms, without X-Windows or Wayland or whatever). And this could even be done with a regular like Chrome by running the output in a X frame buffer program.

Likewise, with headless Magento, the original Magento application still runs, but it is not outputting anything to the browser. Instead, a static webpage (not driven by PHP) would fetch the content it needs (a product listing) through JavaScript-driven AJAX calls from the Magento API. The only thing you would need is a vanilla HTML page, some JavaScript tools and remote calls to the Magento API.

Showing a product listing would be the easiest example: In the HTML page, you could perhaps create placeholders for the products to be, so that every product looks similar. Then JavaScript would fetch the products remotely and replace the placeholder with actual products one-by-one. Applying the same principle to the checkout or customer pages would also require a push of data back to the server (Magento), so basically AJAX POSTs. And of course, you need a mechanism of keeping track of the current session, go through the steps, do validation, etcetera. Things get more complex quickly.

Why is headless cool?

There are various benefits to going headless: The markup in HTML would be simple to understand for a web designer - no PHP code, no complex JavaScript widgets, just plain HTML with some kind of additional placeholder-syntax, that's it. Likewise, because the HTML document requires no PHP code to be executed, the HTML page could be served statically - bringing the application load time down to the time for a butterfly to move its wings. The HTML page does not contain any Magento parts yet at this point (products, categories, menu, cart), so those would need to be lazy loaded (in a 100% headless situation that is).

When people talk about headless being more performant, we will also need to take into account that there is a difference between the Time-To-First-Byte (which will be extremely small) and the Time-To-Interact (when you can actually use the page): Only when the vital parts like products, menu, cart have been loaded, the page actually becomes useful. And this leads to the question whether going 100% headless makes sense. I'll get to that later. Ĺet's focus on the cool part first.

Building headless applications yourself is not something you will want to do: You would need to build your own AJAX engine, you would need to map resources from AJAX to HTML elements, you most likely would like to have a templating engine. This is why we have frameworks like Angular, React, Vue, Ember ... and Knockout. Important is also to realize that JavaScript is evolving rapidly, with a new framework popping up every day. Choosing for a tool X is something that makes sense now, but the tool might be outdated a few years after. Yes, this seems to be already the case of Knockout, but it might also be the case for Vue or Angular as well. Nobody knows what the future will bring.

The buzz

Lately I have been hearing a lot of different talks on different headless approaches: For instance, Sander Mangel talked about creating his own API using Slim to fetch data easily and fast from Magento. Riccardo Tempesta talked during MageTitans Italy about the challenges of integrating ReactJS with Magento. And I have heard many development agencies talk about replacing the current Magento 2 theming setup (XML layout, PHTML templating, KnockoutJS, UiComponents) with their own (Angular, React, Vue).

This is all possible ... with the right amount of time put into it. The main question is why this should be an option for anyone. Personally, whenever I hear about cool technology, I always want to dive into things myself as well. So integrating ReactJS and Magento 2 is cool and as a developer, you should go where the cool stuff is.

Open questions

However, coolness can not be the only reason to replace KnockoutJS with some other JS framework. We have much more things to consider before we can actually say that Magento should make integrating some other JS framework a priority. What about the amount of work and the costs involved? And does such a framework actually help to improve Magento?

The last thing we should do is choose another framework, put a lot of effort into refactoring Magento for that new choice, only to find out that that framework becomes outdated in a few years, while not bringing many benefits. We need to realize that the Magento application (shipped as semi-stable, with a lot of dependencies) is evolving evolve at a much slower pace than a stand-alone JavaScript framework (focused solely on devs).

Why headless in Magento?

So why go headless in Magento 2? Well, a benefit could be that the JavaScript part is looser coupled to the Magento backend. And this would allow theoretically for easier swapping of the framework - Angular, Vue, take your pick. Which JavaScript framework to use would become a frontend developers choice, instead of KnockoutJS being now a solid requirement for developing in Magento.

Also, this theoretically would mean that you don't need to be a Magento developer to build cool stuff upon Magento: Instead, you can focus on a REST API that simply offers everything you need to be loading. This, of course, leads to bigger issues: If a single page would be loading 10 different resources from different REST URLs, the HTML document itself would be optimal, but the entire loading time would be hell. AJAX resources would need to be bundled as single requests and perhaps cached in local storage. Believe me, I've built a bridge between Joomla and Magento and the bundling of requests definitely does not make things easier.

Magento offers a flexible framework that you can use to build your own logic (pricing, logins, checkout). However, this contains a lot of additional stuff that you don't need. Building your own pricing rules might be easier than trying to extend and modify the Magento pricing rule system. It might require effort. But you will be dumping a lot of complex logic, in favor of code that simply works the way you want it to work.

Performance with headless

I have heard people say that performance would be a good reason to move to a headless Magento. This would require all pages to be served statically, while all dynamic parts are lazy loaded through AJAX. Well, as far as I know, this is already the setup of Magento 2: Full page cache (and Varnish) become possible thanks to the concept of Private Content that allows for this kind of lazy loading. You only have this benefit if you go 100% headless. Or put differently, maximum performance of Magento 2 can be gained by using Varnish only, and Varnish will still limit you here. There have been stories where Varnish is replaced with a NodeJS server, gaining even more performance. But this requires you to go 100% headless because otherwise you still rely on the performance of either Varnish or the Magento 2 backend. Alternative solutions also include building a simple API server that proxies (and caches) data from Magento, but not using a generic pass-through-Varnish solution, but a custom-built solution.

Isn't Magento 2 headless already?

So when you say that headless means that you can use some JS framework to lazyload data in a static HTML document, you could say that Magento 2 is already headless for a major part. Currently, with Magento 2, a JavaScript developer only needs to know about KnockoutJS ViewModels to make use of Magento logic. Obviously, when the ViewModels do not suffice, a Magento developer is needed to add backend logic to this JavaScript layer. However, this also applies to going 100% headless: Whenever some REST resource is not available, a Magento developer should make it available.

The loading time of the current Magento 2 system (with Full Page Cache being enabled everywhere and cachable=false not popping up anywhere) is also quite ok for most people (I know, I know, it is open for discussion): It is not 100% headless, because the HTML document not only contains the templating part but also static content that should change less (and therefore should be cachable). It's not a perfect world - it is rather complex and it contains lots of different strategies. But to me, it is already partially headless and Knockout already seems a fine choice, when I compare its features to features with other frameworks like Angular. Obviously, if you have worked a lot of Angular, you would rather see Angular instead of KnockoutJS. But slowly the reverse (favoring Knockout above Angular) is becoming my preference: I like Knockout better than Angular - Angular dictates me to do stuff their way, with Knockout I can build whatever.

KnockoutJS is outdated?

I have also heard many times that KnockoutJS is outdated, old, deprecated. I'm not considering myself to be a real JavaScript guru, though - from the Magento perspective - I begin to know my fair bit. And from this, I believe that KnockoutJS is not obsolete, or deprecated, or outdated. Far from it: It is used to create cool new app frameworks like Aurelia and Durandan. KnockoutJS is basically a flexible tool to let us build great applications on top of. And I have to say that KnockoutJS is a lot more lightweight than Angular or React.

I have to say that the integration of KnockoutJS in Magento feels much more like an addition of some JavaScript thingy to the existing application of Magento, than it would be when the entire application was built from the ground up with a JavaScript framework. It leads to different choices. However, going 100% headless doesn't make sense if not all of the content is 100% dynamic. It asks for a mixed approach and it seems Magento took exactly that mixed approach, by combining their existing frontend architecture (XML layout, Block classes, PHTML templates) with JavaScript (RequireJS, KnockoutJS and their own JS components). Complex, yes, but that's because e-commerce is complex.

My vision on headless

Personally, I think having an option for Angular and React instead of KnockoutJS would be very cool. And it would be even cooler if a lot of the Magento core components (UiComponents, libraries, widgets) would be reusable across any framework. However, on a practical side, I see a lot of work ahead before the Magento core components are that flexible that they fit in any frontend environment.

AMD helps a lot, but there need to be more generic libraries with less dependency on KnockoutJS. Because of RequireJS, you can already swap out Knockout with another Knockout-compatible tool (as if that exists out there) and rewrite the UiElement core behavior with your own Angular-based version. But it is not very practical. It is just very cool.

So personally, I would strongly recommend newcomers to work with whatever is supplied by Magento, while experienced JS developers should be able to play with whatever they want to integrate.

Learning stuff

It does not mean that those two worlds should remain separate: I encourage newcomers to dive into Angular and React as well, to get a broader understanding of what kind of role JavaScript plays in Magento 2. Likewise, I would say that any Angular or React fanatic first builds a separate application in Knockout, to get a taste of what Magento 2 choose for.

Work ahead: Refactoring the API

To bring the visions closer, Magento could be improved as well:

  • The REST APIs should be improved, regardless of the JavaScript framework that uses it. Also, the REST API might best be served from the frontend area, when the API is used to actually serve the frontend area. Otherwise, this leads to many possible bugs that Riccardo Tempesta pointed out in his talk. I think the existing REST API (with its area webapi_rest) is fine for integration with other systems, but an API for the web frontend simply has different requirements.

  • The core JavaScript libraries should be improved, with fewer dependencies with KnockoutJS, more documentation on their purpose and more usage of cacheable REST resources. This way, more functionality can be built in different JavaScript engines.

Conclusion

Both points above would be something to work on if indeed the choice would be to support more frameworks than just KnockoutJS. Still, my point was that a lot of the benefits of other frameworks are already there in the current Magento 2 system. It might be that things are not as stable as they should be, but introducing a new JavaScript framework now could actually make things far worse.

If you have any thoughts on this, please let me know. I'm happy to dive into discussions on this because all of the excitement on headless approaches show an important thing: While we all love Magento 2, it definitely feels like the JavaScript approach could be improved.

Disclaimer

The matter discussed here is complex and I have the feeling that I simplified things a lot. When diving into details, there might be many more pros and cons on having headless approaches. Don't bash me too hard. And God, we have not even touched the topics of Lizards & Pumpkins, Single Page Applications, service works and Progressive Web Apps yet.