Как стать автором
Обновить

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

Время на прочтение9 мин
Количество просмотров1.7K

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

Vercel после сборки отправляет новый код Edge рантайма (для которого недавно сделали компиляцию в машинный код) на точки сети и те сразу начинают работать с новым кодом.

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

На этих точках всегда лежит логика кеширования, также, если в проекте есть реврайты, редиректы, middleware или сегменты в Edge рантайме — после сборки он отправит это всё на edge сервера.

Далее Edge рантайм начнёт обрабатывать запросы: проверит реврайты и редиректы → проведёт через middleware → посмотрит есть ли в кеше → если сегмент в edge рантайме — выполнит его у себя, если нет — отправит запрос на оригинальный сервер (но про все эти порядки в Edge рантайме и внутренности Vercel нигде не пишет, но вероятнее всего это проходит именно так).

То есть, суммарно — хорошо использовать Edge рантайм, когда можно сделать всю обработку внутри Edge среды (Запрос будет Client → Edge). Если же нужно ходить к основному серверу (допустим к БД которая подключена внутри проекта, или по какой‑то причине нужно читать файлы) — это будет не выгодно. То есть запрос всё равно будет Client → Edge → Server. А раз всё равно нужно ходить на сервер — лучше сразу всю обработку сделать в нём — в нём есть весь кеш, рядом лежит БД, рядом вся система, да и в целом больше возможностей.

Ожидаемые изменения в 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.

Спасибо @Dartess за комментарий с дельными вопросами (после которых статья была дополнена).

Теги:
Хабы:
Всего голосов 5: ↑4 и ↓1+5
Комментарии10

Публикации

Истории

Работа

Ближайшие события