Перезапись HTML и преобразование реквизитов страниц в Next.js с помощью Next.js Advanced Middleware

Обращаемся ко всем разработчикам Next.js! Хотели бы вы сделать больше с промежуточным ПО? Хотите ли вы иметь возможность перехватывать и переписывать ответ статически сгенерированной страницы Next.js на границе на основе данных о геолокации? Вы также хотите иметь возможность преобразовывать реквизиты страницы на лету?

Теперь вы можете! С помощью Next.js Advanced Middleware. Она работает на базе Netlify Edge Functions, совершенно новой и только на Netlify.

В этом руководстве я покажу вам, как использовать Next.js Advanced Middleware на Netlify для перехвата запроса к статически предварительно созданной странице и переписать HTML-ответ, чтобы изменить текст и реквизиты страницы на основе данных о геолокации.

Развертывание кода учебника на Netlify

Вот демо-сайт, который я создал ранее! Если вы хотите немедленно приступить к работе, вы можете форкнуть репозиторий кода учебника на GitHub и развернуть сайт на своей собственной учетной записи Netlify за считанные секунды. Нажмите на кнопку Deploy to Netlify ниже и попробуйте!

Создайте его самостоятельно

В качестве альтернативы, если вы хотите создать код с нуля, вы можете следовать приведенному ниже руководству, чтобы создать новый проект Next.js, добавить новый статический маршрут и использовать промежуточное ПО для переписывания HTML ответа в The Edge.

Предварительные условия

Прежде чем приступить к работе, проверьте, есть ли у вас инструменты, необходимые для выполнения этого руководства.

  • Node.js (рекомендуется LTS)
  • GitHub CLI
  • Netlify CLI — последняя версия

Настройка проекта

Давайте создадим новое приложение Next.js. Перейдите в терминал и выполните следующую команду, заменив YOUR_PROJECT_NAME на выбранное вами имя.

npx create-next-app {YOUR_PROJECT_NAME}
Войдите в полноэкранный режим Выйти из полноэкранного режима

Далее, для того чтобы волшебство произошло, нам понадобится пакет @netlify/next. Выполните следующую команду в терминале, которая установит пакет как зависимость в файл package.json проекта.

npm install @netlify/next
Вход в полноэкранный режим Выйдите из полноэкранного режима

Далее откройте проект в выбранной вами IDE.

Добавьте новый статический маршрут

Next.js предлагает маршрутизацию на основе файлов. Добавление файла JavaScript или TypeScript в каталог pages создает новый маршрут браузера с тем же именем, что и файл. Создайте новый файл в каталоге pages с именем static.js и добавьте следующий код.

// pages/static.js

const Page = () => {
  return (
    <main>
      <h1 id="message">A static page</h1>
    </main>
  );
};

export default Page;
Вход в полноэкранный режим Выйдите из полноэкранного режима

Вернувшись в терминал, запустите сервер разработки с помощью Netlify CLI, выполнив следующую команду.

netlify dev
Войти в полноэкранный режим Выйти из полноэкранного режима

Автоматически откроется вкладка браузера на localhost:8888. Перейдите на http://localhost:8888/static в вашем браузере, и там будет ваша новая статическая страница.

Мы собираемся предварительно сгенерировать эту страницу во время сборки с некоторыми базовыми данными, прежде чем преобразовать ее с помощью Next.js Advanced Middleware. Экспортируя функцию getStaticProps из файла страницы, Next.js будет предварительно генерировать эту страницу во время сборки, используя данные, возвращаемые getStaticProps().

Добавьте следующий код в static.js и передайте реквизит message в функцию Page.

// pages/static.js

export async function getStaticProps() {
  return {
    props: {
      message: "This is a static page — and now this is a prop!",
    },
  };
}

const Page = ({ message }) => {
  return (
    <main>
      <h1 id="message">{message}</h1>
    </main>
  );
};

export default Page;
Вход в полноэкранный режим Выход из полноэкранного режима

И чтобы убедиться, что все подключено, вот наша обновленная статическая страница, использующая реквизит message.

Далее, переходим к промежуточному программному обеспечению!

Переписывание HTML и преобразование данных страницы

