Middleware в Next.js: самое простое объяснение
В Next.js мы можем использовать маршрутизацию на основе файлов для создания маршрутов. Любая папка в каталоге приложения с файлом страницы будет выступать в качестве маршрута, и когда пользователь запрашивает маршрут, его файл страницы отображается в качестве ответа.
Предположим, что в каталоге приложения есть папка «users» с файлом page.tsx (для TypeScript), содержащим список пользователей в качестве компонента для рендеринга. Если клиент открывает маршрут «/users», в качестве ответа отображается список пользователей. А что, если мы не хотим отображать список пользователей для всех? Здесь на помощь приходит промежуточное ПО, которое перехватывает запросы, применяет логику и решает, как действовать дальше.
Введение в Middleware
Middleware используется для перехвата входящих запросов и выполнения некоторых действий до их завершения. Действия могут заключаться в изменении ответа, перенаправлении на какой-то маршрут, изменении заголовков и т. д.
Например, в приведенном выше случае мы можем использовать промежуточное ПО для проверки IP-адреса входящих запросов и, если это авторизованное лицо, только отрисовать user/page.tsx
, в противном случае мы отрисовываем сообщение об ошибке или перенаправляем на другую страницу.
Создание Middleware в Next.js
Чтобы создать промежуточное ПО, создайте файл middleware.ts
в корне папки проекта.
Пример:
Выполните приведенную ниже команду в терминале, чтобы создать новое приложение Next.js:
npx create-next-app@latest
Отметьте «Да» для TypeScript и App Router, чтобы следовать за нами:
Теперь откройте проект в редакторе кода, удалите все файлы из директории app
и создайте файл page.tsx
для нашей главной страницы со следующим кодом:
const main = () => {
return <h1>Main Page</h1>;
};
export default main;
Теперь давайте создадим еще один маршрут /home
внутри каталога приложения, создав папку home
с файлом page.tsx
со следующим кодом:
const home = () => {
return <h1>Home Page</h1>;
};
export default home;
Теперь создайте файл middleware.ts
в папке проекта (не в приложении) со следующим кодом:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const response = NextResponse.rewrite(new URL('/home', request.url));
return response;
}
Это переписывает внутренний URL на /home
, а не перенаправляет. Это означает, что URL остается тем же, что запрашивал пользователь, но маршрут изменяется.
Выполните приведенную ниже команду, чтобы запустить проект:
npm run dev
Видите, мы пытаемся получить доступ к главной и тестовой странице (которой не существует), но в ответ получаем домашнюю страницу, это означает, что наше промежуточное ПО успешно перехватывает запрос и перенаправляет его на маршрут /home
.
Сопоставление путей
По умолчанию промежуточное ПО вызывается для каждого маршрута в проекте, поэтому важно указать, какой маршрут будет использоваться промежуточным ПО. Для этого у нас есть матчеры.
export const config = {
matcher: '/',
};
Для нескольких маршрутов:
export const config = {
matcher: ['/', '/about'],
}
Пример:
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
export function middleware(request: NextRequest) {
const response = NextResponse.rewrite(new URL('/home', request.url));
return response;
}
export const config = {
matcher: '/',
};
Если мы попытаемся получить доступ к маршруту /test
, промежуточное ПО не перенаправит нас.
Условные высказывания
Существует только один файл middleware.ts
или middleware.js
, поэтому мы можем использовать операторы условий, чтобы по-разному обрабатывать запросы для нескольких маршрутов.
import { NextResponse } from 'next/server';
import type { NextRequest } from 'next/server';
// Simulated authentication status for example
const isAuthenticated = false;
export function middleware(request: NextRequest) {
if (request.nextUrl.pathname === '/') {
// Redirect to /home
const response = NextResponse.rewrite(new URL('/home', request.url));
return response;
}
if (/^\/admin/.test(request.nextUrl.pathname)) {
// Check authentication status
if (!isAuthenticated) {
// Redirect to /login if not authenticated
const response = NextResponse.rewrite(new URL('/login', request.url));
return response;
} else {
// Redirect to requested page
return NextResponse.rewrite(request.url);
}
}
}
export const config = {
matcher: ['/', '/admin/:path*'],
}
В первом «если» мы используем строгие операторы равенства, а во втором - регулярные выражения для проверки всех маршрутов, начинающихся с «admin».
Настройка заголовков и файлов cookie
Мы также можем просматривать заголовки и куки в промежуточном ПО с помощью NextResponse API.
if (/^\/admin/.test(request.nextUrl.pathname)) {
// Check authentication status
if (!isAuthenticated) {
// Redirect to /login if not authenticated
const response = NextResponse.rewrite(new URL('/login', request.url));
// Set custom header
response.headers.set('x-error-message', 'Unauthorized User');
// Set cookie for unauthorized access
response.cookies.set('user-access', 'denied');
return response;
} else {
// Redirect to requested page
return NextResponse.rewrite(request.url);
}
}
Производство ответа
Кроме того, мы можем отправлять ответы из промежуточного ПО.
if (request.nextUrl.pathname === '/api/helloworld') {
return NextResponse.json({ message: 'Hello, World!' });
}
Заключение
Вкратце, промежуточное ПО – это код, который выполняется для каждой страницы в приложении Next.js для выполнения определенных действий, таких как изменение ответа, перенаправление, изменение заголовков, создание ответов и т. д.
Мы можем создать промежуточное ПО, создав файл middleware.ts
или middleware.js
в корне вашего проекта (не в директории app
), и всё, мы готовы обрабатывать все предстоящие запросы и ответы нашего приложения.