Vercel VS Edge VS Next. Что такое Edge, зачем, как и куда

от автора

Edge рантайм. Один из главных функционалов компании Vercel — компании, которая разработала и развивает next.js. Тем не менее, её влияние по edge рантайму вышло далеко за рамки её фреймворков и утилит. Edge рантайм работает и в недавно купленном Vercel Svelte, и в nuxt, и в более чем 30 других фронтенд фреймворках. Эта статья будет посвящена edge рантайму — что это, как это используется в Vercel, какими возможностями дополняет next.js и какие решения сделал я, чтобы эти возможности расширить.

Vercel Edge Network

Простыми словами Edge рантайм представляет из себя сеть доставки контента (CDN/распределённая инфраструктура), то есть множество точек по всему миру. Таким образом пользователь взаимодействует не с единым сервером (который может лежать в офисе компании на другом конце света), а с ближайшей к нему точкой сети.

Разница обращения напрямую на сервер или через Edge Network

Разница обращения напрямую на сервер или через Edge Network

При этом, это не копии приложения, а отдельный функционал, который может работать между клиентом и сервером. То есть это своего рода мини-сервера со своими особенностями (о которых будет рассказано позже).

Эта система позволяет пользователям ходить не сразу на ваш далёкий сервер, а на близлежащую точку. В ней принимаются решения по а/б тестам, делаются проверки авторизации, кешируются запросы, возвращаются ошибки и многое другое. Уже после этого, если нужно, запрос пойдёт на сервер, сразу за нужной информацией. Иначе же пользователь в минимальные сроки получает ошибку или, например, редирект.

Обработка запросов через Edge Network

Обработка запросов через Edge Network

Конечно, сама эта концепция не является заслугой Vercel. Так умеет и CloudFlare, и Google Cloud CDN и множество других решений. Однако, Vercel, своим влиянием на фреймворки, вывел это на новый уровень, развернув не просто промежуточный роутер на уровне CDN, а сделав мини-приложения, способные даже рендерить страницы в ближайшей к пользователю точке. И самое главное — сделать это можно просто добавив привычные JS файлы в проект.

Edge-рантайм в next.js

В next.js пожалуй главным функционалом этой среды является файл middleware. Любой сегмент (API или страница) также могут исполняться в edge рантайме. Но перед их описанием, немного о next.js сервере.

Next.js — это фуллстак фреймворк. То есть он содержит и клиентское приложение, и сервер. Запуская next.js (next start) — запускается именно сервер и уже он отвечает за выдачу страниц, работу API, кеширование, реврайты и т.д.

Работает это всё в следующем порядке:

  1. headers из next.config.js;

  2. redirects из next.config.js;

  3. Middleware;

  4. beforeFiles реврайты from next.config.js;

  5. Файлы и статичные сегменты (public/_next/static/pages/app/, etc.);

  6. afterFiles реврайты из next.config.js;

  7. Динамические сегменты (/blog/[slug]);

  8. fallback реврайты из next.config.js.

Когда определяется, что текущей запрос доходит именно до сегмента (а не, например, до редиректа) — запускается его обработка (это либо возврат статически собранного сегмента, либо чтение из кеша, либо его выполнение и возврат результата).

В Vercel, вероятно, весь этот цикл может пройти в edge рантайме. Тем не менее, действительно интересны здесь именно пункты 3, 5 и 7.

Сам middleware в базовой имплементации выглядит так:

import { NextResponse, type NextRequest } from 'next/server';  export function middleware(request: NextRequest) {     return NextResponse.redirect(new URL('/home', request.url)); }

В нём, например, можно:

  • Сделать запросы (напр. чтобы узнать данные из третьих сервисов);

  • Выполнить реврайт или редирект (напр. чтобы провести а/б тест или проверить авторизацию);

  • Вернуть некое тело (напр. чтобы отобразить базовую заглушку при определённых ситуациях);

  • Прочитать и/или изменить заголовки и куки (напр. сохранить или прочитать информацию о доступах).

Подробнее про области применения можно почитать в документации next.js по middleware.

Тоже самое можно делать и в сегментах (т.е. API и страницы). Чтобы сегмент работал в edge рантайме нужно экспортировать из файла сегмента:

