More and more cloud hosting providers and software-as-a-service platforms are offering serverless functions at The Edge. But what is The Edge? What are Edge Functions? And why does it matter?
First, let's learn a little bit about serverless functions.
What is a serverless function?
Contrary to what the term suggests, serverless actually doesn't mean the absence of a server! Serverless is a model that removes the limitations and constraints from traditional physical or virtual servers, allowing developers to build and scale applications by considering only the functions that need to be run, rather than needing to manage the overheads of persistently running applications. It's a simpler, more cost-effective way to build and run applications in the cloud.
A server is essentially a computer connected to the internet that can store data, and store and execute code. "Backend code" such as APIs that read and write information to a database need a running server to execute. Before the dawn of serverless and "The Cloud" in around 2008-2010, in order to run any code that required a server, you had to store and run that code on your own physical servers (or computers), and maintain, manage and scale them yourself.
For small projects, you could get away with hosting a server on your computer at home — but this doesn't scale when you have thousands of website visitors around the world generating millions of requests! Larger businesses required a group of networked physical servers to ensure a fast experience for users — and the cost of running these physical servers could get expensive very quickly!
Serverless functions are a backend as a service — on demand. Cloud hosting providers such as Netlify, AWS and Vercel have offered serverless functions for a few years now, meaning that everyone from hobby developers to large businesses can execute backend code on demand, without having to manage, maintain and scale their own servers. When you run a serverless function on a cloud hosting provider, you pay only for the processing required, and you don't need to worry about increasing the number of servers available when your website traffic grows — it's all taken care of for you.
What's more, most cloud providers come with generous free plans, so you can usually run hobby projects that use serverless functions at little to no financial cost.
Serverless and Jamstack
Serverless is an adjacent technology to the Jamstack architecture, and together they can achieve great things! Jamstack's core offering centres around serving pre-generated static assets, which are bundled up at build-time, from a Content Delivery Network (CDN). A CDN is a network of servers, distributed around the world, working together to serve cached content to users from the closest server location possible. As a result, people around the world get a fast experience on static sites served by a CDN. Netlify has a great explanation of how their CDN works on this blog post from 2016.
What is The Edge?
A CDN is also known as an Edge Network, referring to the servers that sit on the "edge" of multiple networks, which act as bridges to route traffic between networks across the CDN. Serverless functions have historically been restricted to running on servers in specific locations. Take for example, the US West server on AWS. For me, making a request to US West from the UK takes longer than making a request to one of the European servers, due to the distance the data has to travel across the wire.
If you're using serverless functions for server side rendering to enrich your Jamstack site, you need high availability on global servers in order to make your website fast for everyone in the world, and an intelligent network which knows how to route requests to the closest location to the user. And this is now possible with Edge Functions!
Edge Functions are serverless functions at The Edge
Edge Computing — running code at The Edge — now gives developers the power to execute serverless functions at the closest location to a request. Using Edge Computing, developers can collectively make the web faster and more accessible to more people, and we may also begin to see a reduction in carbon emissions as a result of data being served quicker over a shorter distance.
Last week, Netlify released Edge Functions, and you can now add Edge Functions to any new or existing project on Netlify. What's more, if you're on a starter plan, you can execute up to 3 million Edge Functions per month!
Edge Functions on Netlify
Edge Functions are very much like serverless functions. You can write them using JavaScript or TypeScript, but instead of using Node.js under the hood, they are powered by Deno — an open source runtime built on web standards. With Netlify Edge Functions, you can transform HTTP Requests and Responses, stream server rendered content, and even run full server side rendered applications at The Edge!
Hello, world!
Let's take a look at writing "Hello, world" as a Netlify Edge Function using TypeScript.
Create a new project directory, and run npm init
to create a package.json file by entering the following in your terminal.
mkdir my-edge-functions-project
cd my-edge-functions-project
npm init
Create the following directories and files inside your project folder.
- netlify > edge-functions > hello.ts
- netlify.toml
Next, open up the netlify.toml file and add an [[edge_functions]]
entry for the hello.ts function.
# netlify.toml
[[edge_functions]]
path = "/hello"
function = "hello"
Copy and paste the following code into hello.ts
.
// netlify/edge-functions/hello.ts
import type { Context } from "https://edge.netlify.com";
export default async (request: Request, context: Context) => {
return new Response("Hello, World!", {
headers: { "content-type": "text/html" },
});
};
Note: You might see a red underline under the type import if you're using VS Code. The Edge Function will still execute, but if you'd like to say goodbye to the red line, run ntl recipes vscode
in your terminal. This will install a VS Code settings directory and JSON file at the root of your project. Read more about Netlify recipes on the CLI docs.
We start by exporting a default async function
which receives two arguments.
- A standard Request object representing the incoming HTTP request
- A Netlify-specific Context object which comes with a LOT of useful functionality
The return value from an Edge Function is either:
- a standard Response object representing the HTTP response to be delivered to the client
- undefined (if you choose to bypass the current function)
Using the Netlify CLI (make sure you've got the latest version!), run netlify dev in your terminal, and navigate to the path in your browser specified in the netlify.toml file, which should be https://localhost:8888/hello.
And bam! You've executed an Edge Function in your local development environment!
Deploy your site to Netlify, and Netlify will automatically bundle your Edge Function code. Visit your new site at {your_site_name}/hello, and boom! Now you're running a serverless function on Netlify's edge network!
Now you have an Edge Function running on Netlify, let's explore what else is possible with the Netlify Context object and more.
What else is possible?
The Netlify Context object comes bundled with Edge-specific APIs and utility methods including a Geolocation API, Cookies API and handy log()
and json()
helpers. Let's look at some of my favourites.
Geolocation API
You can use Edge Functions to get information about a user's location to serve location-specific content and personalise their experience. Geolocation information is available on the Context.geo
object. In hello.ts, console.log
out the Context.geo
object to view your geolocation data in the terminal!
// netlify/edge-functions/hello.ts
import type { Context } from "https://edge.netlify.com";
export default async (request: Request, context: Context) => {
// Let's inspect the geolocation data!
console.log(context.geo);
return new Response("Hello, World!", {
headers: { "content-type": "text/html" },
});
};
Here's mine!
Context.json() method
We can return the geolocation data to the browser as JSON using a convenience method available on the Context object. Instead of returning a standard Response of type text/html, we can return the data using context.json()
, like so:
// netlify/edge-functions/hello.ts
import type { Context } from "https://edge.netlify.com";
export default async (request: Request, context: Context) => {
// Send the geolocation data as JSON to the browser!
return context.json(context.geo);
};
And here's what we see in the browser!
Proxy requests to other APIs
As developers we often work with third-party APIs to get and post data. Edge Functions allow us to use fetch() (without an import!) to make requests to other sources. Here's an example of requesting data from a third-party API, and returning that data as JSON.
import { Context } from "https://edge.netlify.com";
export default async (request: Request, context: Context) => {
const joke = await fetch("https://icanhazdadjoke.com/", {
"headers": {
"Accept": "application/json"
}
});
const jsonData = await joke.json();
return context.json(jsonData);
};
Deploy your own and explore
Phil Hawksworth and I put together an Edge Functions Examples site for you to explore the APIs and functionality available to you on Netlify. You can also browse the source code on GitHub, fork the repository, or copy and paste code examples to your project.
If you want to deploy your own version of the site to Netlify, there's also a handy "Deploy to Netlify" button on the example site.
Watch the video
I tried out Netlify Edge Functions during the launch week live on Twitch. Catch up on the stream below for an explanation of The Edge, a walkthrough of the Netlify documentation, and a showcase of the Edge Functions Examples site.
In short, taking serverless to The Edge is making the web faster, more accessible, and more personalised. Things like this make me excited for the future of the web and I can't wait to see what's next!