revise June and August 2019 articles
Build and deploy / deploy (push) Successful in 13s

This commit is contained in:
2026-07-31 10:49:16 +03:00
parent bbedf1ae87
commit 18adfa80b4
12 changed files with 1607 additions and 1 deletions
@@ -0,0 +1,46 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 760" role="img" aria-labelledby="title desc">
<title id="title">Критический путь первого экрана</title>
<desc id="desc">Схема показывает, как начальный HTML открывает обнаружение CSS, JavaScript и hero-изображения, а затем свободный главный поток и готовые стили позволяют нарисовать полезный экран.</desc>
<defs>
<linearGradient id="background" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#111b30"/>
<stop offset="1" stop-color="#243350"/>
</linearGradient>
<marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#a7bad7"/>
</marker>
</defs>
<rect width="1000" height="760" fill="url(#background)"/>
<g font-family="Arial, sans-serif">
<text x="70" y="68" fill="#f8fbff" font-size="34" font-weight="700">Критический путь полезного экрана</text>
<text x="70" y="104" fill="#c1cee2" font-size="20">Быстрый ответ HTML полезен, но не завершает визуальную работу браузера.</text>
<rect x="70" y="156" width="260" height="110" rx="20" fill="#4a93e9"/>
<text x="200" y="202" text-anchor="middle" fill="#0e2038" font-size="25" font-weight="700">HTML</text>
<text x="200" y="234" text-anchor="middle" fill="#16304e" font-size="18">разбор и обнаружение</text>
<path d="M 330 211 L 426 211" stroke="#a7bad7" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M 330 223 C 380 285 420 300 480 316" fill="none" stroke="#a7bad7" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M 330 223 C 400 385 450 450 510 474" fill="none" stroke="#a7bad7" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="450" y="156" width="260" height="110" rx="20" fill="#5ed2bb"/>
<text x="580" y="202" text-anchor="middle" fill="#09362d" font-size="25" font-weight="700">CSS</text>
<text x="580" y="234" text-anchor="middle" fill="#154f43" font-size="18">stylesheet и CSSOM</text>
<rect x="450" y="292" width="260" height="110" rx="20" fill="#ffb45c"/>
<text x="580" y="338" text-anchor="middle" fill="#351d00" font-size="25" font-weight="700">JavaScript</text>
<text x="580" y="370" text-anchor="middle" fill="#523000" font-size="18">parse и main thread</text>
<rect x="450" y="448" width="260" height="110" rx="20" fill="#d79bf7"/>
<text x="580" y="494" text-anchor="middle" fill="#361442" font-size="25" font-weight="700">Hero</text>
<text x="580" y="526" text-anchor="middle" fill="#512466" font-size="18">request, decode, paint</text>
<path d="M 710 211 C 770 211 755 330 815 330" fill="none" stroke="#a7bad7" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M 710 347 L 815 347" stroke="#a7bad7" stroke-width="5" marker-end="url(#arrow)"/>
<path d="M 710 503 C 770 503 758 366 815 366" fill="none" stroke="#a7bad7" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="830" y="272" width="120" height="150" rx="24" fill="#f5f8ff"/>
<text x="890" y="321" text-anchor="middle" fill="#1b2840" font-size="19" font-weight="700">Готово</text>
<text x="890" y="350" text-anchor="middle" fill="#1b2840" font-size="19" font-weight="700">для</text>
<text x="890" y="379" text-anchor="middle" fill="#1b2840" font-size="19" font-weight="700">paint</text>
<path d="M 890 422 L 890 514" stroke="#a7bad7" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="745" y="545" width="210" height="100" rx="22" fill="#f5f8ff"/>
<text x="850" y="586" text-anchor="middle" fill="#1b2840" font-size="22" font-weight="700">Полезный</text>
<text x="850" y="617" text-anchor="middle" fill="#1b2840" font-size="22" font-weight="700">первый экран</text>
<text x="70" y="682" fill="#c1cee2" font-size="18">Проверяем разрыв: URL обнаружен поздно, CSS не готов или main thread занят.</text>
<text x="70" y="714" fill="#c1cee2" font-size="18">Отдельно: изображение прошло request, decode и paint?</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.3 KiB

@@ -0,0 +1,54 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 780" role="img" aria-labelledby="title desc">
<title id="title">Профиль первой загрузки с четырьмя владельцами времени</title>
<desc id="desc">Вертикальная схема показывает документ и сеть, JavaScript на главном потоке, CSS и hero-изображение как отдельные дорожки, которые сходятся в полезный первый экран.</desc>
<defs>
<linearGradient id="bg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#101a32"/>
<stop offset="1" stop-color="#172a45"/>
</linearGradient>
<filter id="shadow" x="-10%" y="-10%" width="120%" height="130%">
<feDropShadow dx="0" dy="8" stdDeviation="8" flood-color="#07101f" flood-opacity=".28"/>
</filter>
</defs>
<rect width="1000" height="780" fill="url(#bg)"/>
<text x="70" y="70" fill="#f6f8fc" font-family="Arial, sans-serif" font-size="34" font-weight="700">Первая загрузка — четыре независимые дорожки</text>
<text x="70" y="106" fill="#b8c8e3" font-family="Arial, sans-serif" font-size="20">Профиль отвечает «кому принадлежит задержка», а не складывает всё в одно число.</text>
<g font-family="Arial, sans-serif">
<g filter="url(#shadow)">
<rect x="70" y="152" width="860" height="100" rx="18" fill="#1e3558"/>
<rect x="96" y="178" width="154" height="48" rx="24" fill="#4e9af1"/>
<text x="173" y="209" text-anchor="middle" fill="#09192d" font-size="20" font-weight="700">Сеть</text>
<text x="282" y="193" fill="#f6f8fc" font-size="23" font-weight="700">HTML и критические запросы</text>
<text x="282" y="220" fill="#b8c8e3" font-size="18">redirect · connect · response · обнаружение URL</text>
<line x1="655" y1="202" x2="875" y2="202" stroke="#4e9af1" stroke-width="14" stroke-linecap="round"/>
</g>
<g filter="url(#shadow)">
<rect x="70" y="276" width="860" height="100" rx="18" fill="#27365b"/>
<rect x="96" y="302" width="154" height="48" rx="24" fill="#ffb45c"/>
<text x="173" y="333" text-anchor="middle" fill="#2a1700" font-size="20" font-weight="700">JS</text>
<text x="282" y="317" fill="#f6f8fc" font-size="23" font-weight="700">Главный поток</text>
<text x="282" y="344" fill="#c8d2e7" font-size="18">parse · execute · DOM · сторонний код</text>
<line x1="574" y1="326" x2="822" y2="326" stroke="#ffb45c" stroke-width="14" stroke-linecap="round"/>
</g>
<g filter="url(#shadow)">
<rect x="70" y="400" width="860" height="100" rx="18" fill="#1c4551"/>
<rect x="96" y="426" width="154" height="48" rx="24" fill="#5dd6ba"/>
<text x="173" y="457" text-anchor="middle" fill="#06342d" font-size="20" font-weight="700">CSS</text>
<text x="282" y="441" fill="#f6f8fc" font-size="23" font-weight="700">Стиль и layout</text>
<text x="282" y="468" fill="#c3e6df" font-size="18">stylesheet · CSSOM · style · layout</text>
<line x1="612" y1="450" x2="760" y2="450" stroke="#5dd6ba" stroke-width="14" stroke-linecap="round"/>
</g>
<g filter="url(#shadow)">
<rect x="70" y="524" width="860" height="100" rx="18" fill="#4b355d"/>
<rect x="96" y="550" width="154" height="48" rx="24" fill="#d59afa"/>
<text x="173" y="581" text-anchor="middle" fill="#321343" font-size="20" font-weight="700">Image</text>
<text x="282" y="565" fill="#f6f8fc" font-size="23" font-weight="700">Hero-изображение</text>
<text x="282" y="592" fill="#ead8f7" font-size="18">URL · transfer · decode · paint</text>
<line x1="600" y1="574" x2="846" y2="574" stroke="#d59afa" stroke-width="14" stroke-linecap="round"/>
</g>
<path d="M 500 640 L 500 681" stroke="#9bb0d3" stroke-width="5" stroke-linecap="round"/>
<path d="M 500 681 L 488 665 M 500 681 L 512 665" fill="none" stroke="#9bb0d3" stroke-width="5" stroke-linecap="round"/>
<rect x="185" y="695" width="630" height="60" rx="30" fill="#f4f7fc"/>
<text x="500" y="733" text-anchor="middle" fill="#16233a" font-size="21" font-weight="700">Полезный экран: проверяем одну границу</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

