Да, для обычного fetch это хороший вариант. AbortController сократил бы лишний трафик, а requestId остался бы страховкой от ответа, который успел завершиться до abort.
Но в проекте saveAutosaveLabAction вызывается как Server Action. AbortSignal в неё напрямую не передать, аргументы action сериализуются. Отмена сетевого запроса также не гарантирует, что сервер не успел выполнить запись. Поэтому requestId решает отдельную задачу, старый ответ не меняет текущий UI. Для полноценной отмены пришлось бы вынести сохранение в Route Handler и вызывать его через fetch. В Workbench payload небольшой, поэтому работает этот компактный вариант. Для большого редактора лучше использовать оба механизма, плюс проверку версии документа на сервере
Да, это учебный проект с весьма заметной кнопкой Курс, где разбирается конкретный паттерн с localStorage, ограничения которого очевидны.
Через кнопку можно попасть в линейку с проектами на Supabase и Django. Там взыскательного пользователя уже ждут аккаунт, база данных и избранное без привязки к одному браузеру
Проверил проект внимательнее. Layout shift на первой загрузке действительно есть, согласен, но не при кликах после маунта. Hydration-ошибок при этом нет, ssr: false работает корректно.
Сдвиг убирается одинаковыми размерами контейнера до и после загрузки. В проекте оставлю как есть, для этого продукта считаю такую чистку избыточной
Да, cookies решают другой сценарий. Сервер читает значение до рендера и отдаёт HTML уже с нужным состоянием.
В проекте localStorage выбран сознательно. Избранное и история живут только в браузере, сервер их не использует. Компоненты с browser-only состоянием загружаются отдельно через ssr: false.
На текущей реализации проекта например в /goods/5 визуального layout shift при добавлении и удалении из избранного не заметил. Ошибок hydration тоже нет. Размер и поведение элементов заданы самим UI, а не случайностью. В статье есть ссылка на проект, можно проверить, что все ок.
Если persisted state влияет на первый серверный HTML, cookies подходят лучше. Если состояние нужно только после загрузки клиента, localStorage остаётся нормальным вариантом.
PersistStorage и фильтрация cookies уже отдельный паттерн. В этой статье рассматривался localStorage и client boundary в App Router.
Правильно конечно Mermaid/mermaid, в проекте чтобы не пересекать служебное и собственное имя кластера выбрал близкое Mermind/mermind из PictoMind/FlowMaid/SketchFlow/SchemaCraft
Спасибо за глубокий комментарий. Согласен, окружение тестирования (harness) сильно влияет на результат. Независимый black-box набор - правильный путь, особенно для threshold crypto, где «прошло демо» не гарантирует корректность при сбоях. В статье эта тема не раскрыта, вы правы
Верно, на скрине видно, что models параметр именно для автоматической замены при сбое, а не для параллельных вызовов. В статье описан кастомный fallback поверх API, не встроенный механизм
Вы правы, я смешал два разных сценария. Fallback - это последовательная подмена недоступной модели, а не параллельный опрос с агрегацией. Для параллельного опроса и суммаризации нужна отдельная логика, OpenRouter в базовом API этого не даёт, только через надстройку. Цена и выбор конкретной модели тоже важные ограничения, согласен.
Верно, fallback - это последовательный перебор, одна модель не ответила, пробуем следующую. Гарантия не абсолютная, если весь пул моделей недоступен, пользователь всё равно получит ошибку. В текущей реализации цикл проходит по списку один раз. Можно улучшить, либо использовать встроенный fallback OpenRouter (он пробует внутри себя), либо сделать цикл с повторным проходом и задержкой, либо добавить параллельный запрос к двум моделям и брать первый успешный ответ. Но это уже усложнение под конкретные сценарии
В проекте используется OpenRouter, он сам по себе уже является агрегатором моделей и поддерживает fallback между ними на уровне API. То есть описанная в статье логика - надстройка поверх его возможностей, а не замена. Но согласен, OpenAI Agents SDK тоже рабочий вариант для более сложной маршрутизации
Да, из статьи это следует прямо. Backend уже пробует разные модели при сбое, ничего не мешает расширить логику, отправлять запрос параллельно в несколько моделей, сравнивать результаты, выбирать лучший или агрегировать. Вопрос только в цене и времени ответа. OpenRouter, кстати, даёт такую возможность через routing и fallback на уровне платформы
Верно, что заметили. Должно быть «не дать доступ». У OpenRouter особенность - модели, которые числятся в /api/v1/models с фильтром free, не всегда реально доступны в момент запроса. Некоторые отдают ошибку при попытке вызова. Отсюда и логика с fallback - пробуем одну, не дало доступ, идём к следующей
У меня стиль мышления близок к ИИ-шному, не первый раз сталкиваюсь с таким вопросом. А так - да, кто ж сейчас не оптимизирует свои ресурсы через умных помощников? Статья написана на основе собственной кодовой базы и продовых сценариев, форма подачи какая есть
Да, справедливо. В статье я разбирал сценарий, где searchParams сознательно участвует в серверном fetch, поэтому изменение q действительно приводит к новой серверной навигации для затронутого сегмента. Но это не полный reload документа, в App Router навигация остаётся client-side transition, shared layouts сохраняются, а обновляется только нужная часть маршрута. Если реакция нужна полностью локальная и без нового серверного прохода, такое состояние лучше не поднимать в URL. Или разделять черновой ввод и подтверждённый фильтр. Про эту развилку тоже планирую написать позже.
Спасибо) ✌️ Сейчас сфокусирован на своих учебных и продуктовых проектах вокруг AI-чатов, микросервисов и платёжных решений. Готов обсудить формат сотрудничества, если есть конкретная концепция под мой стек (Next.js + Django) и понятная модель взаимодействия.
Да, для обычного fetch это хороший вариант. AbortController сократил бы лишний трафик, а requestId остался бы страховкой от ответа, который успел завершиться до abort.
Но в проекте saveAutosaveLabAction вызывается как Server Action. AbortSignal в неё напрямую не передать, аргументы action сериализуются. Отмена сетевого запроса также не гарантирует, что сервер не успел выполнить запись. Поэтому requestId решает отдельную задачу, старый ответ не меняет текущий UI. Для полноценной отмены пришлось бы вынести сохранение в Route Handler и вызывать его через fetch. В Workbench payload небольшой, поэтому работает этот компактный вариант. Для большого редактора лучше использовать оба механизма, плюс проверку версии документа на сервере
Да, это учебный проект с весьма заметной кнопкой Курс, где разбирается конкретный паттерн с localStorage, ограничения которого очевидны.
Через кнопку можно попасть в линейку с проектами на Supabase и Django. Там взыскательного пользователя уже ждут аккаунт, база данных и избранное без привязки к одному браузеру
Проверил проект внимательнее. Layout shift на первой загрузке действительно есть, согласен, но не при кликах после маунта. Hydration-ошибок при этом нет, ssr: false работает корректно.
Сдвиг убирается одинаковыми размерами контейнера до и после загрузки. В проекте оставлю как есть, для этого продукта считаю такую чистку избыточной
Да, cookies решают другой сценарий. Сервер читает значение до рендера и отдаёт HTML уже с нужным состоянием.
В проекте localStorage выбран сознательно. Избранное и история живут только в браузере, сервер их не использует. Компоненты с browser-only состоянием загружаются отдельно через
ssr: false.На текущей реализации проекта например в
/goods/5визуального layout shift при добавлении и удалении из избранного не заметил. Ошибок hydration тоже нет. Размер и поведение элементов заданы самим UI, а не случайностью. В статье есть ссылка на проект, можно проверить, что все ок.Если persisted state влияет на первый серверный HTML, cookies подходят лучше. Если состояние нужно только после загрузки клиента, localStorage остаётся нормальным вариантом.
PersistStorage и фильтрация cookies уже отдельный паттерн. В этой статье рассматривался localStorage и client boundary в App Router.
Спасибо за комментарий.
Вам спасибо, приятно, что интересно) Когда пощупал впервые Mermaid, был от него в восторге)
Правильно конечно Mermaid/mermaid, в проекте чтобы не пересекать служебное и собственное имя кластера выбрал близкое Mermind/mermind из PictoMind/FlowMaid/SketchFlow/SchemaCraft
Спасибо за глубокий комментарий. Согласен, окружение тестирования (harness) сильно влияет на результат. Независимый black-box набор - правильный путь, особенно для threshold crypto, где «прошло демо» не гарантирует корректность при сбоях. В статье эта тема не раскрыта, вы правы
Верно, на скрине видно, что models параметр именно для автоматической замены при сбое, а не для параллельных вызовов. В статье описан кастомный fallback поверх API, не встроенный механизм
Вы правы, я смешал два разных сценария. Fallback - это последовательная подмена недоступной модели, а не параллельный опрос с агрегацией. Для параллельного опроса и суммаризации нужна отдельная логика, OpenRouter в базовом API этого не даёт, только через надстройку. Цена и выбор конкретной модели тоже важные ограничения, согласен.
Верно, fallback - это последовательный перебор, одна модель не ответила, пробуем следующую. Гарантия не абсолютная, если весь пул моделей недоступен, пользователь всё равно получит ошибку. В текущей реализации цикл проходит по списку один раз. Можно улучшить, либо использовать встроенный fallback OpenRouter (он пробует внутри себя), либо сделать цикл с повторным проходом и задержкой, либо добавить параллельный запрос к двум моделям и брать первый успешный ответ. Но это уже усложнение под конкретные сценарии
Спасибо, все ок ✌️
У меня напротив эмодеформация, когда желательно разбавить лаконичность субъектными штучками)
В проекте используется OpenRouter, он сам по себе уже является агрегатором моделей и поддерживает fallback между ними на уровне API. То есть описанная в статье логика - надстройка поверх его возможностей, а не замена. Но согласен, OpenAI Agents SDK тоже рабочий вариант для более сложной маршрутизации
Да, из статьи это следует прямо. Backend уже пробует разные модели при сбое, ничего не мешает расширить логику, отправлять запрос параллельно в несколько моделей, сравнивать результаты, выбирать лучший или агрегировать. Вопрос только в цене и времени ответа. OpenRouter, кстати, даёт такую возможность через routing и fallback на уровне платформы
Верно, что заметили. Должно быть «не дать доступ». У OpenRouter особенность - модели, которые числятся в
/api/v1/modelsс фильтром free, не всегда реально доступны в момент запроса. Некоторые отдают ошибку при попытке вызова. Отсюда и логика с fallback - пробуем одну, не дало доступ, идём к следующейУ меня стиль мышления близок к ИИ-шному, не первый раз сталкиваюсь с таким вопросом. А так - да, кто ж сейчас не оптимизирует свои ресурсы через умных помощников? Статья написана на основе собственной кодовой базы и продовых сценариев, форма подачи какая есть
Да, справедливо. В статье я разбирал сценарий, где searchParams сознательно участвует в серверном fetch, поэтому изменение q действительно приводит к новой серверной навигации для затронутого сегмента. Но это не полный reload документа, в App Router навигация остаётся client-side transition, shared layouts сохраняются, а обновляется только нужная часть маршрута. Если реакция нужна полностью локальная и без нового серверного прохода, такое состояние лучше не поднимать в URL. Или разделять черновой ввод и подтверждённый фильтр. Про эту развилку тоже планирую написать позже.
Спасибо) ✌️
Сейчас сфокусирован на своих учебных и продуктовых проектах вокруг AI-чатов, микросервисов и платёжных решений. Готов обсудить формат сотрудничества, если есть конкретная концепция под мой стек (Next.js + Django) и понятная модель взаимодействия.
Мой Telegram: @Lemon1964 — пиши, если актуально