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 theawait
keyword is permitted within them. Theasync
andawait
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.