export const runtime = 'edge';

Таким образом сегмент будет исполняться в edge рантайме, а не на самом сервере.

Однако, стоит сделать важную оговорку. Всё описанное выше само по себе не является полноценным edge рантаймом. В Edge Network это распределится только при деплое сервиса в Vercel.

Также, помимо всех этих возможностей, у edge рантайма есть и ряд ограничений. Например, несмотря на то, что при запуске приложения вне Vercel, edge рантайм является частью сервера — взаимодействовать с этим сервером не удастся. И сделано это так потому, что разрабатывалось это именно под Vercel Edge Network.

Концепция edge рантайма в Vercel

Как уже говорилось, edge рантайм можно назвать мини-приложениями. А мини они потому, что работают на node.js V8 (на котором работают например Google Chrome и Electron). Это их ключевая особенность, от которой зависят не только возможности предыдущего раздела, но и запреты.

А именно, в edge рантайме нельзя:

  • Делать действия с файловой системой;

  • Взаимодействовать с окружением сервера;

  • Вызывать require. Можно использовать только ES модули. От этого есть дополнительные ограничения на сторонние решения.

Полный список поддерживаемых API и ограничений можно найти на странице документации next.js.

Таким образом Vercel Edge Network может отвечать, например, за:

  • Роутинг;

  • Рендер страниц;

  • Выполнение API роутов;

  • Кеширование.

Edge рантайм выступает первым этапом обработки сегмента и наиболее эффективен он для ситуаций, когда вся обработка может пройти внутри edge контейнера. Например для редиректов или возврата закешированных данных. Весь процесс обработки в Vercel обычно работает в следующем порядке:

Порядок обработки запроса в Vercel, источник - vercel.com

Порядок обработки запроса в Vercel, источник — vercel.com

Ожидаемые изменения в edge рантайме

Несмотря на то, что edge рантайм — одна из ключевых возможностей Vercel как хостинга, команда активно его пересматривает. При чём не только само применение, но и необходимость в целом. Так, недавно VP Vercel — Ли Робинсон в своём твите поделился, что Vercel [как компания] перестала использовать edge рантайм во всех своих сервисах и вернулась к nodejs рантайму. Также команда ожидает, что экспериментальный частичный пререндер (PPR) будет настолько эффективен, что генерация в edge рантайме окончательно потеряет ценность.

И именно PPR вместе с продвинутым кешированием вытеснил edge рантайм на второй план. То есть раньше страница рендерилась целиком что на сервере, что в edge рантайме. Edge рантайм выигрывал именно за счёт более близкого расположения. Теперь же, страницы в большей части генерируются предварительно. Затем, при запросе, рендерятся отдельные динамические части и кешируются. Кеш, в свою очередь, в edge рантайме для каждой точки свой, когда на сервере он един для всех пользователей.

Ну и, конечно, у сервера есть доступы к окружению, БД и файловой системе. Поэтому если странице нужны эти данные — nodejs рантайм значительно выигрывает (собрать всё в одном окружении быстрее, чем каждый раз делать запросы на сервер из edge среды).

Скорее всего Vercel введёт новые приоритеты в своих прайсингах, перестроив их вокруг частичного пререндера. Возможно с их изменением твитов со счетами в десятки тысяч долларов станет меньше (но это не точно).

Инвойс за использование Vercel в $100000, источник - твит фаундера Cara.

Инвойс за использование Vercel в $100000, источник — твит фаундера Cara.

Помимо этого, недавно команда Next.js поделилась твитом о переработке middleware. Весьма вероятно ему, также как и сегментам, добавят выбор среды исполнения. Опять же, учитывая что вне Vercel middleware работает как часть сервера — это очень логичное решение. Также возможно, что вместе с изменениями будет добавлен отдельный middleware для API роутов.

Расширение Edge рантайма

Я автор ряда пакетов под next.js nimpl.tech. Я уже упоминал геттеры с информацией о текущей странице в статье “Next.js App Router. Опыт использования. Путь в будущее или поворот не туда”, библиотеке переводов в “Больше библиотек богу библиотек или как я переосмыслил i18n [next.js v14]”, пакеты для кэша в “Кеширование next.js. Дар или проклятие”. Но в этом семействе есть также и пакеты, построенные именно под edge рантайм — router и middleware-chain.

