0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Middleware trong Next.js - Cách Tiếp Cận Đúng Đắn

Đăng vào 7 tháng trước

• 4 phút đọc

Middleware trong Next.js - Cách Tiếp Cận Đúng Đắn

Khi bạn bắt đầu làm việc với middleware trong Next.js, có vẻ như thật đơn giản:
chỉ cần thêm một vài chuyển hướng, bảo vệ một số tuyến đường, xong.

Nhưng vấn đề ở đây là: hầu hết các lập trình viên (bao gồm cả tôi trong quá khứ) cuối cùng lại viết middleware như thế này:

typescript Copy
export async function middleware(request: NextRequest, user: User | null) {
  const { pathname } = request.nextUrl;

  if (pathname.startsWith("/dashboard")) {
    if (!user) {
      return NextResponse.redirect(new URL("/login", request.url));
    }
  } else if (pathname.startsWith("/onboarding")) {
    if (!user) {
      return NextResponse.redirect(new URL("/login", request.url));
    }
  }

  if (pathname.startsWith("/login")) {
    if (user) {
      return NextResponse.redirect(new URL("/dashboard", request.url));
    }
  } else if (pathname.startsWith("/signup")) {
    if (user) {
      return NextResponse.redirect(new URL("/dashboard", request.url));
    }
  }

  return NextResponse.next();
}

Mặc dù đoạn mã này hoạt động tốt ở cái nhìn đầu tiên, nhưng có một vấn đề lớn trong cách tiếp cận này.

Khi bạn thêm nhiều tuyến đường hơn (ví dụ: /profile, /settings, /forgot-password, v.v.)... tệp của bạn sẽ trở thành một mớ hỗn độn của các if/else.

Và điều này sẽ chỉ trở nên tồi tệ hơn khi dự án của bạn mở rộng.

Không thú vị, không mở rộng được, và chắc chắn - không sạch sẽ.


Suy Nghĩ Theo Quy Tắc, Không Phải Điều Kiện

Thay vì mã hóa cứng mọi chuyển hướng, chúng ta chỉ cần định nghĩa các điều kiện.

Hãy nghĩ về middleware như một cảnh sát giao thông.

Cảnh sát không quan tâm bạn là ai. Họ chỉ kiểm tra bạn đang đi đâu và liệu bạn có được phép ở đó hay không.

Vì vậy, hãy mô tả các quy tắc của chúng ta một cách có cấu trúc.


Bước 1: Định Nghĩa Nhóm Tuyến Đường

Chúng ta sẽ chia các tuyến đường thành hai nhóm đơn giản:

typescript Copy
const PROTECTED_ROUTES = ["/dashboard", "/onboarding"];
const AUTH_ROUTES = ["/login", "/signup"];
  • Nhóm tuyến đường bảo vệ: chỉ người dùng đã đăng nhập mới có thể truy cập.
  • Nhóm tuyến đường xác thực: chỉ người dùng chưa đăng nhập mới nên thấy chúng.

Đã sạch hơn rất nhiều so với việc viết 20 câu lệnh if kiểm tra.


Bước 2: Mô Tả Quy Tắc

Bây giờ hãy tạo một kiểu cho các quy tắc:

typescript Copy
interface RouteRule {
  routes: string[];
  condition: (user: User | null) => boolean;
  redirect: string;
}

Mỗi quy tắc nói:

  • Các tuyến đường mà nó áp dụng
  • Điều kiện kích hoạt một chuyển hướng
  • Địa điểm chuyển hướng đến

Bước 3: Viết Các Quy Tắc

Đây là hình dạng của hai quy tắc của chúng ta:

typescript Copy
const routeRules: RouteRule[] = [
  {
    routes: PROTECTED_ROUTES,
    condition: (user) => !user, // nếu không có người dùng, chuyển hướng
    redirect: "/login",
  },
  {
    routes: AUTH_ROUTES,
    condition: (user) => !!user, // nếu đã đăng nhập, chuyển hướng
    redirect: "/dashboard",
  },
];

Vậy là xong. Thêm nhiều nhóm? Chỉ cần thêm nhiều đối tượng.
Không cần phải chạm vào logic một lần nữa.


Bước 4: Áp Dụng Các Quy Tắc Trong Middleware

Bây giờ chúng ta lặp qua các quy tắc:

typescript Copy
export class Middleware {
  private routeRules = routeRules;

  async handle(request: NextRequest, user: User | null) {
    const { pathname } = request.nextUrl;

    for (const rule of this.routeRules) {
      const isMatch = rule.routes.some((r) =>
        pathname.startsWith(r)
      );

      if (isMatch && rule.condition(user)) {
        return NextResponse.redirect(
          new URL(rule.redirect, request.url)
        );
      }
    }

    return NextResponse.next();
  }
}

Không có sự lộn xộn. Không có hỗn loạn. Chỉ có logic rõ ràng.


Tại Sao Đây Là "Cách Đúng"

  1. Mở rộng – Thêm tuyến đường mới chỉ trong vài giây
  2. Dễ đọc – Không có rừng rậm các câu lệnh if/else
  3. Tái sử dụng – Một nơi trung tâm cho các quy tắc
  4. Mở rộng – Có thể được mở rộng cho vai trò, quyền hạn, v.v.
  5. Tuân thủ SOLID.

Middleware phải cảm thấy như một middleware, không phải một cơn ác mộng.


Những Suy Nghĩ Cuối Cùng

Mẹo rất đơn giản:
Ngừng mã hóa cứng các điều kiện. Bắt đầu suy nghĩ theo quy tắc.

Mô hình này sẽ giúp bạn tiết kiệm nhiều đau đầu, đặc biệt nếu ứng dụng của bạn có xác thực và một tập hợp các trang được bảo vệ ngày càng phát triển.

Nếu bạn thấy điều này thú vị, hãy bình luận và chúng ta hãy nói chuyện!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào