Next.js 实战 (十):中间件的魅力,打造更快更安全的应用

简介: 这篇文章介绍了什么是Next.js中的中间件以及其应用场景。中间件可以用于处理每个传入请求,比如实现日志记录、身份验证、重定向、CORS配置等功能。文章还提供了一个身份验证中间件的示例代码,以及如何使用限流中间件来限制同一IP地址的请求次数。中间件相当于一个构建模块,能够简化HTTP请求的预处理和后处理,提高代码的可维护性,有助于创建快速、安全和用户友好的Web体验。

什么是中间件?

Next.js 中,中间件(Middleware)是一种用于处理每个传入请求的功能。它允许你在请求到达页面之前对其进行修改或响应。

通过中间件,你可以实现诸如日志记录身份验证重定向CORS配置压缩等任务。中间件是构建高效和安全的 web 应用的重要组成部分。

应用场景

身份验证

你可以在中间件中检查用户的身份验证状态,比如从cookie或头部信息中读取JWT令牌,并根据验证结果决定是否允许访问特定页面或API端点。如果验证失败,可以返回401未授权状态码或者重定向到登录页面。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';

export function middleware(request) {
   
  const token = request.cookies.get('authToken')?.value;

  if (!token) {
   
    // 如果没有令牌,则重定向到登录页面
    return NextResponse.redirect(new URL('/login', request.url));
  }

  // 继续处理链
  return NextResponse.next();
}
AI 代码解读

日志记录

中间件非常适合用来记录所有进入应用程序的请求。这可以帮助监控流量模式、诊断问题以及了解用户行为。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';

export function middleware(request) {
   
  console.log(`Request to ${
     request.url} at ${
     new Date().toISOString()}`);

  // 继续处理链
  return NextResponse.next();
}
AI 代码解读

请求/响应转换

可以在请求到达最终目的地之前对请求数据进行预处理,也可以在发送给客户端之前修改响应内容。例如,格式化数据、添加额外的HTTP头、压缩响应体等。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';

export async function middleware(request) {
   
  // 修改请求体(假设是JSON格式)
  let modifiedBody = await request.json();
  modifiedBody.message = "Modified message";

  // 创建新的请求实例
  const newReq = new Request(request, {
   
    body: JSON.stringify(modifiedBody),
  });

  // 获取响应并修改它
  const response = await fetch(request.nextUrl.pathname, {
   
    method: request.method,
    headers: request.headers,
    body: newReq.body,
  });

  const resClone = await response.clone();
  const data = await resClone.json();
  data.newField = "This is a new field"; // 添加新字段

  // 返回修改后的响应
  return new Response(JSON.stringify(data), {
   
    status: response.status,
    headers: response.headers,
  });
}
AI 代码解读

重定向

基于某些条件(如URL路径、查询参数、用户代理等),你可以使用中间件来执行重定向操作,将用户引导至不同的页面。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';

export function middleware(request) {
   
  // 如果访问的是旧路径,则重定向到新路径
  if (request.nextUrl.pathname.startsWith('/login')) {
   
    return NextResponse.redirect(new URL('/dashboard', request.url));
  }

  // 继续处理链
  return NextResponse.next();
}
AI 代码解读

CORS(跨源资源共享)

设置适当的CORS头以允许或限制来自其他域的请求,这对于拥有多个子域名或需要与第三方服务交互的应用非常重要。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';

