On-Demand ISR Support for Next.js/Faust.js on WP engine’s headless WordPress Platform

Francis Agulto Avatar

·

WP engine’s headless WordPress hosting platform is the go-to end-to-end solution for the headless approach. In this article, I will discuss and guide you through the easy implementation of the latest feature on the platform: Support for On-Demand ISR on Next.js/Faust.js. By the end of this article, you will have a better understanding of On-Demand ISR and using the headless WP platform to support it with Next.js/Faust.js.

Prerequisites

Before reading this article, you should have the following prerequisites checked off:

  • Basic knowledge of Next.js and Faust.js.
  • A WP engine headless WordPress account and environment set up.
  • Node.js and npm are installed on your local machine.

If you do not and need a basic understanding of Next.js and Faust.js, please visit the docs:

https://nextjs.org/docs

https://faustjs.org/tutorial/get-started-with-faust

What is On-Demand ISR?

On-Demand Incremental Static Regeneration (ISR) is a feature that allows you to manually purge the Next.js cache for specific pages, enabling more dynamic and timely updates to your site. Typically, in regular ISR when you set a revalidate time, such as 60 seconds, all visitors will see the same generated version of your site for that duration. The cache is only invalidated when someone visits the page after the revalidation period has passed.

With the introduction of On-Demand ISR in Next.js version 12.2.0, you can now trigger cache invalidation manually, providing greater flexibility in updating your site. This is particularly useful when:

  • Content from your headless CMS is created or updated.
  • E-commerce metadata changes, such as price, description, category, or reviews, are made.

This feature streamlines the process of reflecting changes on your site in real-time, ensuring that your content is always fresh and up-to-date.

Why Use it in headless WordPress?

In headless WordPress, the front end is decoupled from the WordPress backend, often using Next.js and Faust.js to render the website. This architecture offers several advantages, such as potential for improved performance, enhanced security, and greater flexibility in choosing front-end technologies.

However, one challenge with headless WordPress is ensuring that content changes in WordPress are reflected on the front end without sacrificing performance. This is where On-Demand ISR becomes crucial. By leveraging On-Demand ISR, you can achieve the following benefits:

Up-to-date Content: On-Demand ISR allows your site to fetch the latest content updates from WordPress manually, as needed. Unlike regular ISR, which checks for updates at specified intervals, On-Demand ISR lets you trigger cache invalidation whenever content is created or updated in WordPress. This ensures that users see the most recent content without waiting for a revalidation period.

Enhanced Performance: Since On-Demand ISR updates only the specific pages that need regeneration at the moment they are triggered, your site remains fast and responsive. Initial load times are minimized, and only the changed content is updated, reducing server load and build times.

SEO Benefits: Static pages are highly favored by search engines due to their speed and reliability. With On-Demand ISR, you maintain the SEO advantages of static generation while ensuring that your content is always fresh and relevant, as updates are reflected immediately after they are triggered.

Scalability: On-Demand ISR enables your site to handle large volumes of content efficiently. Whether you’re running a blog with frequent updates or an e-commerce site with dynamic product listings, On-Demand ISR ensures that your site scales seamlessly.

All those benefits got me stoked! Let’s get it on our Next.js and Faust.js sites!

Configuring Next.js with the headless WP Platform for On-Demand ISR

Let’s configure our Next.js application to work with On-Demand ISR.

Here is the docs link to the headless WordPress platform support for On-Demand ISR.

Atlas-Next Package

In your Next.js project, go to your terminal and install the @wpengine/atlas-next package:

npm install --save @wpengine/atlas-next

This package provides improved support on the headless WP platform. Once you install it, ensure it is in your project by navigating to your package.json file at the root of your project:

{
  "name": "atlas-on-demand-isr",
  "version": "0.1.0",
  "private": true,
  "scripts": {
    "dev": "next dev",
    "build": "next build",
    "start": "next start",
    "lint": "next lint"
  },
  "dependencies": {
    "@wpengine/atlas-next": "^1.3.0-beta.0",
    "next": "14.2.4",
    "react": "^18",
    "react-dom": "^18"
  },
  "devDependencies": {
    "eslint": "^8",
    "eslint-config-next": "14.2.4",
    "postcss": "^8",
    "tailwindcss": "^3.4.1"
  }
}

Code language: JSON / JSON with Comments (json)

Now that you have verified the proper installation, staying at the root of your project,  modify your next.config.js file like so:

const { withAtlasConfig } = require("@wpengine/atlas-next");

/** @type {import('next').NextConfig} */

const nextConfig = {

 // Your existing Next.js config

};

module.exports = withAtlasConfig(nextConfig);
Code language: PHP (php)

Faust.js Wrapper

If you are using Faust.js, all you need to do is modify your next.config.js file using the withFaust wrapper:

const { withFaust } = require("@faustwp/core")
const { withAtlasConfig } = require("@wpengine/atlas-next")

/** @type {import('next').NextConfig} */
const nextConfig = {
  // Your existing Next.js config
}

module.exports = withFaust(withAtlasConfig(nextConfig))

Code language: PHP (php)

Next, we need to verify that it works.  Run your app in dev mode via npm run dev and you should see this output in your terminal:

Stoked! It works!

Create an API route

The first thing we need to do is create an API route.  This will allow you to pass the path to be revalidated as a parameter.

Step 1. Create the API route file: Navigate to the pages/api directory in your Next.js project and create a new file named revalidate.js.

Step 2. Add the API Route code: Open revalidate.js and add the following code:

