12/3/2020

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));

}

};