Considerations for CMS Integrations with JAMstack Sites


It is often assumed that static site generators have limitations that server side rendering or client side rendering is necessary to get beyond. Single page applications, progressive web apps, engaging and dynamic UI's, integrations with databases and content management systems; these cannot be used with a statically generated site can they? They certainly can. One of the names this technique goes by is JAMstack. While in my opinion a server sending prebuilt HTML to a browser should be the standard it has become necessary to give it a name as both the server side and browser side of web development has become cumbersome and overly complex.
However there are many things to consider when building a JAMstack website. How do you integrate content and databases? How do you enhance it with modern web development techniques such as SPA and PWA? We will take a look at some of these considerations and specifically how they apply to web content management.

Fine Tuned Build Hooks

If your website is large enough, rebuilding it might be a heavy burden on your content provider and databases. How often builds occur, the source and scope of the changes, and the number of requests to your content providers and database that it requires all need considered when designing the build process. Imagine you are building a news outlet that will have tens of thousands of pages and data is changing hundreds of times per day. In a circumstance like this it is important to only rebuild the part of the site that is affected by any given content or code change. We will look at some of the ways to fine tune build processes to only rebuild the pieces of the website that are necessary so that our JAMstack site can scale indefinitely.

When it isn't a Problem

First it is important to understand when this is not a problem. If your site has about a hundred pages and rebuilds from code and data changes are expected a few times per day, then this should only produce a few hundred page builds. If your content providers are capable of millions of reads per day, then this is multiple orders of magnitude away from being a problem. In addition it is often easier to scale the capabilities of data and content providers than it is to deal with restrictive build processes. That being said there are circumstances where a fine tuned build process is necessary.

Build Hooks

When deploying a JAMstack site you usually need to rebuild your site any time dependent data or content changes. To do this your hosting solution needs to have build hooks so that other systems can notify it when it needs to perform a rebuild. The content providers, databases, and code hosting solutions that you select in turn need to be capable of web hooks so that they can notify the hosting service that a rebuild is necessary. They also need to be capable of passing on detailed information so that the build process can identify exactly what needs rebuilt. Additionally, your selection of a static site generator will either limit or enable fine tuned build hooks and will affect how much of your site needs rebuilt on each content or data update.

Global Data

Websites are always going to have global data. This might be the name, metadata, and other information that appears in all or many pages. Another example of this would be a "latest posts" section that appears on every page of your site. Any time this data changes each page might need updated, and there is no way to know until you actually perform the build. One solution is to restructure your site features to not run into this issue, but that is of course limiting and we would rather find a solution that enables us to maintain the feature. There are two general approaches we can follow to solve this problem.
Controlled Changes
The first option is simply to limit the number of changes to global content. This tighter control allows you to maintain the same build process, keeping a simple build system with maximal end user performance. This might come in the form of limiting who has access to updating the content or limiting how often changes to it are integrated into the build. The benefit of this is simplicity and end user performance. However this limits how flexible you can be with global data and how quickly changes can be integrated into the site.
Async UI
The other option is loading this content asynchronously after the page load from an always up to date API. This means that the data can change as often as you would like and changes can be integrated into the end user experience the moment they are made. The limitation of this option is complexity and performance as it introduces client side rendering. The page and any dependent libraries must be loaded, requests for data made, and the UI updated. This is the design that nearly all web frameworks follow, and is the reason for much of the slowness of the modern web. However sometimes it is necessary in order to implement highly interactive and data intensive UI. In these scenarios using this asynchronous UI approach in a careful and selective manner can give content flexibility and more real time content updates.

User Data

The other data consideration with JAMstack sites is authenticated experiences. Do users have their own data? Should some content require authentication? Are some views user specific, where the content they see depends upon their profile? In these scenarios there are some additional considerations with regards to how these views should be delivered.
Prebuilt Views
You can still follow the JAMstack pattern of prebuilt HTML, but this time delivered only through an authenticated UI. This means that your otherwise static server needs to be capable of authorizing requests, increasing hosting complexity, but it also means that you maintain the performance benefits of prebuilt HTML. It is worth noting that this not a very common solution and many build process will either not support this or require a lot of customization.
Async UI
The other option for authenticated experiences is Async UI once again. This one is the standard for many websites these days and for good reason: maximum flexibility. You simply load in your authorized data after the page load and build your UI with a JavaScript library. This enters us back into the world of JavaScript based UI's and needs to be carefully considered so that these portions of your UI do not slow down the initial page load or over reach their welcome. Any UI that can be prebuilt should be prebuilt. User specific UI that needs updated based upon user data and interaction likely will need generated after the page load. However it is easy for this to creep into the rest of the UI, slowing down initial page load and rendering, and unnecessarily generating the UI only after the user needs it, instead of having it ready for them.

Continuous Integration

JAMstack sites are a perfect fit for continuous integration made simple. Your build process already produces a site that can be simply and statically delivered. We have already discussed the need for build hooks that force a rebuild of the site. This same process can be easily extended into version control. All that is needed if for your coding hosting system such as GitHub to use a web hook that triggers the build hook of the hosting system.
However not every code change requires a full rebuild of the site. Very often static site generators will have a source directory hierarchy that matches the end website. In this case if only one page is modified in the source code then it is possible that only that page needs rebuilt.

Single Page Applications

It is common to think that static site generation cannot be a single page application. This is in fact far from the truth. Combined the two can give you the best of both worlds, SPA architecture reducing the amount of network traffic and static site generation reducing the amount of run time processing. Single page applications increase performance by loading only the information needed to update the view, without reloading and re-rendering the whole page. Static sites are good at limiting the amount of run time processing, simply delivering prebuilt HTML as the user needs it. These can be combined to produce a website that is maximally performant.
To do this the static site generator that you select needs to be capable of rendering not only the full static page, with metadata, footer, header, and other layout elements included, but also needs to generate the HTML of just the page. This way the client code can load in these views upon navigation without loading in the whole page layout and metadata

Progressive Web Apps

Progressive web apps surely require a more complex infrastructure than what static site generators are capable of right? Again, this is not the case at all. In fact they go hand in glove. Service workers often require ahead of time understanding of the structure of your site and static site generation provides just this type of information that might otherwise not be known until runtime in a server side or client side rendering scheme. Progressive web apps can turn your static HTML and JavaScript into an installable, offline capable app that can access remote API's, real time databases, authentication services, and cloud functions that turn them into true apps with rich features.

JAMstack Suggestions

With these considerations in mind, I have the following suggestions when implementing a JAMstack site alongside a CMS:
  1. Enable fine tuned build hooks my maintaining a meaningful site hierarchy and selecting the right content, hosting, and site generating solutions.
  2. Enable single page applications by selecting a static site generator capable of generating content in various formats such as with layouts included and not included.
  3. Enable user specific experiences with client side rendering solutions that can fulfill their purpose without overtaking the entire app.
  4. Limit the amount of global data changes and places where small content changes would require full site rebuilds by planning your page layouts and features ahead of time. It is also important to know ahead of time which features will have such an impact so that you can plan accordingly.
  5. Know which side of the build cost vs data request cost equation you are on. Are your databases capable of fulfilling orders of magnitude more requests than your build requires? Then skip the fine tuned build process. Will you have millions of product pages where rebuilding them even once is a heavy load on your database? Then carefully plan ahead for a fine tuned build process.

Comments

Popular Articles

The Vanilla Javascript Component Pattern

The Sunless Citadel: A D&D 5e Session Report

Getting Started with Harp