Improving Site Studio Performance: The Webform Element Module
We recently had a performance issue with a Drupal 10 site running Acquia Site Studio 7.5. In some cases, pages averaged anywhere from 10 to 20 seconds to load per user. On top of that the page headers would come through saying that the pages weren’t cacheable.
We poured over New Relic monitoring reports looking for any standout issues we could tackle. The New Relic logs told us that Site Studio canvases were taking a very long time to render but couldn’t pinpoint which component was at fault. However, we had a few key URLs to analyze where the loading times were the worst.
After removing components in a sample page one by one, we got the page load time to under a second and the page headers reported good cacheability and cache hits. Upon review, we noted the component that we removed had held a Webform in it.
Having a Webform in a Site Studio component was causing the entire page to not be cacheable. But why? Webforms and forms for authenticated users are not cacheable. It only works through a lazy_builder callback. If you were to place the Webform in a block, there would be no caching issue as blocks are automatically set with a placeholder if they’re uncacheable.
So how did we fix this? One problem is that the Site Studio Webform module was being used. This module creates nodes when a Webform is created, then has a list of those nodes to select from in the component. This creates an issue with cacheability on render, as we saw, but it also has additional issues like creating additional nodes in the system. If not configured properly, those nodes can be visited, indexed by Google, included in sitemaps, and a host of other things. It also makes smooth deployments impossible, as components break on import because they don’t have the nodes in production at the time configuration is updated.
You could rework the Site Studio component to leverage a Block field that points at any Webform block and reduces the performance issues. However, this issue is like the one we just mentioned — Blocks are notoriously difficult to capture into a deployable configuration and create more records in the database. They also require someone to create them ahead of time and place them in the “hidden” region of Site Studio. This is a lot of workarounds, clicks, and overhead.
Reviewing an Existing Solution
We’ve solved the deployment and dependency problem in the past as it turns out — only with Views. I created and released the Site Studio Views Element module, which allows editors to pick from any defined Views listing and inject it into their page without any other requirements. This provided me with a model on how to solve the user interface and eliminate deployment issues. All that remained was solving the page performance issues.
Lazy Building in Drupal
Drupal has a method of rendering page content known as “lazy building” or “placeholdering.” In short, it’s an alternate way to render data that won’t impact a page’s ability to be cached by waiting until the last moment to output the content. You can read a more detailed breakdown of this on Drupal.org.
Essentially, we did the following to solve our problem:
- Using Site Studio Views Element as a model, created a new Site Studio element and module to create a simple user interface for selecting a Webform to put in a component.
- Ensure that the Webform is lazy loaded when rendered so it doesn’t interfere with the cacheabilty of pages they’re placed on with Site Studio.
Creating a lazy builder for this use case was very straightforward.
The getFields method provides the option list for Webforms in our component. The list is dynamically populated from the Webforms currently in the system:
Taking advantage of a new feature introduced in Site Studio 7, we can point a regular ‘Select’ field to an internal endpoint to provide the options you see above. This allows us to create one component that can be used an infinite number of times on a website to inject Webforms anywhere an editor would like on a page.
The render method informs the rendering pipeline to insert a placeholder and ‘lazy build’ the result on the page. Finally, the build method is added as the callback for the lazy builder, which returns a simple render array containing the Webform the user selected in the component.
Introducing this change helped us get page load times for authenticated users down from 10–20 seconds in the worst cases to consistently under one second. It also allows the pages to be cached effectively in Cloudflare. For anonymous traffic, pages are loading in the 100–200ms range. Very good!
Site Studio Webform Element Module
We released this fix as a new module for Site Studio and Drupal so everyone can leverage it to get better performance out of their websites. Download it today and use it in Drupal 10 or Drupal 11 with Site Studio 7 or higher.
Want to know more about this module or how you can solve similar performance issues with your Drupal site? Contact us. Our Triple Certified Drupal Expert and team of Drupal specialists will be happy to assist you.