Головна / Статті / Документ AGENTS.md від Vercel навчає штучних інтелект-асистентів 70 найкращих практик використання React

Документ AGENTS.md від Vercel навчає штучних інтелект-асистентів 70 найкращих практик використання React

Практичний огляд інструменту react-best-practices від Vercel, який демонструє, як він безпосередньо вбудовує 70 правил React, перевірених у реальних проектах, у код, створений штучним інтелектом.

1477 слів

Колега з команди платформи поділився посиланням у внутрішньому каналі Slack без жодних пояснень — лише сире URL та емодзі у вигляді підйому плечей. Посилання вело до репозиторію vercel-labs/agent-skills, а саме до елемента react-best-practices. Спочатку очікувалося ще одне перероблене спискове матеріал про „поради щодо продуктивності React“, адаптоване під потреби штучного інтелекту. Але це виявилося не так. Натомість це посібник із 70 правил у 8 категоріях, який Vercel описує як результат аналізу більш ніж десяти років досвіду роботи з продакшн-застосунками на React та Next.js, які постійно виходили з ладу за певними схемами. Важливо те, що він розроблений насамперед для використання штучним інтелектом-асистентом з кодування, а людиною-розробником — лише в другу чергу.

Саме ця структура є суттю того, що робить це особливим, і варто зупинитися на ній перед тим, як перейти до самого змісту правил.

Що насправді є у репозиторії

Щоб встановити цю навичку, достатньо одного командного запиту:

npx skills add vercel-labs/agent-skills

Насправді це компілюється у файл AGENTS.md — це стандарт, який набуває популярності як спосіб надання структурованого контексту проекту кодуючим агентам (інструменти на кшталт Claude Code, Cursor, Codex та OpenCode шукають саме цей файл). Як тільки він створений, ваш агент має посібник з правилами, на який може посилатися під час написання чи перегляду коду, замість того щоб покладатися виключно на різноманітні туторіали з React, які випадково потрапили до його навчальних даних.

70 правил розділено на вісім категорій, кожна з яких має позначку пріоритету від CRITICAL до LOW. Дві категорії, позначені як CRITICAL, — це, як і очікувалося, ті, на які звертає увагу команда Vercel як на основні причини проблем у реальних умовах: послідовні асинхронні операції, що створюють ефект «водоспаду», та неконтрольоване збільшення розміру пакету. Типове правило з категорії «водоспад» формулює цю ідею ось так:

// Flagged: sequential awaits create a waterfall
async function getThreadPage(threadId) {
  const thread = await getThread(threadId)
  const author = await getAuthor(thread.authorId)
  const replies = await getReplies(threadId)
  return { thread, author, replies }
}
// Preferred: parallelize independent fetches
async function getThreadPage(threadId) {
  const [thread, replies] = await Promise.all([
    getThread(threadId),
    getReplies(threadId),
  ])
  const author = await getAuthor(thread.authorId)
  return { thread, author, replies }
}

Усе це не є чимось проривним, якщо ви вже маєте досвід роботи з React. Насправді цікавим є не сам зміст правила — а те, що тепер воно існує у формі, яку машина може обробити та застосувати однаково у всій кодбазі, навіть о 2 години ночі під час pull request, який ніхто ретельно не перевіряв, без втоми чи швидких рішень, які з’являються під тиском кінцевого терміну.

Чому це відрізняється від лінтера

Першою реакцією є запитання: чи не є це просто ESLint у іншому вигляді. У певному сенсі — так, але саме механізм робить його унікальним. Linter вказує на проблему після того, як код вже створений. Цей підхід спрямований на вплив на код під час його створення, щоб виявити проблему ще до того, як вона буде введена. Якщо штучний інтелектовий асистент відповідає за 30–60 відсотків різниці у змінах певного pull request (а оцінки цього показника сильно варіюються залежно від того, кого ви запитаєте у команді), то вбудовування правил безпосередньо у процес генерації є принципово іншим способом впливу, ніж виявлення помилок пізніше.

Існує ще один тип рекомендацій, які лінтер просто не підходить для формулювання: архітектурні судження. Правило на кшталт «уникайте створення моделі типу „водоспад“» принаймні приблизно може бути реалізоване лінтером за наявності достатньої кількості налаштувань та толерантності до хибних позитивних результатів. Але щось на кшталт «цей компонент, ймовірно, слід перетворити на серверний компонент, оскільки в нього немає інтерактивної поведінки, а межа клієнта навколо нього виглядає довільною» вимагає реальних міркувань щодо наміру та структури — саме таких рішень, думка про які мала б бути отримана від агента, а не просто нав’язана через збіг шаблонів.

Де з’являється скептицизм

Варто прямо назвати ту незручну частину. Набір правил, створений тією самою компанією, яка розробляє фреймворк, а чия платформа хостингу випадково заохочує певні моделі продуктивності, за замовчуванням не є нейтральним документом. Деякі рекомендації критичного рівня щодо розміру пакетів занадто чітко відповідають тим моделям, які також роблять власні панелі аналітики та систему кешування Vercel чудовими. Однак це перетин не робить поради автоматично поганою. Уникнення асинхронних послідовностей є розумною інженерною практикою, незалежно від того, хто обслуговує ваш додаток. Проте справедливо пам’ятати, що „найкращі практики“, підібрані постачальником, ніколи не є суто технічними документами — завжди є ледь помітний маркетинговий підтекст, який поєднується з інженерними порадами.

