มีงานที่ต้องทำหน้า Intro Page แบบว่าตอนผู้ใช้เข้ามาเว็บครั้งแรกต้องเด้งไปที่หน้าแนะนำก่อนจะไปหน้าอื่น ๆ ซึ่ง Next.js มีหลายวิธีให้ทำเรื่องพวกนี้ เช่น ใช้ redirect ใน next.config.js หรือทำ redirect ในตัว page เลย
แน่นอนว่า ผมเลือกใช้ Middleware เพราะมันช่วยจัดการ Request ได้ตั้งแต่ตอน Request ก่อนถึง Render Page และยังยืดหยุ่นกว่ามาก
Middleware File
เรามาดู logic ใน middleware.ts
กันหน่อย
import { NextResponse } from "next/server";
import type { NextRequest } from "next/server";
export function middleware(request: NextRequest) {
const introPageCookie = request.cookies.get("visit_intro_page");
// check if not have cookies and not visit intro page, check page because handle for redirected you too many times
if (!introPageCookie && request.nextUrl.pathname !== "/intro") {
return NextResponse.redirect(new URL("/intro", request.url));
}
// when visit intro page, set cookies
if (request.nextUrl.pathname === "/intro") {
const response = NextResponse.next();
response.cookies.set("visit_intro_page", "true", {
maxAge: 60 * 60 * 24 * 1,
});
return response;
}
// when visit root page, redirect to home
if (request.nextUrl.pathname === "/") {
return NextResponse.redirect(new URL("/home", request.url));
}
}
export const config = {
matcher: [
/*
* Match all request paths except for the ones starting with:
* - api (API routes)
* - _next/static (static files)
* - _next/image (image optimization files)
* - favicon.ico, sitemap.xml, robots.txt (metadata files)
*/
"/((?!api|_next/static|_next/image|favicon.ico|sitemap.xml|robots.txt).*)",
],
};
อธิบาย Logic ใน Middleware กันหน่อย
ซึ่งสิ่งที่ทำ ก็ไม่ได้มีอะไรมาก
-
โดยเราจะมีตัวแปรนึงไว้เก็บ cookies โดยให้ชื่อว่า
visit_intro_page
เพื่อไวเก็บว่า user ได้เข้ามาที่หน้า /intro แล้วหรือยัง -
จากนั้นก็ทำการเช็คว่า cookies ที่ประกาศไว้เป็นจริง และ user ยังไม่ได้เข้ามาหน้า /intro ใช่ไหม ซึ่งถ้าไม่ใช่ ก็จะ redirect ไปที่ /intro
-
จากนั้นเมื่อ user ได้เข้ามาที่หน้า /intro ก็จะ set cookies
visit_intro_page
=true
และมีอายุ 1 วัน จากนั้นก็สั่งให้ redirect ไปที่ /home -
สุดท้ายถ้า user ได้เข้ามาที่หน้า / ก็จะสั่งให้ redirect ไปที่ /home
-
สำหรับในส่วน matcher เราจะยกเว้น path ดังต่อไปนี้
/api
/_next/static
/_next/image
/favicon.ico
/sitemap.xml
/robots.txt
ก็คือ path ที่ว่ามาจะไม่เข้าเงื่อนไขของ middleware
Tree
สำหรับโครงสร้างของโปรเจกต์ ก็จะเป็นแบบนี้
.
├── README.md
├── bun.lockb
├── next-env.d.ts
├── next.config.mjs
├── package.json
├── public
│ ├── next.svg
│ └── vercel.svg
├── src
│ ├── app
│ │ ├── favicon.ico
│ │ ├── home
│ │ │ └── page.tsx
│ │ ├── intro
│ │ │ └── page.tsx
│ │ └── layout.tsx
│ └── middleware.ts
Result
มาลองทดสอบกันหน่อย
จะเห็นว่า ครั้งแรกที่ผู้ใช้เข้ามาเว็บไซต์ จะถูกพาไปที่หน้า Intro Page /intro
พร้อมตั้งค่า Cookies visit_intro_page = true
เมื่อกลับเข้ามาอีก จะข้ามหน้า Intro ไปหน้า Home /home
เลย เพียงเท่านี้ก็จะได้หน้า intro page ง่ายๆ แล้ว ลองไปประยุกต์ใช้กันดูนะครับ