@@ -0,0 +1,49 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 1000 800" role="img" aria-labelledby="title desc">
<title id="title">Маршрут диагностики позднего полезного экрана</title>
<desc id="desc">Дерево решения ведёт от позднего полезного screenshot к четырём проверкам: позднее обнаружение ресурса, JavaScript на главном потоке, CSS и layout, а также загрузка и декодирование изображения.</desc>
<defs>
<linearGradient id="fieldbg" x1="0" y1="0" x2="1" y2="1">
<stop offset="0" stop-color="#152039"/>
<stop offset="1" stop-color="#263756"/>
</linearGradient>
<marker id="branchArrow" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="8" markerHeight="8" orient="auto">
<path d="M 0 0 L 10 5 L 0 10 z" fill="#b8c8e2"/>
</marker>
</defs>
<rect width="1000" height="800" fill="url(#fieldbg)"/>
<g font-family="Arial, sans-serif">
<text x="70" y="66" fill="#f8fbff" font-size="34" font-weight="700">Диагностика: поздний экран</text>
<text x="70" y="102" fill="#c6d3e7" font-size="20">Сначала наблюдаемый блок, затем владелец задержки, потом обратимая проверка.</text>
<rect x="280" y="145" width="440" height="92" rx="22" fill="#f5f8ff"/>
<text x="500" y="184" text-anchor="middle" fill="#17243b" font-size="24" font-weight="700">Полезный экран запоздал</text>
<text x="500" y="214" text-anchor="middle" fill="#394962" font-size="17">HTML мог уже прийти — это ещё не ответ о причине</text>
<path d="M 500 237 L 500 292" stroke="#b8c8e2" stroke-width="5" marker-end="url(#branchArrow)"/>
<rect x="322" y="305" width="356" height="74" rx="18" fill="#31476d"/>
<text x="500" y="336" text-anchor="middle" fill="#f8fbff" font-size="21" font-weight="700">Критический URL стартовал рано?</text>
<text x="500" y="361" text-anchor="middle" fill="#d5e0f0" font-size="17">сверяем HTML, waterfall и element</text>
<path d="M 350 379 C 255 415 210 434 185 478" fill="none" stroke="#b8c8e2" stroke-width="5" marker-end="url(#branchArrow)"/>
<path d="M 455 379 C 430 420 410 432 402 478" fill="none" stroke="#b8c8e2" stroke-width="5" marker-end="url(#branchArrow)"/>
<path d="M 545 379 C 570 420 590 432 598 478" fill="none" stroke="#b8c8e2" stroke-width="5" marker-end="url(#branchArrow)"/>
<path d="M 650 379 C 745 415 790 434 815 478" fill="none" stroke="#b8c8e2" stroke-width="5" marker-end="url(#branchArrow)"/>
<rect x="55" y="495" width="260" height="158" rx="20" fill="#4d94ea"/>
<text x="185" y="534" text-anchor="middle" fill="#10233c" font-size="22" font-weight="700">Позднее</text>
<text x="185" y="562" text-anchor="middle" fill="#10233c" font-size="22" font-weight="700">обнаружение</text>
<text x="185" y="594" text-anchor="middle" fill="#16304e" font-size="17">URL создаётся кодом</text>
<text x="185" y="620" text-anchor="middle" fill="#16304e" font-size="17">или скрыт в CSS</text>
<text x="185" y="642" text-anchor="middle" fill="#173454" font-size="15" font-weight="700">Показать URL раньше</text>
<rect x="345" y="495" width="260" height="158" rx="20" fill="#ffb45c"/>
<text x="475" y="534" text-anchor="middle" fill="#352000" font-size="22" font-weight="700">JavaScript</text>
<text x="475" y="562" text-anchor="middle" fill="#352000" font-size="22" font-weight="700">на main thread</text>
<text x="475" y="594" text-anchor="middle" fill="#4b2c00" font-size="17">scripting до render</text>
<text x="475" y="620" text-anchor="middle" fill="#4b2c00" font-size="17">или лишний DOM</text>
<text x="475" y="642" text-anchor="middle" fill="#4b2c00" font-size="15" font-weight="700">Отложить один модуль</text>
<rect x="635" y="495" width="260" height="158" rx="20" fill="#5ed1b8"/>
<text x="765" y="534" text-anchor="middle" fill="#07372e" font-size="22" font-weight="700">CSS и</text>
<text x="765" y="562" text-anchor="middle" fill="#07372e" font-size="22" font-weight="700">layout</text>
<text x="765" y="594" text-anchor="middle" fill="#164e44" font-size="17">поздний stylesheet</text>
<text x="765" y="620" text-anchor="middle" fill="#164e44" font-size="17">или повторный layout</text>
<text x="765" y="642" text-anchor="middle" fill="#164e44" font-size="15" font-weight="700">Исправить границу CSS</text>
<rect x="55" y="690" width="840" height="58" rx="29" fill="#d99af9"/>
<text x="475" y="726" text-anchor="middle" fill="#351442" font-size="21" font-weight="700">Изображение: отдельно проверить request, размер, decode и paint</text>
</g>
</svg>

After

Width:  |  Height:  |  Size: 4.9 KiB

@@ -0,0 +1,49 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1280" role="img" aria-labelledby="title desc">
<title id="title">Локальная fixture проверяет контракт до сетевого теста</title>
<desc id="desc">Вертикальная схема показывает три локальных объекта ответа: корректные 200 и 400 проходят контрактную проверку, а 200 без nextCursor отклоняется; отдельный сетевой шаг не выполнен fixture.</desc>
<rect width="720" height="1280" fill="#0f172a"/>
<rect x="42" y="34" width="636" height="112" rx="18" fill="#1e3a8a"/>
<text x="360" y="80" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">Fixture ловит нарушение до сети</text>
<text x="360" y="116" text-anchor="middle" fill="#bfdbfe" font-size="21" font-family="Arial, sans-serif">локальные объекты не заменяют сервер</text>
<rect x="85" y="190" width="550" height="108" rx="18" fill="#14532d" stroke="#86efac" stroke-width="3"/>
<text x="360" y="232" text-anchor="middle" fill="#ffffff" font-size="27" font-family="Arial, sans-serif" font-weight="700">Fixture A · 200 / JSON</text>
<text x="360" y="268" text-anchor="middle" fill="#dcfce7" font-size="22" font-family="Arial, sans-serif">nextCursor: null</text>
<path d="M360 298v34" stroke="#bfdbfe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="338" width="550" height="108" rx="18" fill="#7f1d1d" stroke="#fca5a5" stroke-width="3"/>
<text x="360" y="380" text-anchor="middle" fill="#ffffff" font-size="27" font-family="Arial, sans-serif" font-weight="700">Fixture B · 400 / problem+json</text>
<text x="360" y="416" text-anchor="middle" fill="#fee2e2" font-size="22" font-family="Arial, sans-serif">errors[0].code: invalid_cursor</text>
<path d="M360 446v34" stroke="#bfdbfe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="486" width="550" height="108" rx="18" fill="#7f1d1d" stroke="#fca5a5" stroke-width="3"/>
<text x="360" y="528" text-anchor="middle" fill="#ffffff" font-size="27" font-family="Arial, sans-serif" font-weight="700">Fixture C · 200 / JSON</text>
<text x="360" y="564" text-anchor="middle" fill="#fee2e2" font-size="22" font-family="Arial, sans-serif">нет обязательного nextCursor</text>
<path d="M360 594v44" stroke="#bfdbfe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="75" y="644" width="570" height="184" rx="18" fill="#1d4ed8" stroke="#93c5fd" stroke-width="3"/>
<text x="360" y="690" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">Контрактная проверка</text>
<text x="360" y="734" text-anchor="middle" fill="#dbeafe" font-size="23" font-family="Arial, sans-serif">1. HTTP status</text>
<text x="360" y="768" text-anchor="middle" fill="#dbeafe" font-size="23" font-family="Arial, sans-serif">2. Content-Type</text>
<text x="360" y="802" text-anchor="middle" fill="#dbeafe" font-size="23" font-family="Arial, sans-serif">3. schema body</text>
<path d="M360 828v42" stroke="#bfdbfe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="876" width="550" height="96" rx="18" fill="#14532d" stroke="#86efac" stroke-width="3"/>
<text x="360" y="918" text-anchor="middle" fill="#ffffff" font-size="27" font-family="Arial, sans-serif" font-weight="700">PASS · A и B</text>
<text x="360" y="950" text-anchor="middle" fill="#dcfce7" font-size="21" font-family="Arial, sans-serif">валидная страница и problem detail</text>
<path d="M360 972v34" stroke="#bfdbfe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="1012" width="550" height="96" rx="18" fill="#991b1b" stroke="#fca5a5" stroke-width="3"/>
<text x="360" y="1054" text-anchor="middle" fill="#ffffff" font-size="27" font-family="Arial, sans-serif" font-weight="700">REJECT · C</text>
<text x="360" y="1086" text-anchor="middle" fill="#fee2e2" font-size="21" font-family="Arial, sans-serif">200 не отменяет обязательную schema</text>
<rect x="70" y="1152" width="580" height="72" rx="16" fill="#334155" stroke="#facc15" stroke-width="3"/>
<text x="360" y="1184" text-anchor="middle" fill="#f8fafc" font-size="23" font-family="Arial, sans-serif" font-weight="700">Следующий шаг: разрешённый тестовый сервер</text>
<text x="360" y="1214" text-anchor="middle" fill="#cbd5e1" font-size="19" font-family="Arial, sans-serif">fixture его не выполняет</text>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0 0L10 5L0 10z" fill="#bfdbfe"/>
</marker>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.8 KiB

@@ -0,0 +1,44 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1160" role="img" aria-labelledby="title desc">
<title id="title">Контракт одной REST API-операции</title>
<desc id="desc">Вертикальная схема показывает запрос списка заказов, явную развилку ответов 200 и 400 и проверку клиентом статуса, Content-Type и схемы тела.</desc>
<rect width="720" height="1160" fill="#0f172a"/>
<rect x="42" y="34" width="636" height="112" rx="18" fill="#172554"/>
<text x="360" y="80" text-anchor="middle" fill="#ffffff" font-size="29" font-family="Arial, sans-serif" font-weight="700">Контракт одной операции</text>
<text x="360" y="116" text-anchor="middle" fill="#cbd5e1" font-size="22" font-family="Arial, sans-serif">URL — только начало договора</text>
<rect x="85" y="190" width="550" height="132" rx="18" fill="#0f766e" stroke="#5eead4" stroke-width="3"/>
<text x="360" y="234" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">GET /api/v1/orders</text>
<text x="360" y="270" text-anchor="middle" fill="#ccfbf1" font-size="23" font-family="Arial, sans-serif">limit=20; cursor — строка или отсутствует</text>
<path d="M360 322v48" stroke="#cbd5e1" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="175" y="376" width="370" height="58" rx="29" fill="#fef3c7"/>
<text x="360" y="414" text-anchor="middle" fill="#1e293b" font-size="22" font-family="Arial, sans-serif" font-weight="700">проверка входа</text>
<path d="M360 434v40" stroke="#cbd5e1" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="480" width="550" height="148" rx="18" fill="#14532d" stroke="#86efac" stroke-width="3"/>
<text x="360" y="526" text-anchor="middle" fill="#ffffff" font-size="29" font-family="Arial, sans-serif" font-weight="700">200 OK · application/json</text>
<text x="360" y="564" text-anchor="middle" fill="#dcfce7" font-size="23" font-family="Arial, sans-serif">items: Order[]</text>
<text x="360" y="598" text-anchor="middle" fill="#dcfce7" font-size="23" font-family="Arial, sans-serif">page.nextCursor: string | null</text>
<path d="M360 628v44" stroke="#cbd5e1" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="678" width="550" height="148" rx="18" fill="#7f1d1d" stroke="#fca5a5" stroke-width="3"/>
<text x="360" y="724" text-anchor="middle" fill="#ffffff" font-size="29" font-family="Arial, sans-serif" font-weight="700">400 Bad Request</text>
<text x="360" y="762" text-anchor="middle" fill="#fee2e2" font-size="23" font-family="Arial, sans-serif">application/problem+json</text>
<text x="360" y="796" text-anchor="middle" fill="#fee2e2" font-size="23" font-family="Arial, sans-serif">type, status, detail, errors[].code</text>
<path d="M360 826v44" stroke="#cbd5e1" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="70" y="876" width="580" height="170" rx="18" fill="#1e293b" stroke="#64748b" stroke-width="3"/>
<text x="360" y="924" text-anchor="middle" fill="#ffffff" font-size="27" font-family="Arial, sans-serif" font-weight="700">Клиент проверяет три вещи</text>
<text x="360" y="962" text-anchor="middle" fill="#cbd5e1" font-size="23" font-family="Arial, sans-serif">1. HTTP status</text>
<text x="360" y="994" text-anchor="middle" fill="#cbd5e1" font-size="23" font-family="Arial, sans-serif">2. Content-Type</text>
<text x="360" y="1026" text-anchor="middle" fill="#cbd5e1" font-size="23" font-family="Arial, sans-serif">3. schema тела</text>
<rect x="70" y="1080" width="580" height="46" rx="14" fill="#334155"/>
<text x="360" y="1111" text-anchor="middle" fill="#e2e8f0" font-size="21" font-family="Arial, sans-serif">JSON сам по себе не равен успеху</text>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0 0L10 5L0 10z" fill="#cbd5e1"/>
</marker>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.1 KiB

@@ -0,0 +1,46 @@
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 720 1180" role="img" aria-labelledby="title desc">
<title id="title">Как OpenAPI связывает операцию с ответом и схемой</title>
<desc id="desc">Вертикальная схема показывает Operation Object, карту ответов 200 и 400, а затем различие между required полем nextCursor и nullable значением.</desc>
<rect width="720" height="1180" fill="#172554"/>
<rect x="42" y="34" width="636" height="112" rx="18" fill="#312e81"/>
<text x="360" y="80" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">Операция становится матрицей</text>
<text x="360" y="116" text-anchor="middle" fill="#ddd6fe" font-size="21" font-family="Arial, sans-serif">вход → HTTP-код → media type → schema</text>
<rect x="85" y="190" width="550" height="140" rx="18" fill="#3730a3" stroke="#a5b4fc" stroke-width="3"/>
<text x="360" y="236" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">Operation Object</text>
<text x="360" y="274" text-anchor="middle" fill="#e0e7ff" font-size="23" font-family="Arial, sans-serif">GET /orders</text>
<text x="360" y="306" text-anchor="middle" fill="#e0e7ff" font-size="22" font-family="Arial, sans-serif">query: limit, cursor</text>
<path d="M360 330v48" stroke="#c7d2fe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="140" y="384" width="440" height="128" rx="18" fill="#0f766e" stroke="#5eead4" stroke-width="3"/>
<text x="360" y="430" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">Responses Object</text>
<text x="360" y="468" text-anchor="middle" fill="#ccfbf1" font-size="23" font-family="Arial, sans-serif">"200" · "400" · "500"</text>
<text x="360" y="496" text-anchor="middle" fill="#ccfbf1" font-size="20" font-family="Arial, sans-serif">код выбирает форму тела</text>
<path d="M360 512v48" stroke="#c7d2fe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="566" width="550" height="116" rx="18" fill="#14532d" stroke="#86efac" stroke-width="3"/>
<text x="360" y="610" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">200 + JSON → OrdersPage</text>
<text x="360" y="648" text-anchor="middle" fill="#dcfce7" font-size="22" font-family="Arial, sans-serif">items и page</text>
<path d="M360 682v36" stroke="#c7d2fe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="85" y="724" width="550" height="116" rx="18" fill="#7f1d1d" stroke="#fca5a5" stroke-width="3"/>
<text x="360" y="768" text-anchor="middle" fill="#ffffff" font-size="28" font-family="Arial, sans-serif" font-weight="700">400 + problem → Problem</text>
<text x="360" y="806" text-anchor="middle" fill="#fee2e2" font-size="22" font-family="Arial, sans-serif">type, status, errors</text>
<path d="M360 840v42" stroke="#c7d2fe" stroke-width="5" marker-end="url(#arrow)"/>
<rect x="55" y="888" width="610" height="214" rx="18" fill="#1e293b" stroke="#64748b" stroke-width="3"/>
<text x="360" y="934" text-anchor="middle" fill="#ffffff" font-size="27" font-family="Arial, sans-serif" font-weight="700">Schema Object: два разных вопроса</text>
<rect x="86" y="966" width="250" height="92" rx="14" fill="#334155"/>
<text x="211" y="1002" text-anchor="middle" fill="#f8fafc" font-size="23" font-family="Arial, sans-serif" font-weight="700">required</text>
<text x="211" y="1033" text-anchor="middle" fill="#cbd5e1" font-size="20" font-family="Arial, sans-serif">ключ nextCursor есть</text>
<rect x="384" y="966" width="250" height="92" rx="14" fill="#334155"/>
<text x="509" y="1002" text-anchor="middle" fill="#f8fafc" font-size="23" font-family="Arial, sans-serif" font-weight="700">nullable</text>
<text x="509" y="1033" text-anchor="middle" fill="#cbd5e1" font-size="20" font-family="Arial, sans-serif">значение может быть null</text>
<text x="360" y="1088" text-anchor="middle" fill="#cbd5e1" font-size="20" font-family="Arial, sans-serif">отсутствующий ключ и null — не один случай</text>
<defs>
<marker id="arrow" viewBox="0 0 10 10" refX="8" refY="5" markerWidth="8" markerHeight="8" orient="auto-start-reverse">
<path d="M0 0L10 5L0 10z" fill="#c7d2fe"/>
</marker>
</defs>
</svg>

After

Width:  |  Height:  |  Size: 4.5 KiB