Using Next.JS API Routes
Next.JS comes with a useful feature out of the box, api routes. Files created in the `pages/api/` folder are treated as an endpoint rather than a page. Instead of exporting a React component to display your UI, you can export a function returning, say, a JSON response.
- nextjs
- api
- serverless
Next.JS comes with a useful feature out of the box, api routes. Files created in the pages/api/ folder are treated as an endpoint rather than a page. Instead of exporting a React component to display your UI, you can export a function returning, say, a JSON response.
For example, if you wanted to return a blog post from your CMS, you could write the following in file pages/api/post.js :
/**
* NextJS API function
* https://nextjs.org/docs/api-routes/introduction)
*/
export default (request, response) => {
res.statusCode = 200;
res.setHeader('Content-Type', 'application/json');
res.end(JSON.stringify({ title: 'My Blog Post' }));
};
If we wanted to handle multiple methods in a single route, we could check the method property from the request object.
export default (req, res) => {
switch (req.method) {
case 'GET':
// process GET requests
break;
case 'POST':
// process POST requests
break;
default:
res.status(405).end(); //Method Not Allowed
// process every other method
break;
}
};
API Routes also support Next.JS dynamic routes and can be used used to pass a query to our routes.
For example, if we wanted to fetch our posts based on their uid, we could write the following in the file pages/api/post/uid].js
export default async (req, res) => {
// use the uid from the reauest's query to fetch our post from our CMS
const post = await fetchPostFromCMS(req.query.uid);
res.statusCode = 200;
res.end(JSON.stringify(post));
};
Bonus
One great use for API functions is creating a sitemap for your Next.JS project. The function below is the very same code for our website here.
import { NextApiRequest, NextApiResponse } from 'next';
import { SitemapStream, streamToPromise } from 'sitemap';
import posts from '../blog/post-index';
export default async (req: NextApiRequest, res: NextApiResponse) => {
try {
const smStream = new SitemapStream({
hostname: `https://${req.headers.host}`,
});
// Create each URL row for each static page
staticPages.forEach((page) => {
smStream.write({
changefreq: 'monthly',
priority: 0.5,
...page,
});
});
// Create each URL row for each blog post
Object.entries(posts).forEach(([name, metadata]) => {
smStream.write({
title: name,
url: `/blog/${metadata.slug}`,
changefreq: 'weekly',
priority: 0.9,
});
});
// End sitemap stream
smStream.end();
// XML sitemap string
const sitemapOutput = (await streamToPromise(smStream)).toString();
// Change headers
res.writeHead(200, {
'Content-Type': 'application/xml',
});
res.end(sitemapOutput);
} catch (e) {
console.log(e);
res.send(JSON.stringify(e));
}
};