Месяц назад я написал статью о том, как сделал отладчик рендеров для Vue — инструмент, который называет точную причину каждой перерисовки. Рассказывал про renderTriggered, про ловушки с process.env.NODE_ENV, кириллицей в байтовых смещениях и вычислением чужих computed.
С тех пор вышла версия 0.8 — с тремя большими фичами, которые я не планировал делать так быстро. Расскажу, что нового и зачем.
Что было
Если не читали первую статью — вкратце. vue-why-render подключается к Vue 3 приложению двумя строками:
import { scan } from 'vue-why-render'scan(app, { panel: true })
И показывает на каждом перерисованном компоненте: имя, счётчик рендеров, длительность и причину. Не target: Proxy, а prop badge: {text} → {text} — new reference, same value. Для Pinia — store cart.items: Array(1) → Array(0) · action clear(). Для роутера — route.params.id: "1" → "2".
Плюс панель с пятью вкладками, бюджеты рендеров, тесты (expectRenders(Card).toBe(0)), отчёты в JSON/Markdown. Ноль зависимостей, MIT.
Что нового в 0.8
1. Граф реактивности (Deps)
Раньше vue-why-render отвечал на вопрос «почему этот компонент перерисовался?». Теперь он отвечает на вопрос «кто от чего зависит?».
Новая вкладка Deps строит живую карту зависимостей: компонент ↔ реактивный источник. Здесь я как раз подключил renderTracked — в первой статье я объяснял, почему не стал его использовать (слишком много вызовов, замедляет приложение). Решение: собирать данные лениво, только для открытой вкладки Deps, и дедуплицировать на лету.
Два режима:
-
Components → какие ref, prop, store и computed читает этот компонент?
-
Sources → какие компоненты зависят от этого ref?
На каждом ребре — счётчик чтений и триггеров. Если UserAvatar читает user.name 47 раз, но это вызвало 2 рендера — остальные чтения безвредны. Если CartBadge дёргается от cart.items на каждый keystroke — вот проблема.
Это рентген для реактивности Vue.
2. Rust/WASM ядро
В первой статье всё работало на чистом JS. Для небольших приложений — нормально. Но когда компонентов сотни или тысячи, три операции начинают заметно тормозить:
-
Построение дерева компонентов
-
Дедупликация причин рендера
-
Сравнение (дифф) двух отчётов
Я переписал их на Rust и скомпилировал в WebAssembly.
Как это устроено:
WASM-модуль подгружается лениво, отдельным чанком. Бандл приложения не растёт — пока vue-why-render не нужен, ничего лишнего не грузится. Если WASM недоступен (SSR, jsdom, строгий CSP) — автоматически включается JS-фолбэк. Конфигурировать ничего не нужно.
scan(app, { panel: true })// Внутри:// 1. Пробуем загрузить .wasm чанк// 2. Если ok — используем Rust-реализацию// 3. Если нет — переключаемся на JS// Потребитель не замечает разницы
Для обычного приложения разница в скорости незаметна. Для крупного — заметна.
3. VS Code расширение
Браузерные DevTools — это хорошо, но переключаться между Chrome и VS Code надоело. Поэтому я сделал WebSocket-мост: сканер в браузере стримит данные прямо в редактор.
Что появляется в VS Code:
-
Дерево компонентов в сайдбаре — отсортировано по рендерам, иконки 🔥 для горячих компонентов
-
Дерево зависимостей — тот же граф реактивности
-
CodeLens на
.vueфайлах — количество рендеров и средняя длительность прямо над<script setup> -
Статус-бар — живой счётчик рендеров
-
Команды — pause, resume, reset из палитры
Не нужно переключаться между браузером и редактором. Данные там, где пишется код.
Что ещё добавилось
Vue DevTools интеграция — помимо собственной панели, vue-why-render теперь регистрируется в Vue DevTools. Второй инспектор с деревом реактивных источников (цветные теги: ref, prop, store, computed) и второй слой на таймлайне, логирующий каждый триггер как событие.
Nuxt модуль — одна строка в конфиге:
export default defineNuxtConfig({ modules: ['vue-why-render/nuxt']})
Модуль уже в каталоге nuxt.com/modules.
Итого
За месяц пакет набрал 668 загрузок на npm, попал в каталог модулей Nuxt, и получил три фичи, которые я честно не планировал делать в ближайшие полгода.
-
npm i vue-why-render -
Для Nuxt:
modules: ['vue-why-render/nuxt'] -
Ноль зависимостей. MIT. Vue 3.3+.
Если нашли баг или хотите фичу — issues открыты.
Хабы: JavaScript, Vue.js, Rust, WebAssembly, Разработка веб-сайтов Сложность: Средняя
ссылка на оригинал статьи https://habr.com/ru/articles/1098942/