@nimpl/router

Как уже говорилось, edge рантайм лучше всего работает если он может обработать весь запрос в замкнутом мини-приложении. Во всех остальных случаях это ненужный шаг, так как запрос все равно будет ходить на сервер, но более длинным путём.

Одна из таких задач — роутинг. В роутинг входят также реврайты, редиректы, basePath и i18n из next.config.js.

Их главные проблема в том, что задаются они лишь единожды — в файле конфигурации — для всего приложения, а i18n полон багов. Поэтому в том числе в App Router нет информации об опции i18n и документация рекомендуют использовать для этой задачи middleware. Но такое разделение означает, что редиректы из конфига и i18n роутинг из middleware обрабатываются отдельно. От этого могут происходить двойные редиректы (сперва выполнится редирект из конфига, затем редирект из middleware) и вылезать различные неожиданные артефакты.

Чтобы этого избежать весь этот функционал стоит собрать в одном месте. И, как рекомендует документация для i18n — таким местом должен стать middleware.

import { createMiddleware } from '@nimpl/router';  export const middleware = createMiddleware({     redirects: [         {             source: '/old',             destination: '/',             permanent: false,         },     ],     rewrites: [         {             source: '/home',             destination: '/',             locale: false,         },     ],     basePath: '/doc',     i18n: {         defaultLocale: 'en',         locales: ['en', 'de'],     }, });

Привычные Next.js редиректы, реврайты, basePath и i18n настройки, но на уровне edge рантайма. Документация пакета @nimpl/router.

@nimpl/middleware-chain

Работая с готовыми решениями или создавая свои — из раза в раз я сталкивался с проблемой их объединения в одном middleware. То есть когда к одному проекту нужно подключить два и более готовых middleware.

Проблема в том, что middleware в next.js это не тоже самое, что в express или koa — он сразу возвращает финальный результат. Поэтому каждый пакет просто создаёт финальный middleware. Например у next-intl это выглядит следующим образом:

import createMiddleware from 'next-intl/middleware'; export default createMiddleware({     locales: ['en', 'de'],     defaultLocale: 'en', });

Я не первый столкнулся с этой проблемой, и в npm можно найти уже готовые решения. Все они работают через свои собственные API — сделанные в стиле express или в их собственном видении. Они полезны, хорошо реализованы и удобны. Но только в тех случаях, когда вы можете обновить каждый используемый middleware.

Однако, есть много ситуаций, когда нужно добавить уже готовые решения. Обычно в задачах этих решений можно найти «добавить поддержку для добавления пакета цепи A”, “работать с пакетом цепи B». Именно для таких ситуаций и создан @nimpl/middleware-chain.

Этот пакет позволяет создавать цепь нативных next.js middleware без каких-либо модификаций (то есть, можно добавить любой готовый middleware в цепь).

import { default as authMiddleware } from "next-auth/middleware"; import createMiddleware from "next-intl/middleware"; import { chain } from "@nimpl/middleware-chain";  const intlMiddleware = createMiddleware({     locales: ["en", "dk"],     defaultLocale: "en", });  export default chain([     intlMiddleware,     authMiddleware, ]);

Цепь обрабатывает каждый middleware поочерёдно. При обработке собираются все модификации до завершения цепи или пока какой-нибудь элемент цепи не вернёт FinalNextResponse.

export default chain([     intlMiddleware,     (req) => {         if (req.summary.type === "redirect") return FinalNextResponse.next();     },     authMiddleware, ]);

Это не Koa и не Express, это пакет для next.js, в его уникальном стиле и в формате его API. Документация пакета @nimpl/middleware-chain.

Ну и в завершении позволю себе немного ссылок.

Мой хабр с другими полезными статьями | nimpl.tech с документацией пакетов | github с кнопкой звёздочек


Карта из точек, используемая в качестве фона изображений в начале статьи сделана mocrovector с freepik.


ссылка на оригинал статьи https://habr.com/ru/articles/829074/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *