Serverless Functions using Next.js API routes

Paul Ho
3 min readMar 15, 2021
Guess who is in the picture ?

Definition

Serverless means build and run applications without thinking about servers.

functions are APIs and APIs are functions

derived from medium article The duality between serverless functions and APIs

Functions are the building blocks of serverless computing. They lend themselves naturally to compositions for reusable components, libraries, and applications. Functions-as-a-service platforms offer a model where functions run in response to events, including HTTP requests. In this way, functions are APIs. Going further, cloud-native applications will often interface to third party services via APIs. In order to promote composition across APIs in a serverless model, it is also necessary to treat HTTP requests for services as functions. And therefore, APIs are also functions.

Serverless Functions by largest cloud companies

AWS Lambda

Microsoft Azure Functions

Google Cloud Functions

Next.js Serverless Functions

Alternatively, we can use Next.js API routes to build serverless functions.

Serverless Functions can be used for every part of your application, including:

Since most serverless functions involved CRUD operation in database. Let’s create a serverless function that performs a query from GraphQL endpoint.

Create a new Next.js project, run:

npx create-next-app next-serverless-functions

Any file inside the folder pages/api is mapped to /api/* and will be treated as an API endpoint instead of a page. They are server-side only bundles and won't increase your client-side bundle size.

By default, Next.js comes with the following API route pages/api/hello.js returns a json response with a status code of 200:

export default (req, res) => {
res.status(200).json({ name: 'John Doe' })
}

Set up Apollo Client in Next.js app, let’s install the packages we need:

npm install @apollo/client graphql

I had created a graphql endpoint from Slash GraphQL. Slash GraphQL is a fully managed GraphQL backend service.

https://winter-tree.ap-south-1.aws.cloud.dgraph.io/graphql

The graphql endpoint had been populated with Pokemon data.

Let’s create new api route pages/api/pokemon.js

An async function is a function declared with the async keyword, and the await keyword is permitted within them. The async and await keywords enable asynchronous, promise-based behavior to be written in a cleaner style, avoiding the need to explicitly configure promise chains.

Create async function in pokemon.js

export default async function handler(req, res) {}

We need to initialize Apollo client before query data from GraphQL endpoint.

import { ApolloClient, InMemoryCache, createHttpLink, gql } from '@apollo/client'const createApolloClient = () => {
return new ApolloClient({
link: new createHttpLink({
uri: '
https://winter-tree.ap-south-1.aws.cloud.dgraph.io/graphql',
}),
cache: new InMemoryCache(),
})
}
const apolloClient = createApolloClient();export default async function handler(req, res) {}

Prepare GraphQL query statement for Pokemon type.

import { ApolloClient, InMemoryCache, createHttpLink, gql } from '@apollo/client'const createApolloClient = () => {
return new ApolloClient({
link: new createHttpLink({
uri: 'https://winter-tree.ap-south-1.aws.cloud.dgraph.io/graphql',
}),
cache: new InMemoryCache(),
})
}
const apolloClient = createApolloClient();const GET_POKEMONS = gql`
query {
queryPokemon {
id
name
imgUrl
pokemonTypes
captured
}
}`;
export default async function handler(req, res) {}

Let’s complete the async function handler

If query successful, returns query data as json response with a status code of 200

export default async function handler(req, res) {
try {
const { data } = await apolloClient.query({
query: GET_POKEMONS,
})
res.statusCode = 200
res.setHeader('Content-Type', 'application/json')
res.json({ data })
} catch (error) {
console.error(error);
res.status(error.status || 500).end(error.message);
}
}

The final code is ready to run,

test it out in localhost with command npm run dev and go to http://localhost:3000/api/pokemon

You can find the final code in github repo

See you in next post.

--

--