Промежуточное ПО в Next.js позволяет запускать код до завершения HTTP-запроса — оно находится в середине запроса и ответа. Вы можете создать файл промежуточного ПО в Next.js, используя JavaScript или TypeScript, и для целей этого руководства мы будем писать промежуточное ПО на TypeScript.

В корне вашего проекта создайте новый файл и назовите его middleware.ts. Этот файл будет запускаться на каждый запрос при работе вашего приложения — включая страницы, статические файлы и активы. В middleware.ts добавьте следующий код. Мы импортируем тип NextRequest, который представляет входящий HTTP-запрос, экспортируем асинхронную функцию middleware и передаем запрос как nextRequest в функцию, которая является объектом NextRequest.

// middleware.ts

import type { NextRequest } from "next/server";

export async function middleware(nextRequest: NextRequest) {

}
Вход в полноэкранный режим Выход из полноэкранного режима

В этом демо мы хотим, чтобы промежуточное ПО запускалось на маршруте с именем static. Давайте получим имя пути из запроса и подготовим функцию, которая будет делать что-то, когда имя пути начинается с static.

// middleware.ts

import type { NextRequest } from "next/server";

export async function middleware(nextRequest: NextRequest) {
  const pathname = nextRequest.nextUrl.pathname;

  if (pathname.startsWith("/static")) {
    // do something here
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Далее настало время для магии Netlify. Давайте перепишем HTML статической страницы, которую мы создали ранее. В верхней части файла импортируйте MiddlewareRequest как именованный импорт из @netlify/next.

// middleware.ts

import type { NextRequest } from "next/server";
import { MiddlewareRequest } from "@netlify/next";

export async function middleware(nextRequest: NextRequest) {
  const pathname = nextRequest.nextUrl.pathname;

  if (pathname.startsWith("/static")) {
    // do something here
  }
}
Вход в полноэкранный режим Выход из полноэкранного режима

Внутри функции middleware инициализируем новый Netlify MiddlewareRequest, передавая исходный NextRequest в качестве nextRequest.

import type { NextRequest } from "next/server";
import { MiddlewareRequest } from "@netlify/next";

export async function middleware(nextRequest: NextRequest) {
  const pathname = nextRequest.nextUrl.pathname;

  const middlewareRequest = new MiddlewareRequest(nextRequest);

  if (pathname.startsWith("/static")) {
    // do something here
  }
}
Вход в полноэкранный режим Выйти из полноэкранного режима

Это улучшает исходный объект запроса, добавляя все хорошее, что есть в Netlify Edge Functions. Netlify Edge Functions очень похожи на бессерверные функции. Вы можете написать их на JavaScript или TypeScript, но вместо использования Node.js под капотом, они работают на базе Deno — среды выполнения с открытым исходным кодом, построенной на веб-стандартах — и выполняются на ближайшем к запросу сервере. Это позволяет полностью персонализировать страницы на The Edge в Next.js, без необходимости использовать getServerSideProps() в маршрутах страниц. Это также работает с Incremental Static Regeneration.

Теперь наш объект NextRequest выровнен с объектом Netlify MiddlewareRequest, у нас есть возможность изменять HTTP-ответ до его возвращения — потому что мы можем фактически отправить запрос на источник, чтобы получить его и работать с ним.

Добавьте следующий код внутри оператора if, и давайте распакуем, что он делает.

// middleware.ts

import type { NextRequest } from "next/server";
import { MiddlewareRequest } from "@netlify/next";

export async function middleware(nextRequest: NextRequest) {
  const pathname = nextRequest.nextUrl.pathname;

  const middlewareRequest = new MiddlewareRequest(nextRequest);

  if (pathname.startsWith("/static")) {
    const response = await middlewareRequest.next();    

    const message = `This was a static page but has been transformed in 
                     ${nextRequest?.geo?.city}, 
                     ${nextRequest?.geo?.country} using 
                     @netlify/next in middleware.ts!`;

    response.replaceText("#message", message);
    response.setPageProp("message", message);

    return response;
  }
}
Войти в полноэкранный режим Выйти из полноэкранного режима

Если имя пути начинается с static, мы получаем следующий ответ в цепочке HTTP, ожидая middlewareRequest.next() — это наша статическая страница — и присваиваем его переменной response. Затем, используя геолокационные данные из nextRequest, мы создаем новое персонализированное сообщение, заменяющее содержимое статической страницы.

Next.js Advanced Middleware от Netlify включает функцию replaceText, а также имеет поддержку более мощных преобразований с помощью потокового трансформатора HTML Rewriter. Чтобы получить доступ к сообщению из DOM в функции middleware, мы добавляем ID к узлу DOM, содержащему сообщение, которое мы хотим преобразовать на статической странице.

// pages/static.js

const Page = ({ message }) => {
  return (
    <main>
      <h1 id="message">{message}</h1>
    </main>
  );
};
Вход в полноэкранный режим Выйти из полноэкранного режима

Затем мы выполняем replaceText в ответе, передавая в DOM ID, который мы добавили к сообщению в static.js, и новое сообщение, которое мы создали. Чтобы убедиться, что гидратированное содержимое на клиенте соответствует HTML, отображаемому на сервере (и чтобы избежать ошибки React hydration error), мы также можем обновить реквизиты страницы с помощью setPageProp, чтобы обновить данные сообщения на странице.

Наконец, верните ответ! Вернитесь в браузер и посмотрите на обновленное сообщение на ранее статически сгенерированной странице.

Сообщение было преобразовано в файле промежуточного ПО, а HTML статической страницы был переписан. Более того, реквизит страницы также был обновлен! Просмотрите исходный текст страницы, найдите NEXT_DATA в DOM и проверьте обновленный реквизит сообщения страницы — все это с помощью Next.js Advanced Middleware от Netlify.

Давайте развернем Netlify, чтобы посмотреть, как HTML-перезапись происходит в реальном времени на живом URL.

Подключение вашего git-репозитория

У нас есть несколько вариантов того, как развернуть проект Next.js в Netlify. В этом руководстве мы подключимся к новому git-репозиторию, чтобы бесплатно получить CI/CD и настройки.

Проекты Next.js поставляются с уже инициализированным git-репо. Поставьте и зафиксируйте свои файлы с помощью следующих команд.

git add . # stage your files
git commit -m 'Initial commit' # commit your files with a commit message
Войти в полноэкранный режим Выйти из полноэкранного режима

Следующие шаги помогут вам добавить ваш репозиторий в GitHub с помощью GitHub CLI — но вы можете отправить свой проект в GitHub любым удобным для вас способом.

Выполните следующую команду в терминале, чтобы создать новый репозиторий, подключенный к вашей учетной записи GitHub:

gh repo create
Войти в полноэкранный режим Выйти из полноэкранного режима

В ответ на запрос о типе репозитория, который вы хотите создать, выберите: Push an existing local repository to GitHub. Следуйте оставшимся подсказкам, чтобы заполнить соответствующие детали проекта. Теперь вы готовы к развертыванию в Netlify!

Развертывание в Netlify с помощью Netlify CLI

Если вы еще не вошли в Netlify CLI, выполните следующую команду в терминале и следуйте подсказкам для авторизации в Netlify (откроется окно браузера).

netlify login
Войти в полноэкранный режим Выход из полноэкранного режима

Далее выполните следующую команду для инициализации нового проекта на Netlify.

netlify init
Войти в полноэкранный режим Выйти из полноэкранного режима

Заполните следующие подсказки для настройки нового проекта:

  • Что вы хотите сделать? Создать и настроить новый сайт.
  • Команда: YOUR_TEAM
  • Название сайта (необязательно): CHOOSE_UNIQUE_SITE_NAME

Netlify CLI автоматически определит, что вы используете Next.js, поэтому следующие подсказки будут предварительно заполнены. Нажмите Enter, чтобы использовать значения по умолчанию.

  • Ваша команда сборки (hugo build/yarn run build/etc): (next build).
  • Каталог для развертывания (пустой для текущего каталога): (.next)
  • Папка функций Netlify: (netlify/functions).

Подождите несколько секунд… и ваш новый сайт развернут! 🎉 Теперь вы можете продемонстрировать свои новые навыки персонализации в Next.js, отправив живой URL своим друзьям.

Узнайте больше

Посетите официальную документацию Netlify, чтобы узнать о том, что теперь возможно с Next.js Advanced Middleware — только на Netlify.

Оцените статью
devanswers.ru
Добавить комментарий