Why did we go with SSG, Typescript, golang and VueJS+NuxtJS?
For the customer-facing storefront we evaluated various tech stacks including the most popular general-purpose web-frontend frameworks and libraries (ReactJS, AngularJS, VueJS) to more purpose specific ones in the E-Commerce domain (Frontastic, VueStorefront).
The frontend in itself should not contain any content or assets, it should be provided by other services such as a headless CMS and a PIM. This will enable a decoupling between content editors and software engineers. The content editors will be able to update the website using the UI provided by the services.
To reach our goals to build a state-of-the-art E-Commerce storefront that is built to be fast, flexible, cost-efficient, and quick to implement, we set a couple of technical characteristics for it to achieve, i.e.:
- Delivering a Progressive Web Application (PWA),
- Using modern framework(s) with a vivid community and available talent pool,
- Supporting Emma’s rapid growth though concurrent development
Why SSG instead of SSR for the Storefront (high traffic)
- As speed metrics such as — First-Paint, First-Contentful-Paint, Time-to-Interactive and Time-to-First-Byte — are crucial in any E-Commerce site, SSG is preferable if feasible for the use case. Due to a manageable number of pages (few products) and not too frequent content updates, SSG’s cons don’t apply in our case.
- Cost will be minimal compared to SSR as the static pages can be deployed to static CDN without cost scaling per page visit. A valid argument is that it can be achieved using SSR by caching the pages, but that introduces new complex problems.
- Offers less security concerns due to minimal attack surface.
- A/B testing will not be as easy as with SSR, but they can be performed by generating multiple versions of the site and use split testing (we will enforce a limit on concurrent A/B due to avoid variation explosion).
Why SSR instead of SSG for lower traffic, dynamic pages?
- The customized content needed for each page does not suit the SSG case because there is too much dynamic personalized data involved.
- An alternative would be to use SSG with client-side fetching. But would need to fetch all data and therefore the gain is minimal. First Meaningful Paint would be slower.
Why VueJS instead of ReactJS?
- More collective knowledge about it than ReactJS at Emma, meaning faster and more reliable implementation.
- Easier to transition to without prior knowledge of modern web frameworks.
- Superior documentation including best practices that aligns VueJS projects across organizations.
- Easier to onboard new team members: For inexperienced developers it’s easier to separate logic from HTML when doing DSL instead of mixing arbitrary JS with HTML thus making the codebase more maintainable.
- There is a larger fraction of developers who used ReactJS but would not use again compared to those who used VueJS but would not use it again.
- It’s popular — VueJS already has more github stars than ReactJS.
- Preference within the team — this is taken into consideration as happy engineers mean better teamwork and product in the end.
Why VueJS instead of Angular?
- Angular’s learning curve is steeper.
- It’s not as lightweight as VueJS.
- Angular is better suited for more complex applications or applications behind a login page.
Why not VueStorefront?
- They are in between versions with the VueJS 2-version being tied into the old ways of creating VueJS apps and the new VueJS 3-version not being production-ready yet.
- The main reason of going with VueStorefront would be speed of implementation as a lot of the core features are implemented already, but, as the new VueJS 3-version is not ready yet, we can’t rely on their schedule for the missing and broken features.
- The initial investment of creating the provided features ourselves in a project we fully control, in our opinion, outweigh the usefulness of the framework. However, we can take inspiration from them on how to manage features, best practices, etc. as the project is Open Source.
- They focus on SSR and SSG is still an experimental feature in the stable VueJS 2-version. The main use case would be a shop with a lot of products, showing the ‘classic’ product categories and search feature for them.
- They also have an E-Commerce component library which would speed up the initial implementation but since the library is Open Source and decoupled from VueStorefront we can still use it if we want. Also, it would take a while to understand the framework and what are the things we don’t need and how we can strip them away.
Why not Frontastic?
- The visual editor is redundant to the CMS. When combined with the headless CMS, if we model the content right, we can do what we need in the CMS. Having both we feel would bring confusion to the editors.
- We already have the infrastructure ready to go to be able to manage the complexity surrounding deployments ourselves, which is one of the main things of their offering.
- To develop UI components in Frontastic we would need to use their infrastructure for everything. Nothing is done on Emma’s systems, even the repository is owned and provided by Frontastic where we use their built-in file sync to sync with their servers.
- Looked to be too new with too many bugs for now. The UI had at the time we tried it breaking bugs and the general feel was that it was barely production ready.
- They used SSR and changed per site visit as the price model. For Emma’s business the commercials were not convincing.
- It forces us to use ReactJS — no other choices offered.
- NuxtJS is by a wide margin the most adopted and mature SSR/SSG framework for VueJS.
- NuxtJS can only be compared to the counterpart in ReactJS called NextJS.
NextJS offers some additional features that NuxtJS doesn’t, but both have the features we need and as VueJS was preferred instead of ReactJS we can be confident with NuxtJS.
Why Typescript and golang?
- Strict typing pulls error-handling from runtime to compile time, meaning early debugging and correction by the original code author.
- Object-oriented approach and language features (e.g., interfaces, generics, type annotations).
- Improved readability and documentation through strictly typed character.
So, we decided to use Typescript as our primary programming language in the business domains for frontend (client-side) and backend (server-side) of our E-Commerce architecture as its downsides (e.g., being single-threaded) are not relevant in our use cases.
However, for specific workloads in the backend of the Order Management business domain, we chose golang as a second programming language, due to these considerations:
- Based on the business forecasts, we expect to process a high volume of events.
- We know that the OMS will sit between a lot of other services, and we don’t want to risk bottlenecks due to slow performing microservices.
- golang is proven to be fast and has very little resource consumption in Kubernetes deployments.
- It’s deployable as serverless functions with almost no code changes.
- It’s built with microservices in mind and taking concurrency to the next level.
We hope this rather long post gave you a good idea on our thought process when deciding for the cornerstones of Emma’s composable commerce system landscape as of this writing. For sure in the future, we will learn more about the tools we selected, and we might even turn away again from one or the other to head for an even more promising alternative. However, this is exactly the most important part and the beauty of our foundational principles for selection, ensuring flexibility to adapt agile to ever changing business requirement and insights along the way.