export function middleware(request) {
   
  const response = NextResponse.next();

  // 设置CORS头
  response.headers.set('Access-Control-Allow-Origin', '*');
  response.headers.set('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
  response.headers.set('Access-Control-Allow-Headers', 'Content-Type, Authorization');

  return response;
}
AI 代码解读

限流

防止滥用API接口,可以通过中间件实现速率限制,限制同一IP地址在一定时间内的请求次数。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';
import rateLimit from 'express-rate-limit'; // 需要安装依赖

const limiter = rateLimit({
   
  windowMs: 1 * 60 * 1000, // 1分钟
  max: 100, // 每分钟最多100次请求
});

export function middleware(request) {
   
  return new Promise((resolve, reject) => {
   
    limiter(request, {
   }, (err) => {
   
      if (err) {
   
        return reject(new NextResponse('Too many requests', {
    status: 429 }));
      }
      resolve(NextResponse.next());
    });
  });
}
AI 代码解读

国际化路由

根据用户的语言偏好或地理位置自动调整网站的语言版本。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';

export function middleware(request) {
   
  const locale = request.cookies.get('NEXT_LOCALE')?.value || 'en';

  // 如果不是根路径并且没有包含语言前缀,则添加语言前缀
  if (!request.nextUrl.pathname.startsWith(`/${
     locale}`)) {
   
    const url = new URL(request.url);
    url.pathname = `/${
     locale}${
     url.pathname}`;
    return NextResponse.redirect(url);
  }

  // 继续处理链
  return NextResponse.next();
}
AI 代码解读

静态文件服务

尽管Next.js已经提供了基本的静态文件服务功能,但你可以用中间件来增强这一功能,比如为特定类型的文件提供自定义处理逻辑。
示例代码:

// middleware.js
import {
    NextResponse } from 'next/server';
import fs from 'fs/promises';

export async function middleware(request) {
   
  const path = request.nextUrl.pathname;

  if (path.startsWith('/static-files/')) {
   
    try {
   
      const filePath = `./public${
     path}`;
      const file = await fs.readFile(filePath);
      return new Response(file, {
   
        headers: {
    'Content-Type': 'application/octet-stream' },
      });
    } catch (error) {
   
      return NextResponse.next();
    }
  }

  // 继续处理链
  return NextResponse.next();
}
AI 代码解读

config 配置对象

matcher

matcher 是一个非常强大的配置项,它允许你指定中间件应该应用于哪些路径。你可以通过正则表达式或通配符模式来匹配URL路径。

  • 通配符:可以使用 * 来表示任意字符序列。
  • 正则表达式:支持完整的正则表达式语法,但需要使用反斜杠进行转义。
    export const config = {
         
    matcher: ['/about', '/dashboard/:path*', '/users/:uid'],
    };
    
    AI 代码解读

unstable_ignorePaths

这个配置项可以让中间件忽略某些路径,即不对其应用中间件逻辑。这对于排除不需要处理的资源或者避免循环重定向等问题非常有用。

export const config = {
   
  unstable_ignorePaths: ['/api/*', '/static/*'],
};
AI 代码解读

这里,所有以 /api /开头和静态资源路径都将被忽略,不会受到中间件的影响。

maxDuration

maxDuration 定义了中间件函数的最大执行时间(以秒为单位)。如果中间件执行时间超过了这个值,Next.js将会抛出错误。这有助于防止长时间运行的任务阻塞请求处理。

export const config = {
   
  maxDuration: 5, // 中间件最大执行时间为5秒
};
AI 代码解读

regions

regions 配置项指定了中间件应该部署到的地理区域。这对于希望减少延迟、提高性能的应用来说非常重要,因为它可以让中间件尽可能靠近用户部署。

export const config = {
   
  regions: ['us-east-1', 'eu-west-1'], // 在美国东部和欧洲西部部署
};
AI 代码解读

下面是一个结合了多个config配置项的例子:

// middleware.js
import {
    NextResponse } from 'next/server';

export function middleware(request) {
   
  // 中间件逻辑...
  return NextResponse.next();
}

export const config = {
   
  matcher: ['/about', '/dashboard/:path*', '/users/:uid'],
  unstable_ignorePaths: ['/api/*', '/static/*'],
  maxDuration: 10,
  regions: ['us-east-1', 'eu-west-1'],
};
AI 代码解读

总结

总之,Next.js中间件不仅仅是一个简单的请求处理器,它更像是一个构建模块,允许开发者以一种非侵入式的方式对HTTP请求进行预处理和后处理。这不仅简化了代码逻辑,提高了代码的可维护性,而且还有助于创建更加快速、安全和用户友好的Web体验。无论你是刚开始接触Next.js的新手,还是已经熟悉框架的老手,掌握中间件的使用都将为你的项目带来显著的价值。

Githubnext-admin

线上预览地址Next Admin

相关文章
通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
通义灵码基于自然语言需求,快速生成完整Vue组件。例如,用Vue 2和JavaScript实现贪吃蛇游戏:包含键盘控制、得分系统、游戏结束判定与Canvas动态渲染。AI生成的代码符合规范,支持响应式数据与事件监听,还能进阶优化(如增加启停按钮、速度随分数提升)。传统需1小时的工作量,使用通义灵码仅10分钟完成,大幅提升开发效率。操作简单:安装插件、输入需求、运行项目即可实现功能。
200 4
 通义灵码2.5实战评测:Vue.js贪吃蛇游戏一键生成
如何减少Node.js应用中的全局变量?
如何减少Node.js应用中的全局变量?
146 43
有哪些有效的方法可以优化Node.js应用的性能?
有哪些有效的方法可以优化Node.js应用的性能?
222 69
流量分发代码实战|学会用JS控制用户访问路径
流量分发工具(Traffic Distributor),又称跳转器或负载均衡器,可通过JavaScript按预设规则将用户随机引导至不同网站,适用于SEO优化、广告投放、A/B测试等场景。本文分享一段不到百行的JS代码,实现智能、隐蔽的流量控制,并附完整示例与算法解析。
51 1
公司局域网管理视域下 Node.js 图算法的深度应用研究:拓扑结构建模与流量优化策略探析
本文探讨了图论算法在公司局域网管理中的应用,针对设备互联复杂、流量调度低效及安全监控困难等问题,提出基于图论的解决方案。通过节点与边建模局域网拓扑结构,利用DFS/BFS实现设备快速发现,Dijkstra算法优化流量路径,社区检测算法识别安全风险。结合WorkWin软件实例,展示了算法在设备管理、流量调度与安全监控中的价值,为智能化局域网管理提供了理论与实践指导。
101 3
如何通过DIY.JS快速构建出一个DIY手机壳、T恤的应用?
DIY.JS 是一款基于原生 Canvas 的业务级图形库,专注于商品定制的图形交互功能,帮助开发者轻松实现个性化设计。适用于 T 恤、手机壳等多种商品场景。它自带丰富功能,无需从零构建,快速集成到项目中。通过创建舞台、添加模型、定义 DIY 区域和添加素材四个步骤即可完成基础用法。支持在线演示体验,文档详细,易上手。
157 57
JavaScript中通过array.map()实现数据转换、创建派生数组、异步数据流处理、复杂API请求、DOM操作、搜索和过滤等,array.map()的使用详解(附实际应用代码)
array.map()可以用来数据转换、创建派生数组、应用函数、链式调用、异步数据流处理、复杂API请求梳理、提供DOM操作、用来搜索和过滤等,比for好用太多了,主要是写法简单,并且非常直观,并且能提升代码的可读性,也就提升了Long Term代码的可维护性。 只有锻炼思维才能可持续地解决问题,只有思维才是真正值得学习和分享的核心要素。如果这篇博客能给您带来一点帮助,麻烦您点个赞支持一下,还可以收藏起来以备不时之需,有疑问和错误欢迎在评论区指出~
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
【消息中间件】详解三大MQ:RabbitMQ、RocketMQ、Kafka
8735 0
Docker部署RabbitMQ消息中间件
【7月更文挑战第4天】Docker部署RabbitMQ消息中间件
379 3