Edge-Functions on Next.JS! Yay or Nay?

Rajdeep Chandra
5 min readJan 11, 2023

--

Source: Google

In Next.js, an edge function is a middleware that runs on the edge of a content delivery network (CDN) rather than on the server. These functions are designed to run close to the client, which can make them well-suited for tasks that need to be performed quickly and with low latency, such as authentication, caching, and image processing. Edge functions allow developers to run custom code on the CDN, which can help offload some workloads from the server and improve the performance and scalability of their applications.

Some example use-cases:

  1. Authentication: You can use an edge function to authenticate incoming requests before they reach your server. This can help protect your application from unauthorized access and reduce the load on your server.
  2. Caching: You can use an edge function to cache frequently-requested assets, such as images and JSON data, on the CDN. This can reduce the number of requests that need to be sent to your server, which can improve the performance and scalability of your application.
  3. Image Processing: You can use an edge function to manipulate images on the fly, such as by resizing or compressing them. This can help reduce the load on your server and improve the performance of your application, especially if you are serving large numbers of images.
  4. Redirection: You can use an edge function to perform redirection of incoming requests, for example for maintaining different versions of the same site or for redirecting based on certain headers, by providing a more efficient and low-latency way.

How to create one Edge function in Next.js

First, you would need to create a new file in your project’s root directory called next.config.js and inside this file you can define your edge function:

const { createServer } = require('http');
const { parse } = require('url');

module.exports = {
async onRequest(req, res) {
// Parse the request URL
const parsedUrl = parse(req.url, true);
// Check if the request is for an authenticated route
if (parsedUrl.pathname === '/secret') {
// Get the authentication token from the request headers
const authToken = req.headers.authorization;
// Validate the token
if (authToken !== 'mysecretkey') {
// Send a 401 Unauthorized response if the token is not valid
res.statusCode = 401;
res.setHeader('Content-Type', 'text/plain');
res.end('Unauthorized');
return;
}
}
// Pass the request on to the Next.js server if it is not for an authenticated route or if the token is valid
return createServer((req, res) => app.getRequestHandler()(req, res)).listen(3000);
},
};

This is a simple example of how you might use an edge function to authenticate incoming requests. In this example, the edge function checks the request URL to see if it is for an authenticated route. If it is, it checks the request headers for an authentication token. If the token is not present or is not valid, the function sends a 401 Unauthorized response. If the token is valid, the request is passed on to the Next.js server to be handled as usual.

You should be aware that this code is just an example, you will have to adjust it to match your specific use case, and not suitable for production.

You should also keep in mind that this type of authentication only works for routes that are being handled by the Next.js server, and not for dynamic routes.

You should also consider using more advanced authentication techniques like using JWT token and verify them in your middleware, that way you are sure that your routes are secure.

Edge function to compress image on the fly

const { createServer } = require('http');
const { parse } = require('url');
const sharp = require('sharp');

module.exports = {
async onRequest(req, res) {
// Parse the request URL
const parsedUrl = parse(req.url, true);
// Check if the request is for an image
if (parsedUrl.pathname.startsWith('/images')) {
// Get the requested width and height from the query string
const width = parsedUrl.query.width;
const height = parsedUrl.query.height;
// Get the path to the image file on the server
const imagePath = `public${parsedUrl.pathname}`;
// Use the Sharp library to resize the image
sharp(imagePath)
.resize(width, height)
.toBuffer()
.then(data => {
// Set the Content-Type header and send the resized image
res.setHeader('Content-Type', 'image/jpeg');
res.end(data);
})
.catch(err => {
// Send a 500 Internal Server Error response if there was an error
console.error(err);
res.statusCode = 500;
res.setHeader('Content-Type', 'text/plain');
res.end('Internal Server Error');
});
return;
}
// Pass the request on to the Next.js server if it is not for an image
return createServer((req, res) => app.getRequestHandler()(req, res)).listen(3000);
},
};

In this example, the edge function checks the request URL to see if it is for an image file. If it is, it gets the requested width and height from the query string, and then uses the Sharp library to resize the image to the specified dimensions. The resized image is then sent back to the client. If there is an error, the function sends a 500 Internal Server Error response.

Just like before, this is just an example, and you would need to adjust it to match your specific use case and for production. Also, you would need to set the correct configuration in your next.config.js and make sure that the correct dependencies are in your project.

Using edge functions in this way can offload some of the processing required to generate the images from your server, which can help improve the performance and scalability of your application.

Edge function to perform redirection

const { createServer } = require('http');
const { parse } = require('url');

module.exports = {
async onRequest(req, res) {
// Parse the request URL
const parsedUrl = parse(req.url, true);
// Check the request headers for a custom header
const customHeader = req.headers['x-custom-header'];
// If header is present, redirect
if (customHeader){
res.statusCode = 301;
res.setHeader('Location', 'https://new-site.com');
res.end();
return;
}
// Pass the request on to the Next.js server if it doesn't have custom header
return createServer((req, res) => app.getRequestHandler()(req, res)).listen(3000);
},
};

In this example, the edge function checks the request headers for a custom header named x-custom-header, if it is present it redirects the user to a new specified location (in this case 'https://new-site.com'). If it is not present, it passes the request to the Next.js server to be handled as usual.

As you can see, this is a simple example that shows one of the use cases you can use to perform redirects, you can adapt it to your needs, like redirect based on some condition or create a dynamic path based on certain variables. Also, as with the previous examples this code is only for demonstration and not suitable for production.

It’s important to mention that you should use a 301 status code for a permanent redirect and 302 for a temporary redirect.

--

--