Vue Storefront lessons learned: architecture and technical decisions

TL;DR: This is the last part of the Vue Storefront lessons learned. It’s about technical decisions and architecture, how to deal with lazy loading and SSR, and improve modularity as the project goes.

Architecture

Theme engine

The way users customize the UI — by creating themes — was a key enabler and single most important feature of Vue Storefront. It enabled developers to copy or modify the base theme, while still having the core, open for general updates or new features. Inheritance is important in here. Features are usually added in the core (logic) + some basic UI on the theme level. Themes should inherit from a kind of “blank” or “theme-starter”. By having such inheritance, when there are new features added to the core, a user can simply enable them in his/her UI and just add CSS to the blank UI representation. Users like theming because it’s something they’re familiar with: Wordpress uses themes, Magento uses themes, Shopify uses themes …

Vue Storefront’s demo theme (source)

Abstraction layers

We centralized the rest communication to a single ”sync” library. Request construction, even offline/ready data synchronization takes place there. The queries should be object based. By having such an abstraction we were able to introduce GraphQL support as an alternative to REST API — just after releasing version 1.4. Abstractions that are easy to understand are good. Too many abstractions make the project hard to understand. We started introducing abstractions when we found it necessary via refactoring.

Application config

Config should be reloadable during runtime (using ENV variables for example) — it’s key for deployment operations/scaling. In Vue Storefront, webpack was used for compiling the config into the app bundle — during the build process. It was pretty optimal regarding network round-trips but we were not able to reload the config without rebuilding the app. We changed this behavior a few versions ago.

Dynamic Code Splitting

With frameworks like Angular, Vue and React and with applications with the size of Vue Storefront, code splitting is a must to provide users with optimal performance. It’s much easier to introduce code splitting at day zero than to refactor the app later on. This is one of the exceptions from the general rule of the optimization. It’s because code splitting involves architectural changes to your app.

SSR is a must for eCommerce

Most eCommerce sites leverage, to some point, the traffic they got from Google. Google won’t index your SPA/PWA if you do not provide the Server Side Rendered markup to feed the crawler. In Vue.js, the SSR requires you to comply with some general assumptions (like all data fetching into centralized Vuex stores). So you should think about it at the architecture level. Thankfully, we started with SSR :)

QA and UI

QA

Pull Requests should be accepted not only by devs after a Code Review but also by QA engineers after testing all the critical paths (of course, it’s good to have unit tests / e2e tests plus the critical paths written down). Moreover, it’s a generally a good idea to have a kind of quarterly/bi-annual SEO audit of the default markup/capabilities like open graph/meta-management.

Design systems

If we had a chance to start the project once again, we would probably start with the design system and a lightweight set of UI components. We started with a Figma.com based design, divided into components. But then we just used the components implementing the default theme without creating a basic, lightweight component set (like a Twitter Bootstrap kind of thing). I think it’s much better if you start with these basics. You can open source this design system and generally you end up with much better, reusable UI code.

Misc/optimizations

Tree Shaking

Another thing with bundle sizes we learned the hard way is tree-shaking. You should use only the libraries that support it, or are very small (so you don’t need tree shaking). For example, you can choose ‘lodash-es’ instead of ‘lodash’ and import granular functions as they’re really needed to optimize the JS size. We refactored a lot to get to this point :)

RxJS

For the data management/event management, we would probably use rxjs if we started Vue Storefront once again. It’s framework agnostic.

Here you have our other key takeaways (on starting an open source project and its setup) of what we learned in the process of building the first PWA for eCommerce. Have you had similar experiences with building an open-source project? Please do share your thoughts!