Next.js 中的边缘函数和中间件
Next.js 是由 Vercel 开发的基于 React 的全栈框架,支持网页预渲染等功能。与将整个应用程序加载到客户端的传统反应应用程序不同。 Next.js 允许在服务器上呈现网页,这对性能和 SEO 来说非常有用。您可以在此处了解有关 Next.js 的更多信息。
Vercel 在最近对 Next.js 版本 12 的更新中引入了许多新功能,包括 Edge 功能和中间件。
直到最近,主要有两种向用户浏览器提供内容的方法:
静态地从靠近用户位置的内容交付网络获得更快的响应时间,或者,
对来自单个服务器的每个请求动态地使用不同的内容和逻辑。
这两种方法都有局限性,例如 CDN 无法缓存动态内容,服务器无法匹配 CDN 的交付速度。
什么是边缘函数?
Vercel 引入了 Edge 功能,以实现 CDN 的速度和服务器端的灵活性。边缘功能使开发人员能够在全球分布的服务器上运行他们的代码。这意味着您的代码将在用户更方便的位置执行。这允许开发人员将服务器端逻辑移动到边缘,更靠近访问者的来源,以加快响应时间。
如果您曾经使用过无服务器函数,那么上面的定义可能听起来很熟悉。
Edge 功能与无服务器功能有何不同?
- 低延迟:我们部署在边缘的代码被复制到许多全球位置,因此它是从用户最近的地理位置执行的。来自世界各地的用户将体验到低延迟。
- 无冷启动:当调用无服务器函数时,在执行前需要大约 250 毫秒的冷启动,但边缘函数提供 100 倍的启动时间,并将启动时间减少到几乎 0 毫秒。
使用 Edge 函数:在我们开始之前,您应该熟悉术语中间件。这不是一个新概念,但它最近才在 Next.js 中引入。中间件是在对 Next.js 发出每个请求之前执行的函数。所以,如果用户请求一个页面,中间件函数的逻辑首先被执行,然后是请求。 Vercel 引入的中间件将在边缘函数上执行。
示例:为了演示边缘功能的实际应用,我们将使用 Next.js 创建一个小型应用程序。我们将首先创建一个新的 Next.js 项目,然后使用 Next.js 中间件来实现受保护的路由。访问受保护的路由需要密钥;否则,用户将被重定向到主页。
第 1 步:运行以下命令创建一个新的 Next.js 应用程序(确保已安装 NPM 和节点):
npx create-next-app@latest myproject
当我们在代码编辑器中打开我们的项目时,我们会看到一个简单的项目结构。对于本教程的范围,我们将只关注 /pages 目录。我们将首先清理/pages/index.js文件。然后我们将创建一个名为protected的新路由。现在,在 pages 文件夹中创建一个名为/pages/_middleware.js的新文件。从此文件导出的任何函数都将被视为中间件并在边缘运行。我们的中间件逻辑将写在 _middleware.js 中。
项目结构:它将如下所示。
例子:
/pages/index.js
import React from 'react'
const Home = () => {
return (
Home Page
)
}
export default Home
/pages/protected.js
import React from 'react'
const Protected = () => {
return (
Secret Data
)
}
export default Protected
/pages/_middleware.js
import { NextResponse } from "next/server";
// This function will act as middleware
const middlewareHandler = (req) => {
// We'll first check if route includes
// the protected path
if (req.url.includes("/protected")) {
// Get the secret from the url params
const urlParams = new URLSearchParams(req.nextUrl.search);
const secret = urlParams.get("secret");
// Check if secret exists, if it does
// then it must be correct.
if (secret && secret === "mysecret") {
// If secret matches we will continue
// to the protected route.
return NextResponse.next();
} else {
// If the secret doesn't exist or is incorrect
// we'll redirect to the index (Home) page.
return NextResponse.redirect("http://localhost:3000/");
}
}
// For all other routes, we won't change anything.
NextResponse.next();
};
export default middlewareHandler;
/pages/protected.js
import React from 'react'
const Protected = () => {
return (
Secret Data
)
}
export default Protected
/pages/_middleware.js
import { NextResponse } from "next/server";
// This function will act as middleware
const middlewareHandler = (req) => {
// We'll first check if route includes
// the protected path
if (req.url.includes("/protected")) {
// Get the secret from the url params
const urlParams = new URLSearchParams(req.nextUrl.search);
const secret = urlParams.get("secret");
// Check if secret exists, if it does
// then it must be correct.
if (secret && secret === "mysecret") {
// If secret matches we will continue
// to the protected route.
return NextResponse.next();
} else {
// If the secret doesn't exist or is incorrect
// we'll redirect to the index (Home) page.
return NextResponse.redirect("http://localhost:3000/");
}
}
// For all other routes, we won't change anything.
NextResponse.next();
};
export default middlewareHandler;
运行应用程序:打开终端并输入以下命令。
npm run dev
输出: