{"id":7708,"date":"2021-10-26T23:53:06","date_gmt":"2021-10-26T18:53:06","guid":{"rendered":"https:\/\/ahmadawais.com\/?p=7708"},"modified":"2021-10-27T00:00:36","modified_gmt":"2021-10-26T19:00:36","slug":"vercel-edge-functions-next-js","status":"publish","type":"post","link":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/","title":{"rendered":"Vercel Edge Functions with Next.js"},"content":{"rendered":"<p>Vercel&#8217;s Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on Next.js using Vercel will have access to a super useful middleware.<\/p>\n<p>I&#8217;ll be deleting a bunch of infrastructure code and probably thousands of lines of code that I have now for things like basic auth and purchasing power parity. This is pretty amazing.<\/p>\n<h2 id=\"edge-functions\">Edge Functions<a href=\"#edge-functions\" class=\"heading-link\">#<\/a><\/h2>\n<blockquote><p>Traditionally there are two ways to serve content, statically from a Content Delivery Network (CDN) close to the user for fast response times, or dynamically, with personalization configured at the server level on each request.<\/p>\n<p>When deciding on how you want to deliver content to your application visitors, you have to take into consideration the trade-offs that each of these two options offer.<\/p>\n<p>A static page will deliver the same content to all visitors, no matter where they are in the world, and it will be fast as it&#8217;s cached by the CDN. But this approach may not be viable if you want to deliver personalized content, depending on, for example, where a user is located in the world.<\/p>\n<p>To give your user a personalized experience, you can take advantage of server-side rendering to create dynamic content on each request to your sites pages. This will enable you to offer different content to people based on their location, authenticate them, or configure the language of your site.<\/p>\n<p>The drawback of this approach is that it can be slower. If the server processing the request is far away from the visitors origin, then the request can take time to complete, and the content may not be available to the user at the speed offered by serving purely static content.<\/p><\/blockquote>\n<h3 id=\"what-are-edge-functions\">What are Edge Functions?<a href=\"#what-are-edge-functions\" class=\"heading-link\">#<\/a><\/h3>\n<blockquote><p>To achieve both speed and dynamism, you can use Edge Functions. They allow you to deliver content to your sites visitors with speed and personalization, are deployed globally by default on Vercel&#8217;s Edge Network, and have zero cold starts. They enable you to move server-side logic to the Edge, close to your visitors origin.<\/p>\n<p>To use Edge Functions, you can deploy Middleware. Middleware is code that executes before a request is processed. Depending on the incoming request, you can execute custom logic, rewrite, redirect, add headers and more, before returning a response.<\/p><\/blockquote>\n<h2 id=\"middleware-vercel-nextjs\">Middleware (Vercel &amp; Nextjs)<a href=\"#middleware-vercel-nextjs\" class=\"heading-link\">#<\/a><\/h2>\n<blockquote><p>The middleware function runs code before a request is completed, then based on the request, you can modify the response. It can be used for anything that shares logic between pages.<\/p>\n<p>It takes two parameters, request, and event. The request parameter is an extension of the native Request interface and has added methods and properties that include accessing cookies, getting geolocation from an IP Address, and user-agent info. You can import its type definition with<br \/>\nNextRequest.<\/p>\n<p>In addition, you can import the NextResponse API, which extends the native Response interface and lets you redirect, rewrite, cookies, and clear cookies.<\/p><\/blockquote>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\" class=\"lean geist-text h3\" data-components-heading=\"true\" id=\"middleware-use-cases\">Middleware use-cases<a href=\"#middleware-use-cases\" class=\"heading-link\">#<\/a><\/h3>\n<div class=\"jsx-960901022 geist-container lg-row\">\n<div>\n<div class=\"jsx-2223033313 row\">\n<ul>\n<li class=\"jsx-2223033313 icon\"><a class=\"link_old_link__1gRam\" href=\"https:\/\/github.com\/vercel\/examples\/tree\/main\/edge-functions\/basic-auth-password\">Authentication<\/a><\/li>\n<li class=\"jsx-2223033313 icon\"><a class=\"link_old_link__1gRam\" href=\"https:\/\/github.com\/vercel\/examples\/tree\/main\/edge-functions\/bot-protection-botd\">Bot Protection<\/a><\/li>\n<li><a class=\"link_old_link__1gRam\" href=\"https:\/\/github.com\/vercel\/examples\/tree\/main\/edge-functions\/redirects-upstash\">Redirects<\/a><\/li>\n<li>Browser Support<\/li>\n<li><a class=\"link_old_link__1gRam\" href=\"https:\/\/github.com\/vercel\/examples\/tree\/main\/edge-functions\/feature-flag-apple-store\">Feature Flags<\/a><\/li>\n<li><a class=\"link_old_link__1gRam\" href=\"https:\/\/github.com\/vercel\/examples\/tree\/main\/edge-functions\/ab-testing-simple\">A\/B Testing<\/a><\/li>\n<li>Server-Side Analytics<\/li>\n<li>Logging<\/li>\n<\/ul>\n<\/div>\n<\/div>\n<\/div>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"how-to-use-middleware\" class=\"jsx-4241549934 target\"><\/span>How to use Middleware<\/h3>\n<blockquote>\n<p class=\"geist-text p\">To start using Middleware in your Next.js project, begin by upgrading to the latest Next.js version. The following steps will guide you through the process. Note that the below example uses TypeScript, though this is <span class=\"jsx-219205317\">not<\/span> a requirement.<\/p>\n<\/blockquote>\n<ol>\n<li class=\"jsx-3358961161\">\n<p class=\"geist-text p\">Install the latest version of <code class=\"code_code__3jDWG\">next<\/code>:<\/p>\n<pre class=\"lang:bash\">npm install next@latest \r\n\r\n# or \r\nyarn upgrade next@latest\r\n<\/pre>\n<\/li>\n<li class=\"jsx-3358961161\">\n<p class=\"geist-text p\">Next, create a <code class=\"code_code__3jDWG\">_middleware.ts<\/code> file under your <code class=\"code_code__3jDWG\">\/pages<\/code> directory.<\/p>\n<pre class=\"lang:bash\">- \/pages\r\n  _middleware.ts\r\n- package.json\r\n<\/pre>\n<\/li>\n<li class=\"jsx-3358961161\">\n<p class=\"geist-text p\">Finally, create function in the <code class=\"code_code__3jDWG\">_middleware.ts<\/code> file.<\/p>\n<pre class=\"lang:javascript\">export default function middleware(req, ev) {\r\n  return new Response({\r\n    body: 'Hello, world!',\r\n  });\r\n}<\/pre>\n<\/li>\n<\/ol>\n<p class=\"geist-text p\">When you deploy your site, your Middleware will work out of the box<\/p>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"api\" class=\"jsx-4241549934 target\"><\/span>API<\/h3>\n<p class=\"geist-text p\">Middleware is created by using a <code class=\"code_code__3jDWG\">middleware<\/code> function that lives inside a <code class=\"code_code__3jDWG\">_middleware<\/code> file. Its API is based upon the native <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/FetchEvent\"><code class=\"code_code__3jDWG\">FetchEvent<\/code><\/a>, <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Response\"><code class=\"code_code__3jDWG\">Response<\/code><\/a>, and <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Request\"><code class=\"code_code__3jDWG\">Request<\/code><\/a> objects.<\/p>\n<p class=\"geist-text p\">These native Web API objects are extended to give you more control over how you manipulate and configure a response, based on the incoming requests.<\/p>\n<p class=\"geist-text p\">The function signature:<\/p>\n<pre class=\"lang:javascript\">import type { NextFetchEvent } from 'next\/server';\r\nimport type { NextRequest } from 'next\/server';\r\n\r\nexport type Middleware = (\r\n  request: NextRequest,\r\n  event: NextFetchEvent,\r\n) =&gt; Promise&lt;Response | undefined&gt; | Response | undefined;<\/pre>\n<p class=\"geist-text p\">The function can be a default export and as such, does <span class=\"jsx-219205317\">not<\/span> have to be named <code class=\"code_code__3jDWG\">middleware<\/code>. Though this is a convention. Also, note that you only need to make the function <code class=\"code_code__3jDWG\">async<\/code> if you are running asynchronous code.<\/p>\n<blockquote>\n<div class=\"note_note__2M1Dh geist-themed geist-warning\" data-geist-note=\"\">\n<p><span class=\"geist-text span\"><b>Warning: <\/b><\/span>Edge Functions are currently in Beta. The API might change as we look to continually make improvements.<\/p>\n<div class=\"note_action__3VvR0\"><\/div>\n<\/div>\n<\/blockquote>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"nextfetchevent\" class=\"jsx-4241549934 target\"><\/span>NextFetchEvent<\/h4>\n<p class=\"geist-text p\">The <code class=\"code_code__3jDWG\">NextFetchEvent<\/code> object extends the native <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/FetchEvent\"><code class=\"code_code__3jDWG\">FetchEvent<\/code><\/a> object, and includes the <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/ExtendableEvent\/waitUntil\"><code class=\"code_code__3jDWG\">waitUntil()<\/code><\/a> method.<\/p>\n<p class=\"geist-text p\">The <code class=\"code_code__3jDWG\">waitUntil()<\/code> method can be used to prolong the execution of the function, after the response has been sent. In practice this means that you can send a response, then continue the function execution if you have other background work to make.<\/p>\n<p class=\"geist-text p\">An example of <em>why<\/em> you would use <code class=\"code_code__3jDWG\">waitUntil()<\/code> is integrations with logging tools such as <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/sentry.io\/\">Sentry<\/a> or <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/www.datadoghq.com\/\">DataDog<\/a>. After the response has been sent, you can send logs of response times, errors, API call durations or overall performance metrics.<\/p>\n<p class=\"geist-text p\">The <code class=\"code_code__3jDWG\">event<\/code> object is fully typed and can be imported from <code class=\"code_code__3jDWG\">next\/server<\/code>.<\/p>\n<pre class=\"lang:javascript\">import { NextFetchEvent } from 'next\/server';<\/pre>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"nextrequest\" class=\"jsx-4241549934 target\"><\/span>NextRequest<\/h4>\n<p class=\"geist-text p\">The <code class=\"code_code__3jDWG\">NextRequest<\/code> object is an extension of the native <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Request\"><code class=\"code_code__3jDWG\">Request<\/code><\/a> interface, with the following added methods and properties:<\/p>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">cookies<\/code> &#8211; Has the cookies from the <code class=\"code_code__3jDWG\">Request<\/code><\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">nextUrl<\/code> &#8211; Includes an extended, parsed, URL object that gives you access to Next.js specific properties such as <code class=\"code_code__3jDWG\">pathname<\/code>, <code class=\"code_code__3jDWG\">basePath<\/code>, <code class=\"code_code__3jDWG\">trailingSlash<\/code> and <code class=\"code_code__3jDWG\">i18n<\/code><\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">geo<\/code> &#8211; Has the geo location from the <code class=\"code_code__3jDWG\">Request<\/code>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">geo.country<\/code> &#8211; The country code<\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">geo.region<\/code> &#8211; The region code<\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">geo.city<\/code> &#8211; The city<\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">geo.latitude<\/code> &#8211; The latitude<\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">geo.longitude<\/code> &#8211; The longitude<\/li>\n<\/ul>\n<\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">ip<\/code> &#8211; Has the IP address of the <code class=\"code_code__3jDWG\">Request<\/code><\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">ua<\/code> &#8211; Has the user agent<\/li>\n<\/ul>\n<p class=\"geist-text p\">You can use the <code class=\"code_code__3jDWG\">NextRequest<\/code> object as a direct replacement for the native <code class=\"code_code__3jDWG\">Request<\/code> interface, giving you more control over how you manipulate the request.<\/p>\n<p class=\"geist-text p\"><code class=\"code_code__3jDWG\">NextRequest<\/code> is fully typed and can be imported from <code class=\"code_code__3jDWG\">next\/server<\/code>.<\/p>\n<pre class=\"lang:javascript\">import type { NextRequest } from 'next\/server';<\/pre>\n<p class=\"geist-text p\">Example using the <code class=\"code_code__3jDWG\">geo<\/code> object to check a requests location and blocking if it does not match an allowlist:<\/p>\n<pre class=\"lang:javascript\">import type { NextRequest } from 'next\/server';\r\n\r\n\/\/ Block GB, prefer US\r\nconst BLOCKED_COUNTRY = 'GB';\r\n\r\nexport function middleware(req: NextRequest) {\r\n  const country = req.geo.country || 'US';\r\n\r\n  \/\/ If the request is from the blocked country,\r\n  \/\/ send back a response with a status code\r\n  if (country === BLOCKED_COUNTRY) {\r\n    return new Response('Blocked for legal reasons', { status: 451 });\r\n  }\r\n\r\n  \/\/ Otherwise, send a response with the country\r\n  return new Response(`Greetings from ${country}, where you are not blocked.`);\r\n}<\/pre>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"nextresponse\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#nextresponse\">NextResponse<\/a><\/h4>\n<p class=\"geist-text p\">The <code class=\"code_code__3jDWG\">NextResponse<\/code> object is an extension of the native <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Response\"><code class=\"code_code__3jDWG\">Response<\/code><\/a> interface, with the following added methods and properties:<\/p>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">cookies<\/code> &#8211; An object with the cookies in the <code class=\"code_code__3jDWG\">Response<\/code><\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">redirect()<\/code> &#8211; Returns a <code class=\"code_code__3jDWG\">NextResponse<\/code> with a redirect set<\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">rewrite()<\/code> &#8211; Returns a <code class=\"code_code__3jDWG\">NextResponse<\/code> with a rewrite set<\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">next()<\/code> &#8211; Returns a <code class=\"code_code__3jDWG\">NextResponse<\/code> that will continue the middleware chain<\/li>\n<\/ul>\n<p class=\"geist-text p\">All methods above return a <code class=\"code_code__3jDWG\">NextResponse<\/code> object that only takes effect if it&#8217;s returned in the middleware function.<\/p>\n<p class=\"geist-text p\"><code class=\"code_code__3jDWG\">NextResponse<\/code> is fully typed and can be imported from <code class=\"code_code__3jDWG\">next\/server<\/code>.<\/p>\n<pre class=\"lang:javascript\">import { NextResponse } from 'next\/server';<\/pre>\n<p class=\"geist-text p\">Example using <code class=\"code_code__3jDWG\">rewrite()<\/code> to rewrite the response to a different URL based on the request (browser) location:<\/p>\n<pre class=\"lang:javascript\">import { NextResponse } from 'next\/server';\r\nimport type { NextRequest } from 'next\/server';\r\n\r\nexport function middleware(req: NextRequest) {\r\n  const country = req.geo.country?.toLowerCase() || 'us';\r\n\r\n  req.nextUrl.pathname = `\/${country}`;\r\n  return NextResponse.rewrite(req.nextUrl);\r\n}<\/pre>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"why-does-redirect()-use-307-and-308\" class=\"jsx-4241549934 target\"><\/span>Why does redirect() use 307 and 308?<\/h4>\n<blockquote>\n<p class=\"geist-text p\">When using <code class=\"code_code__3jDWG\">redirect()<\/code> you may notice that the status codes used are <code class=\"code_code__3jDWG\">307<\/code> for a temporary redirect, and <code class=\"code_code__3jDWG\">308<\/code> for a permanent redirect. While traditionally a <code class=\"code_code__3jDWG\">302<\/code> was used for a temporary redirect, and a <code class=\"code_code__3jDWG\">301<\/code> for a permanent redirect, many browsers changed the request method of the redirect, from a <code class=\"code_code__3jDWG\">POST<\/code> to <code class=\"code_code__3jDWG\">GET<\/code> request when using a <code class=\"code_code__3jDWG\">302<\/code>, regardless of the origins request method.<\/p>\n<\/blockquote>\n<p class=\"geist-text p\">Taking the following example of a redirect from <code class=\"code_code__3jDWG\">\/users<\/code> to <code class=\"code_code__3jDWG\">\/people<\/code>, if you make a <code class=\"code_code__3jDWG\">POST<\/code> request to <code class=\"code_code__3jDWG\">\/users<\/code> to create a new user, and are conforming to a <code class=\"code_code__3jDWG\">302<\/code> temporary redirect, the request method will be changed from a <code class=\"code_code__3jDWG\">POST<\/code> to a <code class=\"code_code__3jDWG\">GET<\/code> request. This doesn&#8217;t make sense, as to create a new user, you should be making a <code class=\"code_code__3jDWG\">POST<\/code> request to <code class=\"code_code__3jDWG\">\/people<\/code>, and not a <code class=\"code_code__3jDWG\">GET<\/code> request.<\/p>\n<p class=\"geist-text p\">The introduction of the <code class=\"code_code__3jDWG\">307<\/code> status code means that the request method is preserved as <code class=\"code_code__3jDWG\">POST<\/code>.<\/p>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">302<\/code> &#8211; Temporary redirect, will change the request method from <code class=\"code_code__3jDWG\">POST<\/code> to <code class=\"code_code__3jDWG\">GET<\/code><\/li>\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">307<\/code> &#8211; Temporary redirect, will preserve the request method as <code class=\"code_code__3jDWG\">POST<\/code><\/li>\n<\/ul>\n<p class=\"geist-text p\">The <code class=\"code_code__3jDWG\">redirect()<\/code> method uses a <code class=\"code_code__3jDWG\">307<\/code> by default, instead of a <code class=\"code_code__3jDWG\">302<\/code> temporary redirect, meaning your requests will <em>always<\/em> be preserved as <code class=\"code_code__3jDWG\">POST<\/code> requests.<\/p>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"middleware-running-order\" class=\"jsx-4241549934 target\"><\/span>Middleware running order<\/h3>\n<p class=\"geist-text p\">If you <span class=\"jsx-219205317\">do not<\/span> have any sub-directories, the Middleware will run on all routes within the <code class=\"code_code__3jDWG\">\/pages<\/code> directory and public files like <code class=\"code_code__3jDWG\">\/favicon.ico<\/code>. The below example assumes you have <code class=\"code_code__3jDWG\">about.ts<\/code> and <code class=\"code_code__3jDWG\">teams.ts<\/code> routes.<\/p>\n<pre class=\"lang:bash\">- \/pages\r\n  _middleware.ts # Will run on all routes under \/pages\r\n  index.ts\r\n  about.ts\r\n  teams.ts\r\n- package.json<\/pre>\n<p class=\"geist-text p\">If you <em>do<\/em> have sub-directories with nested routes, the Middleware will run in a top-down fashion. For example, if you have created <code class=\"code_code__3jDWG\">\/pages\/about\/_middleware.ts<\/code> and <code class=\"code_code__3jDWG\">\/pages\/about\/team\/_middleware.ts<\/code>, the Middleware will run <em>first<\/em> on <code class=\"code_code__3jDWG\">\/pages\/about<\/code>, and then <code class=\"code_code__3jDWG\">\/pages\/about\/team<\/code>. The below example shows how this works with a nested routing structure.<\/p>\n<pre class=\"lang:bash\">- \/pages\r\n  index.ts\r\n  - \/about\r\n    _middleware.ts # Will run first\r\n    about.ts\r\n    - \/teams\r\n      _middleware.ts # Will run second\r\n      teams.ts\r\n- package.json<\/pre>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"runtime\" class=\"jsx-4241549934 target\"><\/span>Runtime<\/h3>\n<p class=\"geist-text p\">Once the Middleware is deployed, it will run within a <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/v8.dev\/\">V8 Runtime<\/a> with a limited set of APIs. In development, the code will run in a sandbox environment that emulates the production runtime.<\/p>\n<p class=\"geist-text p\">Because of this, there are some restrictions to writing Middleware. These include:<\/p>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\">Native Node.js APIs <span class=\"jsx-219205317\">are not supported<\/span>. For example, you can&#8217;t read or write to the filesystem<\/li>\n<li class=\"jsx-3358961161\">Node Modules <em>can<\/em> be used, as long as they implement ES Modules and <span class=\"jsx-219205317\">do not<\/span> use any native Node.js APIs. For example, you could use the <code class=\"code_code__3jDWG\">path-to-regexp<\/code> package to do path matches<\/li>\n<li class=\"jsx-3358961161\">You can use ES Modules and split your code into reusable files that will then be bundled together when the application is built<\/li>\n<li class=\"jsx-3358961161\">Calling <code class=\"code_code__3jDWG\">require<\/code> directly is <span class=\"jsx-219205317\">not allowed<\/span>. If you do use it, it might work when the import path can be statically resolved, but it is not recommended. Use ES Modules instead<\/li>\n<\/ul>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"runtime-apis\" class=\"jsx-4241549934 target\"><\/span>Runtime APIs<\/h3>\n<p class=\"geist-text p\">The following objects and APIs are available in the runtime:<\/p>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"globals\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#globals\">Globals<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Request\"><code class=\"code_code__3jDWG\">Request<\/code><\/a><\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Response\"><code class=\"code_code__3jDWG\">Response<\/code><\/a><\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Blob\"><code class=\"code_code__3jDWG\">Blob<\/code><\/a><\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"base64\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#base64\">Base64<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/atob\"><code class=\"code_code__3jDWG\">atob<\/code><\/a>: Decodes a string of data which has been encoded using base-64 encoding<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/btoa\"><code class=\"code_code__3jDWG\">btoa<\/code><\/a>: Creates a base-64 encoded ASCII string from a string of binary data<\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"encoding\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#encoding\">Encoding<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/TextEncoder\"><code class=\"code_code__3jDWG\">TextEncoder<\/code><\/a>: Takes a stream of code points as input and emits a stream of bytes (UTF8)<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/TextDecoder\"><code class=\"code_code__3jDWG\">TextDecoder<\/code><\/a>: Takes a stream of bytes as input and emit a stream of code points<\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"environment\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#environment\">Environment<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><code class=\"code_code__3jDWG\">process.env<\/code>: Holds an object with all environment variables for both production and development in the exact same way as any other page or API in Next.js<\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"fetch\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#fetch\">Fetch<\/a><\/h4>\n<p class=\"geist-text p\">The <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Fetch_API\">Web Fetch API<\/a> can be used from the runtime, enabling you to use Middleware as a proxy, or connect to external storage APIs<\/p>\n<blockquote>\n<p class=\"geist-text p\">A potential caveat to using the Fetch API in a Middleware function is latency. For example, if you have a Middleware function running a fetch request to New York, and a user accesses your site from London, the request will be resolved from the nearest Edge to the user (in this case, London), to the origin of the request, New York. There is a risk this could happen on every request, making your site slow to respond. When using the Fetch API, you <em>must<\/em> make sure it does not run on every single request made.<\/p>\n<\/blockquote>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"streams\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#streams\">Streams<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/TransformStream\"><code class=\"code_code__3jDWG\">TransformStream<\/code><\/a>: Consists of a pair of streams: a writable stream known as its writable side, and a readable stream, known as its readable side. Writes to the writable side, result in new data being made available for reading from the readable side. Support for web streams is quite limited at the moment, although it is more extended in the development environment<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/ReadableStream\"><code class=\"code_code__3jDWG\">ReadableStream<\/code><\/a>: A readable stream of byte data<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/WritableStream\"><code class=\"code_code__3jDWG\">WritableStream<\/code><\/a>: A standard abstraction for writing streaming data to a destination, known as a sink<\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"timers\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#timers\">Timers<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/setInterval\"><code class=\"code_code__3jDWG\">setInterval<\/code><\/a>: Schedules a function to execute every time a given number of milliseconds elapses<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/clearInterval\"><code class=\"code_code__3jDWG\">clearInterval<\/code><\/a>: Cancels the repeated execution set using <code class=\"code_code__3jDWG\">setInterval()<\/code><\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/setTimeout\"><code class=\"code_code__3jDWG\">setTimeout<\/code><\/a>: Schedules a function to execute in a given amount of time<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/clearTimeout\"><code class=\"code_code__3jDWG\">clearTimeout<\/code><\/a>: Cancels the delayed execution set using <code class=\"code_code__3jDWG\">setTimeout()<\/code><\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"web\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#web\">Web<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Headers\"><code class=\"code_code__3jDWG\">Headers<\/code><\/a>: A <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/whatwg.org\/\">WHATWG<\/a> implementation of the headers API<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/URL\"><code class=\"code_code__3jDWG\">URL<\/code><\/a>: A WHATWG implementation of the URL API.<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/URLSearchParams\"><code class=\"code_code__3jDWG\">URLSearchParams<\/code><\/a>: A WHATWG implementation of <code class=\"code_code__3jDWG\">URLSearchParams<\/code><\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"crypto\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#crypto\">Crypto<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Crypto\"><code class=\"code_code__3jDWG\">Crypto<\/code><\/a>: The <code class=\"code_code__3jDWG\">Crypto<\/code> interface represents basic cryptography features available in the current context<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Crypto\/randomUUID\"><code class=\"code_code__3jDWG\">crypto.randomUUID<\/code><\/a>: Lets you generate a v4 UUID using a cryptographically secure random number generator<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Crypto\/getRandomValues\"><code class=\"code_code__3jDWG\">crypto.getRandomValues<\/code><\/a>: Lets you get cryptographically strong random values<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/Crypto\/subtle\"><code class=\"code_code__3jDWG\">crypto.subtle<\/code><\/a>: A read-only property that returns a <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/SubtleCrypto\">SubtleCrypto<\/a> which can then be used to perform low-level cryptographic operations<\/li>\n<\/ul>\n<h4 class=\"lean geist-text h4\" data-components-heading=\"true\"><span id=\"logging\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#logging\">Logging<\/a><\/h4>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/console\/debug\"><code class=\"code_code__3jDWG\">console.debug<\/code><\/a>: Outputs a message to the console with the log level debug<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/console\/info\"><code class=\"code_code__3jDWG\">console.info<\/code><\/a>: Informative logging of information. You may use string substitution and additional arguments with this method<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/console\/clear\"><code class=\"code_code__3jDWG\">console.clear<\/code><\/a>: Clears the console<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/console\/dir\"><code class=\"code_code__3jDWG\">console.dir<\/code><\/a>: Displays an interactive listing of the properties of a specified JavaScript object<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/console\/count\"><code class=\"code_code__3jDWG\">console.count<\/code><\/a>: Log the number of times this line has been called with the given label<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/console\/time\"><code class=\"code_code__3jDWG\">console.time<\/code><\/a>: Starts a timer with a name specified as an input parameter<\/li>\n<\/ul>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"unsupported-apis\" class=\"jsx-4241549934 target\"><\/span><a class=\"jsx-4241549934\" href=\"https:\/\/vercel.com\/docs\/concepts\/functions\/edge-functions#unsupported-apis\">Unsupported APIs<\/a><\/h3>\n<p class=\"geist-text p\">The Edge Runtime has some restrictions including:<\/p>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\">Native Node.js APIs <span class=\"jsx-219205317\">are not supported<\/span>. For example, you can&#8217;t read or write to the filesystem<\/li>\n<li class=\"jsx-3358961161\">Node Modules <em>can<\/em> be used, as long as they implement ES Modules and do not use any native Node.js APIs<\/li>\n<li class=\"jsx-3358961161\">Calling <code class=\"code_code__3jDWG\">require<\/code> directly is <span class=\"jsx-219205317\">not allowed<\/span>. Use ES Modules instead<\/li>\n<\/ul>\n<p class=\"geist-text p\">The following JavaScript language features are disabled, and <span class=\"jsx-219205317\">will not work:<\/span><\/p>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/eval\"><code class=\"code_code__3jDWG\">eval<\/code><\/a>: Evaluates JavaScript code represented as a string<\/li>\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/JavaScript\/Reference\/Global_Objects\/Function\"><code class=\"code_code__3jDWG\">new Function(evalString)<\/code><\/a>: Creates a new function with the code provided as an argument<\/li>\n<\/ul>\n<p class=\"geist-text p\">The following Web APIs are currently not supported, but will be in the future:<\/p>\n<ul class=\"jsx-377721955\">\n<li class=\"jsx-3358961161\"><a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/developer.mozilla.org\/en-US\/docs\/Web\/API\/AbortController\"><code class=\"code_code__3jDWG\">AbortController<\/code><\/a>: Abort one or more Web requests when desired<\/li>\n<\/ul>\n<h2 class=\"lean geist-text h2\" data-components-heading=\"true\"><span id=\"technical-details\" class=\"jsx-4241549934 target\"><\/span>Technical Details<\/h2>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"maximum-execution-duration\" class=\"jsx-4241549934 target\"><\/span>Maximum Execution Duration<\/h3>\n<p class=\"geist-text p\">The maximum duration for an Edge Function execution is <span class=\"jsx-219205317\">30 seconds<\/span>, but the function needs to return a response in less than <span class=\"jsx-219205317\">1.5 seconds<\/span>, otherwise, the request will time out.<\/p>\n<p class=\"geist-text p\">This means that you should return a response as soon as possible, and continue with any asynchronous workloads in the background, after returning the response.<\/p>\n<h3 class=\"lean geist-text h3\" data-components-heading=\"true\"><span id=\"code-size-limit\" class=\"jsx-4241549934 target\"><\/span>Code size limit<\/h3>\n<p class=\"geist-text p\">The maximum size for an Edge Function is <span class=\"jsx-219205317\">1 MB<\/span>, including all the code that is bundled in the function.<\/p>\n<p class=\"geist-text p\">If you reach the limit, make sure the code you are importing in your function is used and is not too heavy. You can use a package size checker tool like a <a class=\"link_old_link__1gRam link_old_color__3TJR0\" href=\"https:\/\/bundle.js.org\/\">bundle<\/a> to check the size of a package and search for a smaller alternative.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Vercel&#8217;s Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on Next.js using Vercel will have access to a super useful middleware. I&#8217;ll be deleting a bunch of infrastructure code and probably thousands of lines of code that I have now for things like basic auth and purchasing power parity. This is pretty amazing. Edge Functions# Traditionally there are two ways to serve content, statically from a Content Delivery Network (CDN) close to the user for fast response times, or dynamically, with personalization configured at the server level [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"webmentions_disabled_pings":false,"webmentions_disabled":false,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[181],"tags":[],"class_list":["post-7708","post","type-post","status-publish","format-standard","hentry","category-javascript"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v27.4 - https:\/\/yoast.com\/product\/yoast-seo-wordpress\/ -->\n<title>Vercel Edge Functions with Next.js<\/title>\n<meta name=\"description\" content=\"Vercel&#039;s Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on\" \/>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Vercel Edge Functions with Next.js\" \/>\n<meta property=\"og:description\" content=\"Vercel&#039;s Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on\" \/>\n<meta property=\"og:url\" content=\"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/\" \/>\n<meta property=\"og:site_name\" content=\"Ahmad Awais\" \/>\n<meta property=\"article:publisher\" content=\"https:\/\/facebook.com\/AhmadAwais\" \/>\n<meta property=\"article:author\" content=\"https:\/\/facebook.com\/AhmadAwais\" \/>\n<meta property=\"article:published_time\" content=\"2021-10-26T18:53:06+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2021-10-26T19:00:36+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/ahmadawais.com\/wp-content\/uploads\/2024\/08\/ahmad-awais.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"2560\" \/>\n\t<meta property=\"og:image:height\" content=\"1440\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Ahmad Awais\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:creator\" content=\"@MrAhmadAwais\" \/>\n<meta name=\"twitter:site\" content=\"@MrAhmadAwais\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Ahmad Awais\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"11 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\\\/\\\/schema.org\",\"@graph\":[{\"@type\":\"Article\",\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/#article\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/\"},\"author\":{\"name\":\"Ahmad Awais\",\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/#\\\/schema\\\/person\\\/1d1b9504182dca2315cf039fb4ebb85b\"},\"headline\":\"Vercel Edge Functions with Next.js\",\"datePublished\":\"2021-10-26T18:53:06+00:00\",\"dateModified\":\"2021-10-26T19:00:36+00:00\",\"mainEntityOfPage\":{\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/\"},\"wordCount\":2112,\"commentCount\":0,\"publisher\":{\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/#\\\/schema\\\/person\\\/1d1b9504182dca2315cf039fb4ebb85b\"},\"articleSection\":[\"JavaScript\"],\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"CommentAction\",\"name\":\"Comment\",\"target\":[\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/#respond\"]}]},{\"@type\":\"WebPage\",\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/\",\"url\":\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/\",\"name\":\"Vercel Edge Functions with Next.js\",\"isPartOf\":{\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/#website\"},\"datePublished\":\"2021-10-26T18:53:06+00:00\",\"dateModified\":\"2021-10-26T19:00:36+00:00\",\"description\":\"Vercel's Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on\",\"breadcrumb\":{\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/\"]}]},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/vercel-edge-functions-next-js\\\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\\\/\\\/ahmadawais.com\\\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Vercel Edge Functions with Next.js\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/#website\",\"url\":\"https:\\\/\\\/ahmadawais.com\\\/\",\"name\":\"Ahmad Awais\",\"description\":\"Founder &amp; CEO of CommandCode.ai f\\\/k\\\/a Langbase | Google Developers Advisory Board (gDAB) founding member\",\"publisher\":{\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/#\\\/schema\\\/person\\\/1d1b9504182dca2315cf039fb4ebb85b\"},\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\\\/\\\/ahmadawais.com\\\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":[\"Person\",\"Organization\"],\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/#\\\/schema\\\/person\\\/1d1b9504182dca2315cf039fb4ebb85b\",\"name\":\"Ahmad Awais\",\"image\":{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/wp-content\\\/uploads\\\/2020\\\/06\\\/Ahmad-Awais-face.jpg\",\"url\":\"https:\\\/\\\/ahmadawais.com\\\/wp-content\\\/uploads\\\/2020\\\/06\\\/Ahmad-Awais-face.jpg\",\"contentUrl\":\"https:\\\/\\\/ahmadawais.com\\\/wp-content\\\/uploads\\\/2020\\\/06\\\/Ahmad-Awais-face.jpg\",\"width\":2299,\"height\":1705,\"caption\":\"Ahmad Awais\"},\"logo\":{\"@id\":\"https:\\\/\\\/ahmadawais.com\\\/wp-content\\\/uploads\\\/2020\\\/06\\\/Ahmad-Awais-face.jpg\"},\"description\":\"Founder & CEO of \u2318 Command Code coding agent with taste. Founded Langbase.com, AI cloud to build, deploy, and scale AI agents with tools & memory \u00b7 Creator of Command.new. \\\"Awais is an awesome example for developers\\\" \u2014 Satya Nadella, CEO of Microsoft. NASA Mars Ingenuity Helicopter mission code contributor 8th GitHub Stars Award recipient with 5x GitHub Stars Award (Listed as GitHub's #1 JavaScript trending developer). Google Developers Expert Web DevRel. Ex VP Eng (DevTools & DevRel) Rapid \u00b7 Google Developers Advisory Board (gDAB) founding member \u00b7 AI\\\/ML\\\/DevTools Angel Investor (Replit, Resend, Daytona, Gumroad and you?) \u276f AI\\\/ML Advisory Board San Francisco, DevNetwork. Award-winning Open Source Engineering leader authored hundreds of open-source dev-tools and software libraries used by millions of developers, including Shades of Purple code theme and corona-cli. Linux Foundation (Node.js Committee Lead), OpenAPI Business Governing Board. Taught 108K+ developers via NodeCLI.com and VSCode.pro course. 274 million views, blogging for 24 yrs. \u276f Read more about Ahmad Awais or come say hi on \ud835\udd4f @MrAhmadAwais.\",\"sameAs\":[\"https:\\\/\\\/AhmadAwais.com\\\/\",\"https:\\\/\\\/facebook.com\\\/AhmadAwais\",\"https:\\\/\\\/instagram.com\\\/MrAhmadAwais\\\/\",\"https:\\\/\\\/www.linkedin.com\\\/in\\\/MrAhmadAwais\\\/\",\"https:\\\/\\\/x.com\\\/MrAhmadAwais\",\"https:\\\/\\\/youtube.com\\\/AhmadAwais\"]}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Vercel Edge Functions with Next.js","description":"Vercel's Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/","og_locale":"en_US","og_type":"article","og_title":"Vercel Edge Functions with Next.js","og_description":"Vercel's Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on","og_url":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/","og_site_name":"Ahmad Awais","article_publisher":"https:\/\/facebook.com\/AhmadAwais","article_author":"https:\/\/facebook.com\/AhmadAwais","article_published_time":"2021-10-26T18:53:06+00:00","article_modified_time":"2021-10-26T19:00:36+00:00","og_image":[{"width":2560,"height":1440,"url":"https:\/\/ahmadawais.com\/wp-content\/uploads\/2024\/08\/ahmad-awais.jpg","type":"image\/jpeg"}],"author":"Ahmad Awais","twitter_card":"summary_large_image","twitter_creator":"@MrAhmadAwais","twitter_site":"@MrAhmadAwais","twitter_misc":{"Written by":"Ahmad Awais","Est. reading time":"11 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"Article","@id":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/#article","isPartOf":{"@id":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/"},"author":{"name":"Ahmad Awais","@id":"https:\/\/ahmadawais.com\/#\/schema\/person\/1d1b9504182dca2315cf039fb4ebb85b"},"headline":"Vercel Edge Functions with Next.js","datePublished":"2021-10-26T18:53:06+00:00","dateModified":"2021-10-26T19:00:36+00:00","mainEntityOfPage":{"@id":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/"},"wordCount":2112,"commentCount":0,"publisher":{"@id":"https:\/\/ahmadawais.com\/#\/schema\/person\/1d1b9504182dca2315cf039fb4ebb85b"},"articleSection":["JavaScript"],"inLanguage":"en-US","potentialAction":[{"@type":"CommentAction","name":"Comment","target":["https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/#respond"]}]},{"@type":"WebPage","@id":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/","url":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/","name":"Vercel Edge Functions with Next.js","isPartOf":{"@id":"https:\/\/ahmadawais.com\/#website"},"datePublished":"2021-10-26T18:53:06+00:00","dateModified":"2021-10-26T19:00:36+00:00","description":"Vercel's Edge Functions to be used with Next.js (v12) announced today at the second Next.js Conference look pretty amazing. Now everyone building on","breadcrumb":{"@id":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/"]}]},{"@type":"BreadcrumbList","@id":"https:\/\/ahmadawais.com\/vercel-edge-functions-next-js\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/ahmadawais.com\/"},{"@type":"ListItem","position":2,"name":"Vercel Edge Functions with Next.js"}]},{"@type":"WebSite","@id":"https:\/\/ahmadawais.com\/#website","url":"https:\/\/ahmadawais.com\/","name":"Ahmad Awais","description":"Founder &amp; CEO of CommandCode.ai f\/k\/a Langbase | Google Developers Advisory Board (gDAB) founding member","publisher":{"@id":"https:\/\/ahmadawais.com\/#\/schema\/person\/1d1b9504182dca2315cf039fb4ebb85b"},"potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/ahmadawais.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":["Person","Organization"],"@id":"https:\/\/ahmadawais.com\/#\/schema\/person\/1d1b9504182dca2315cf039fb4ebb85b","name":"Ahmad Awais","image":{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/ahmadawais.com\/wp-content\/uploads\/2020\/06\/Ahmad-Awais-face.jpg","url":"https:\/\/ahmadawais.com\/wp-content\/uploads\/2020\/06\/Ahmad-Awais-face.jpg","contentUrl":"https:\/\/ahmadawais.com\/wp-content\/uploads\/2020\/06\/Ahmad-Awais-face.jpg","width":2299,"height":1705,"caption":"Ahmad Awais"},"logo":{"@id":"https:\/\/ahmadawais.com\/wp-content\/uploads\/2020\/06\/Ahmad-Awais-face.jpg"},"description":"Founder & CEO of \u2318 Command Code coding agent with taste. Founded Langbase.com, AI cloud to build, deploy, and scale AI agents with tools & memory \u00b7 Creator of Command.new. \"Awais is an awesome example for developers\" \u2014 Satya Nadella, CEO of Microsoft. NASA Mars Ingenuity Helicopter mission code contributor 8th GitHub Stars Award recipient with 5x GitHub Stars Award (Listed as GitHub's #1 JavaScript trending developer). Google Developers Expert Web DevRel. Ex VP Eng (DevTools & DevRel) Rapid \u00b7 Google Developers Advisory Board (gDAB) founding member \u00b7 AI\/ML\/DevTools Angel Investor (Replit, Resend, Daytona, Gumroad and you?) \u276f AI\/ML Advisory Board San Francisco, DevNetwork. Award-winning Open Source Engineering leader authored hundreds of open-source dev-tools and software libraries used by millions of developers, including Shades of Purple code theme and corona-cli. Linux Foundation (Node.js Committee Lead), OpenAPI Business Governing Board. Taught 108K+ developers via NodeCLI.com and VSCode.pro course. 274 million views, blogging for 24 yrs. \u276f Read more about Ahmad Awais or come say hi on \ud835\udd4f @MrAhmadAwais.","sameAs":["https:\/\/AhmadAwais.com\/","https:\/\/facebook.com\/AhmadAwais","https:\/\/instagram.com\/MrAhmadAwais\/","https:\/\/www.linkedin.com\/in\/MrAhmadAwais\/","https:\/\/x.com\/MrAhmadAwais","https:\/\/youtube.com\/AhmadAwais"]}]}},"jetpack_featured_media_url":"","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/posts\/7708","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/comments?post=7708"}],"version-history":[{"count":5,"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/posts\/7708\/revisions"}],"predecessor-version":[{"id":7713,"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/posts\/7708\/revisions\/7713"}],"wp:attachment":[{"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/media?parent=7708"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/categories?post=7708"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/ahmadawais.com\/api\/wp\/v2\/tags?post=7708"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}