export default async function handler(req, res) {
  // Check for a secret token to authenticate the request
  if (req.query.secret !== process.env.MY_SECRET_TOKEN) {
    return res.status(401).json({ message: 'Invalid token' });
  }

  const path = req.query.path;

  // Ensure the path parameter is provided
  if (!path) {
    return res.status(400).json({ message: 'Path query parameter is required' });
  }

  try {
    // Revalidate the specified path
    await res.revalidate(path);
    return res.json({ revalidated: true });
  } catch (err) {
    return res.status(500).json({ message: 'Error revalidating', error: err.message });
  }

Code language: JavaScript (javascript)

Step 3.  Configure the environment variables: Create a .env.local file in the root of your project if it does not exist already.

Step 4. Next, create a secret token. This code sets up an API route that checks for a secret token for security, validates the presence of the path parameter, and triggers the revalidation of the specified path.

Once you have Node.js installed, you can use it to generate a secret token.

Open Your Terminal: Start by opening your terminal or command prompt.

Generate a Secret Token: Run the following command in your terminal:

node -e "console.log(require('crypto').randomBytes(32).toString('hex'))

This command uses the crypto module to generate a 32-byte random string in hexadecimal format. The output will be your secret token.

Once the token is generated, copy and paste it into your .env.local file and give it an environment variable name e.g. `REVALIDATION_SECRET` 

It should look like this: REVALIDATION_SECRET=your-secret-key

Use the API route to configure cache revalidation

To configure cache revalidation in the headless WordPress setup, you could follow one of the approaches below:

Use a webhook plugin: You can use plugins like WP Webhooks to enable webhook functionality and trigger the API endpoint you’ve just created when relevant events occur, such as when a post is published or updated.

When you have your secret key generated and need an API endpoint, append a query string parameter to it with the key and value pair, where the key is secret and the value is the secret token. For instance:

http://localhost:3000/api/revalidate?secret=your-secret-key

This is the endpoint you can embed in a field that requires it when using a plugin like WP Webhooks. The field will correlate to whatever action will happen when the endpoint is hit such as updating a post.  

Set up WordPress hooks: You can also add actions in your WordPress theme or plugin to send requests to your Next.js API route. Here’s an example using the wp_remote_post function in php, which will send a POST request to the Next.js API route whenever a post is saved in WordPress, triggering the revalidation of the corresponding path:

function trigger_revalidation($post_id) {
  $url = 'https://your-nextjs-site.com/api/revalidate?secret=your-secret-token&path=' . get_permalink($post_id);
  
  $response = wp_remote_post($url);

  if (is_wp_error($response)) {
    error_log('Error triggering revalidation: ' . $response->get_error_message());
  }
}
add_action('save_post', 'trigger_revalidation');
Code language: PHP (php)

Headless WordPress Platform User Portal

We now have On-Demand ISR set up with the proper configuration. The last steps are to connect our remote repository to WP engine’s headless WP platform, git push any changes, and observe On-Demand ISR working in all its cache invalidation glory.

If you have not connected your local project to a remote repository, go ahead and do so.  WP engine headless platform supports GitHub, Bitbucket, and GitLab.

Once you have connected your remote repository and added all your necessary environment variables, go ahead and build the app. If you have done this with an existing repo, you can git push the change, which will trigger a build.

When the application is finished in the build step, you are on the main page of the WP engine headless WP portal.  Navigate over to the Logs subpage:

In the Logs subpage, click the “Show logs” button on the Runtime option:

You should see the same output focusing on line 6 as you did in your terminal to ensure it’s working properly:

Awesome!!! It is implemented and working in runtime.  Now, when you edit or input new content in your WP backend, and then visit the live URL of the WP engine headless WP site you just deployed, the ISR should work on demand like so:

Limitations

At the moment, the headless WP platform supports On-Demand ISR with the following limitations:

  1. Requires @wpengine/atlas-next package: To enable On-Demand ISR on Atlas, you must use the @wpenngine/atlas-next package and follow the setup steps outlined in the previous sections of this document.
  2. On-demand ISR for App Router is not supported: The App Router is a new routing system in Next.js that enhances routing capabilities with features like server components and nested layouts. However, Atlas currently supports On-Demand ISR only in the context of the traditional Pages Router. This means that methods like revalidatePath and revalidateTag, which are used for revalidation in the App Router, are not compatible with the headless WP platform’s ISR mechanism. For more details on the App Router and its data fetching methods, you can refer to the Next.js documentation here.
  3. Rewrites are not supported: Rewrites in Next.js allow you to change the destination URL of a request without altering the URL visible to the user. However, On-Demand ISR on the headless WP platform does not support rewrites. This means that if your Next.js application relies on rewrites, the On-Demand ISR feature might not function as expected. You can learn more about rewrites here.
  4. Not compatible with Next.js I18N: Since Next.js uses rewrites for internationalization, this feature is not supported on the headless WP platform due to the rewrite limitation mentioned above.
  5. Next.js >=13.5 is required: To be able to use this feature, you need to update your application to Next.js version 13.5 or higher.

NoteRedirects (which, unlike rewrites, actually change the URL in the user’s browser to the specified destination) are supported.

If you want to give us feedback on how we can make things better for this feature or anything else with the platform, please visit our feedback form.

Conclusion

Implementing On-Demand Incremental Static Regeneration (ISR) with Next.js and Faust.js on WP engine’s headless WP platform is a game-changer for maintaining performance and up-to-date content in a headless WordPress setup. By following the steps outlined in this guide, you can leverage On-Demand ISR to ensure your site remains both fast and current, without the need for full rebuilds. 

The integration with the platform also simplifies the deployment and management process, providing a seamless workflow from development to production. 

As always, we look forward to hearing your feedback, thoughts, and projects so hit us up in our headless Discord!