Front-end techstack

It uses Vue 3

To maximize performance and DX (Developer Experience) we made the choice to invest in a rebuild of the existing default project. Especially the tech stack including Vue 3 and Vite was promising. After a few tests we decided to go for it and do a step-by-step migration of the Vue 2 code to Vue 3 code. At the end it resulted in a iterative rebuild of all the code. This was definitly not a big bang but piece by piece.

At the end the changes are enormous compared to the first version of Core SaaS, but as mentioned it was a step by step proces. So don't hesitate for your next project to use Vue 3. Just go for it, because the DX is so incredible fast, it will catch up in time despite the rebuilds and learnings.

It uses Vite under the hood

  • Faster dev server start
  • Faster hot updates
  • Faster build

Innovation

Due the innovative style of the project we introduced a lot of new stuff. From DX things, smart components, cool little details and a Headless CMS. All these things are documented here to help you out working with these tools. We also try to give an insights in the choices we made to avoid the same pitfalls for you in the future.

GraphQL is a query language for APIs. This projects uses the GraphQL API from Strapi. The GraphQL setup exists of a few parts;

Schema

The schema is the definition of the GraphQL API. In this project the Strapi app generates a schema everytime the definition of the API changes. The schema can be used to generate GraphQL queries or to get auto-complete support in your IDE. In this project the .graphqlrc.yml file is used to reference to the schema so the IDE knows where to find the corresponding schema. Make sure you install the correct extension to get IDE support for .graphql files.

Codegen

To make use of a GrpahQL API your application should generate code for it based on the schema. This will help the developer to understand the data he will receive from the API. Besides that generating code will also help to validate the correctness of the data. For codegeneration this project makes use of the @graphql-codegen cli. This CLI contains a lot of packages for different tools and languages. The configuration is done in the .codegen.yml. A npm script will run the codegen so make sure you run the task when working with GraphQL.

In our case the resulting code consists of types and queries. All in TypeScript to make sure it's type-safe. The uncertain thing about GraphQL is that the data that is been queries shouldn't be all the data. So the developer determines the data to receive. This also means that every property is wrapped in a Maybe<T> statement to make sure the IDE will give feedback of a possible null value.

How to query?

To query the GraphQL API create a new file that end with .graphql. This file will be generated with to codegenerator as a query. To use the query and the result in your component use import type ... instead of import to avoid large scale dependencies in the codebase.

To query the GraphQL API this project makes use of urql. It's a light and clean library without much fuzzyness. The client internally chaches the results so make sure you set the correct requestPolicy when working woth urql.

Prefer server-to-server traffic

All the traffic between the GraphQL API and the application is server-to-server traffic. This means a high cache hit and less concerns about scalability of the GraphQL API. This also means that the application doesn't have to ship large amount of JavaScript for a GraphQL client.

Server Side Rendering (SSR)

As an ecommerce company SSR is probably the most important part of our applications. This will help us to result the best indexable pages for the SEO spiders. It also introduces a lot of complexity in our applications. To make sure the complexity is less than before (self build) we make use of a plugin that abstract some complex logic from SSR.

To setup our application with SSR we currenlty make use of vike. This plugin is based on Nuxt.js but with less features. in terms of setup it is more like our previous setup with the netivity libraries. This library is for now the best solution (did some research in the time we start the project), but it might change in the future (as always).

The plugin is based on vite, and vite is also the base of the project.

A few features that are really useful of this plugin;

Full Control

Besides the plugin is controlling the SSR as a developer you still have the control of all the aspects of the UI framework (we use Vue of course but the plugin works with all SSR frameworks).

Routing

We make use of the routing feature of this plugin because it's way more easy than the vue-router. This allows us to have cleaner code in terms of linking and navigation.

Prefetching

Because we make use of the routing feature we also have built-in link prefetching support. This allows us to have a server-to-server fetching strategy what results in very fast data transfer for new pages.

Some Caveats

This plugin is cool, but not bug free. Some caveats that we came up too during development;

Link prefetching pageContext.json

When the link get prefetched the application executes a request with .pageContext.json as an extension. This will result in a SSR request and the collected pageContext will be the JSON response. When this request fails the front-end will get stuck in an error loop. The loop is happaning because the request contains a try/catch and the catch will retry the request. The result may contain an error, but the loop is just wrong behaviour. To fix this issue the server always returns a statuscode 200 when the request is a pageContext.json request.

Link navigation

There are some caveats according the link navigation. The vike contains some assets in the code and dome are failing because the compare is not correct. The patch-package package has the possibility to fix an issue in an existing npm package. This tool is used to fix the assert failure. The assert will fail when the application visits a page with a decoded part in the search part of the url. So for example a page with the querystring ?brand=American%20Tourister will contain some invalid URL's.

Tailwind CSS is a utility-first CSS framework. This means that it exists of single classes with single responsibility. So for example py-4 results in top and bottom padding of 4 rem.

The big advantage when using Tailwind is the small amount of CSS you need to ship to the frontend to render the full page. A big percentage of the CSS is usable for the rendering of every page.

It is recommend to use the corresponding extentions for your IDE when using Tailwind. These extension will hint the class options based on your personal tailwind.config.js.

For this project we also use tailwind for our theming solution. The tailwind.config.js is extented with some theming classes, those classes are defined with CSS vars to make use of theming options on runtime (so no compiling needed per theme). Make sure you take a look at the tailwind.config.js.

Tailwind UI is a component library with predefined Tailwind components. These components are used as a baseline for this project. On the Tailwind UI you're able to copy the Vue component from the component to use it in the application. These components often use the Headless UI Library. This library contains some reusable Vue components for some basic interaction like collapsing or popover.

To make use of the Tailwind components in this project make sure you transform the component you want to use to a project specific component. This means that you need to change the theming classes of the components you copied to the theme classes of this project.

For forms this project make use of Vee Validate. The library contains good composables to fix the forms in a simple way.

ValidatedValueProvider

We started by using the ValidatedValueProvider which is ported to Vue 3. This works very well, but it's hard to maintain. We had some setbacks when using de ValidatedValueProvider when we wanted to develop the perfect UX. So we decided to drop it and rebuild it with Vee Validate. It didn't take too long because the interfaces a very similair. Rebuilding the components took some time, but it was manageable. There is not a valid argument anymore for the ValidatedValueProvider to keep it maintained so when working on Vue 3, keep in mind that it would be affordable to rebuild the forms to Vee Validate.

Vue Use is a composable driven library, give it a try, it's awesome. Sometimes maybe not exactly what you need. But the source code of some composables are very useful to get an idea on how to write composables.