Друга проблема має більш структурний характер: що буде, коли кількість правил зросте з 70 до 200, або коли інструменти від конкуруючих постачальників почнуть потрапляти до одного й того ж файлу AGENTS.md та суперечити один одному? Наразі, завдяки єдиному репозиторію та абсолютно новій концепції, все здається організованим та зрозумілим. Однак через вісімнадцять місяців легко уявити, що кожна платформа, кожен постачальник хостингу та кожна система дизайну будуть хотіти, щоб їхні інструменти були встановлені окремо. У такому разі ваш агент може мати справу з купою посібників із суперечливими вказівками, і може не бути очевидного способу визначити, які з них мають перевагу.

Тестування на реальному кодовому базисі

Швидше з цікавості, ніж через очікування, цей інструмент було застосовано до середнього за розміром внутрішнього панелі керування, щоб побачити, що саме він виявить. Виявлені проблеми рівня CRITICAL та HIGH виявилися досить буденними: кілька послідовних викликів await, які можна було б виконати паралельно, кілька клієнтських компонентів, які не мали реальної потреби бути клієнтськими компонентами, та один досить незручний випадок — використання цілої бібліотеки для обробки дат лише для форматування одного значення. Усе це не здивує тих, хто вже проводив серйозний аналіз продуктивності кодової бази на React. Однак варто було звернути увагу на швидкість — агенту знадобилося приблизно чотири хвилини, щоб знайти та позначити всі ці проблеми, на відміну від того, скільки часу знадобиться людині-рецензентові, щоб виявити ті самі проблеми, розкидані по великому запиту на зміни.

Саме ця різниця у швидкості є справжньою ключовою перевагою тут. Самі правила не є проривними — більшість досвідчених інженерів вже інстинктивно володіють цими знаннями. Змінюється те, що правила тепер застосовуються з такою послідовністю та швидкістю, яку людський рецензент, особливо той, хто вже проводить третю перевірку за день, просто не може підтримувати.

Недооцінена перевага: навчання, а не лише примус

Те, що насправді змінило підхід до аналізу коду, — це не самі перевірки продуктивності, а спостереження за тим, як новий член команди використовує інструмент. Ця людина працювала в команді лише кілька місяців та все ще ознайомлювалася з кодовою базою. Перш ніж створити запит на об’єднання коду, вона попросила свого агента спочатку його переглянути. Агент виявив певну структуру виконання операцій та, замість простого позначення проблеми, пояснив простою мовою — безпосередньо пов’язуючи це з конкретним правилом — чому виконання цих операцій паралельно має значення саме в цьому контексті. Це суттєво відрізняється від роботи інструменту для перевірки коду, який просто виводить ідентифікатор правила та коротке повідомлення, які потрібно окремо шукати. Це було схоже на коментар від досвідченого інженера, який залишає справді корисний відгук, тільки зворотний зв’язок надходив ще до того, як запит на об’єднання коду навіть вийшов з режиму чернетки.

Це, можливо, є більш переконливим сценарієм використання, ніж твердження про те, що «ШІ пише більш чистий код». Це ближче до формулювання «ШІ виховує кращі звички» — постійно та без необхідності, щоб хтось виділяв час на наставництво або писав документацію для ознайомлення, яка за шість місяців стає застарілою. Чи збережеться ця перевага, коли в команді буде п’ятдесят файлів з накладаючимися навичками — кожен із власними поглядами, деякі з яких неминуче будуть суперечити іншим — залишається відкритим питанням. Але для невеликої команди, що складається з одного досвідченого інженера та кількох людей, які ще знаходять своє місце, це вже справді є фактором, що посилює ефективність.

Яке це дає результат

Ця функція врешті-решт була додана до спільної конфігурації команди, головним чином тому, що недоліки мінімальні, а переваги — агент, який припиняє створення коду у форматі «водоспад», — є доцільною ціною за такий крок. Чи стане цей підхід стандартним способом, яким фреймворки передають свої ідеї AI-агентам, чи просто перетвориться на ще один файл конфігурації, який поступово втратить актуальність після того, як новизна зникне, і ніхто не буде його оновлювати, поки що незрозуміло. Це питання варто переглянути через шість місяців, а не відповідати на нього зараз.

Пов’язана література

  • Inside TypeScript 7's Go Rewrite: Speed Gains Without Code Changes — Дізнайтеся, як компілятор TypeScript 7 на основі Go забезпечує у 8–12 разів швидшу компіляцію, чому така зміна архітектури ефективна та як безпечно оновлювати існуючі проекти.
  • Часткове попереднє оброблення та одночасне оброблення: пояснення — Дізнайтеся, як функції часткового попереднього оброблення в Next.js та одночасного оброблення в React вирішують проблему повільної роботи додатків, дозволяючи фреймворкам планувати та виконувати завдання поетапно замість того, щоб розглядати процес обробки як єдину блокуючу одиницю.