Understanding Middleware in Sitecore JSS with Next.js
As you progress through your frontend journey you may have encountered the need to work with middleware in Next.js. These usually involve the need to add custom logic before the request is completed, here are some tasks that might require creating them into middleware.
- Authentication
- Logging
- Rewriting and redirecting
I’ll be tackling how these are integrated into a Sitecore JSS application that uses Next.js where the project structure has the scripts folder setup like below.
The generate-plugins.ts File
Before everything gets built, the bootstrap.ts
file runs and one of the scripts is the generate-plugins
which sets up the needed middleware the project needs. We’re trying to trace how this works because we want to integrate our own custom plugin into how Sitecore does it. When we look into the generate-plugins.ts
file, at the very top you get a good idea of how your file should be setup just so it works properly.
/*
PLUGINS GENERATION
NOTE: pluginName: the name of the plugin in the src/lib folder
Generates the `/src/temp/{pluginName}-plugins.ts` file, which exports list of plugins
Generating the plugins is optional, and it can be maintained manually if preferred.
The default convention uses the plugin's filename (without the extension) as the first part of the component
name. For example, the file `/lib/page-props-factory/plugins/exampleName.ts` would map to plugin `exampleNamePlugin`.
This can be customized in writePlugins().
*/
Based on the guide Sitecore JSS has given us, it seems like on build it generates files inside our temp folder and it uses the folder structure and creates a separate file for each. As we look further down the file you will see another set of logic.
/**
* Generates the plugins file and saves it to the filesystem.
* By convention, we expect to find plugins under src/lib/{pluginName}/plugins/** (subfolders are
* searched recursively). The filename, with extension and non-word characters
* stripped, is used to identify the plugin's JavaScript module definition (for adding
* new plugin to the factory).
* Modify this function to use a different convention.
*/
This further explains how we should add more plugins into the project. You might get overwhelmed and start questioning, “I don’t really see any middleware explained here.” but we’ll get to that. Now that we know how plugins work in JSS in Next.js we can look into what these plugin files are.
Looking Into the Temp Folder
Inside the temp folder we will see a lot of files generated and some of these are plugin files. One of these files should be middleware-plugins.ts
and inside the file you will see a bunch of plugins being exported. The script above generates these lines of code and just so you don’t make a mistake of creating your new plugin, make sure to not include the word plugin on the filename and make sure to add it on the export.
For example you want a plugin named auth, we name the file auth.ts and inside the file your export should look like this.
export const authPlugin = new AuthPlugin();
You will also notice that all the middleware plugins will come from the path lib/middleware/plugins
which should contain all the middleware plugin files.
Creating Your Middleware Plugin
The basic idea when you need to create your new middleware plugin is the code structure below. You will need to specify on which step of the plugin list should this run and the exec function it needs to perform based on your objective. I won’t go too deep since codes written here can be different depending on the objective you are trying to get. Just make sure to restart your container as soon as you’re done since we’ll need the build script to add this into the temp files. That’s pretty much it! Try playing around with the order if something’s not working right or maybe your variables and filenames might be using the wrong casing.
import { NextRequest, NextResponse } from 'next/server';
import { MiddlewarePlugin } from '..';
class AuthPlugin implements MiddlewarePlugin {
order = 2; // Define the execution order if needed
async exec(req: NextRequest, res?: NextResponse): Promise<NextResponse> {
return response;
}
}
export const AuthPlugin = new AuthPlugin();
Where to Go Next with Middleware in Sitecore JSS and Next.js
How Sitecore has integrated JSS into the Next.js project is great and you can build upon it. You just have to be open to taking a look at the code they have in place. The good thing here is they add a lot of helpful comments which can make navigating through the scripts less daunting. You will see inside the scripts folder there are some useful ones like the scaffold-component and generate-component-factory which we’ve already discussed in a previous blog.