In our earlier post, we had introduced component-based front-end design for websites. We discussed how essential it is, to ensure coherence, consistency and productivity when building large websites. We also discuss what typical website components look like and how they are organized.
In this post, we discuss how to implement component-based design in Headless CMS platforms.
What is a Headless CMS?
They consume API from a backend server instance running in Node making them fully data driven and dynamic. Generally deployed as container images with orchestration tools like Kubernetes, Docker Swarm, Amazon EKS or Apache Mesos; aiding portability, isolated environments, payload balancing between services, it has the most streamlined, robust distribution and deployment.
A Headless CMS can be categorized as a hybrid web application which is based on similar architecture where a backend provides data through API endpoints ergo Headless. The frontend consumes this API data through components and renders the output on server (SSR). A frontend is usually built upon one of these frameworks which can harness advanced features like SPA or PWA.
Built on the principle of component model and data driven applications these frameworks offer component creation, scaffolding, state management, sync/async component loading out of the box delivering a more dynamic user experience.
Why go with Headless CMS?
Let’s take a typical use case against traditional CMS like WP or Drupal. Although the window for creating AMP (Accelerated Mobile Pages) theme is open to fair debate, it still needs to cover serious ground.
Traditional CMS’es render web pages synchronously causing slower page response times. This heavily depends on how render blocking assets like CSS, JS, Images, Videos and number of DOM elements affect a page. Ideally they should render viewport content within 2-3 seconds.
On the contrary a Headless CMS can render pages faster by utilizing advanced DOM manipulation and loading assets asynchronously on demand. For eg. a modal dialog can be deferred until explicitly requested or loading components until the user has scrolled beyond certain viewport axis. Deployed with container orchestration, Headless CMS also immensely benefits from isolated services, as backend and frontend services can run in their own namespace or environment.
Building Components with Headless CMS
We cherry picked VuePress for this use case, so let’s explore a VuePress component. VuePress transpiles page speed optimized, SEO-friendly static HTML pages. But behind the scenes VuePress is actually turning your static HTML into a full blown SPA (Single Page Application) where additional payload assets are loaded on demand as users navigate through the site. VuePress utilizes Vue, Vue Router and WebPack to achieve this. A VuePress component structure:
VuePress uses markdown template files and as the tip suggests you can use that component like a regular Vue component inside your markup. Probably the biggest advantage with Vue components is that they can be loaded globally or asynchronously. An example of basic Vue async component.
Defined inside a factory function the async-example component will be loaded dynamically, however this is a very basic method. A better recommended approach is using async components with WebPack’s code splitting feature. Declared as below.
WebPack empowers many other small tweaks like prefetching and preloading with code split. As WebPack documentation suggests, using inline directives while declaring your imports will allow WebPack to output “Resource Hint” which tells the browser that for:
- prefetch: resource is probably needed for some navigation in the future
- preload: resource might be needed during the current navigation
Simple prefetch example can have a HomePage component, which renders a LoginButton component which then on demand loads a LoginModal component after being clicked.
Also, if you are interested in our analysis of using a very different front-end framework (Gatsby JS) with another popular Headless CMS, Prismic, you can hop over here. (Link)