Przejdź do treści
Wróć do akt
Akta 02Odtajnione (częściowo)

Ratunek wydajności: Vue 2 → 3

Vue 2 → Vue 3, przepisane od zera — i wolne, zanim w ogóle trafiło na produkcję.

Klient
Firma cateringowa, Niemcy
Rola
Senior frontend engineer, de facto tech lead
Czas trwania
[utajnione]
Stack
Vue 3 · TypeScript · TanStack Query · SignalR · Biome · Feature-based architecture

W skrócie

  • 0

    pozostałych kaskad requestów

  • 1

    typowane źródło prawdy dla zapytań

  • RT

    celowana inwalidacja w czasie rzeczywistym

  • 100%

    PR-ów formatowanych przez maszyny, recenzowanych przez ludzi

Ratowanie wydajności dużej aplikacji przepisywanej na Vue 3

Kontekst

Zespół przepisywał dużą aplikację z Vue 2 na Vue 3. Nowa wersja korzystała z architektury feature-based, TanStack Query do pobierania danych oraz SignalR do aktualizacji w czasie rzeczywistym. Stack był nowoczesny, ale aplikacja już przed wdrożeniem wykazywała poważne problemy z wydajnością.

Problem

  1. Niewydajny kod. W części aplikacji występowała zbędna złożoność, zagnieżdżone pętle oraz wywołania watchEffect, które przez swoje zależności uruchamiały się ponownie.
  2. TanStack Query używany jako szyna zdarzeń. Stan aplikacji był powiązany przez queries i mutations uruchamiane z miejsc, które nie powinny musieć o sobie wiedzieć.
  3. Kaskady requestów. Reaktywne zapytania uruchamiane wewnątrz watchEffect powodowały, że jedno wywołanie uruchamiało kolejne, tworząc łańcuch zależnych od siebie requestów zamiast jawnego przepływu danych.
  4. Szum w code review. Formatowanie nie było konsekwentnie egzekwowane, więc pull requesty zawierały zmiany utrudniające skupienie się na logice i architekturze.

Co zrobiłem

  1. Przeniosłem formatowanie i lintowanie do narzędzi. Wprowadziłem Biome oraz git hooki, dzięki czemu formatowanie i podstawowe zasady spójności były sprawdzane automatycznie, zanim kod trafił do review.
  2. Rozdzieliłem odpowiedzialności. Uporządkowałem granice pomiędzy modułami i widokami oraz usunąłem niepotrzebne zależności pomiędzy store'ami.
  3. Scentralizowałem dostęp do danych. Klienci API, queries, mutations i query keys trafiły do jednej typowanej warstwy danych. Dzięki temu aplikacja ma jedno miejsce definiujące sposób pobierania i identyfikowania danych.
  4. Zbudowałem celowaną inwalidację. Wprowadziłem mechanizm sterowany zdarzeniami SignalR, dzięki któremu każda wiadomość unieważnia tylko te zapytania, których rzeczywiście dotyczy.
  5. Usunąłem łańcuchowe requesty. Wyeliminowałem kaskady tworzone przez reaktywne zapytania, a przy okazji wprowadziłem dziesiątki mniejszych poprawek dotyczących wydajności i architektury.

Efekt

  • 0 pozostałych kaskad requestów w analizowanych przepływach
  • 1 typowana warstwa danych dla klientów API, queries, mutations i query keys
  • Celowana inwalidacja danych w czasie rzeczywistym sterowana zdarzeniami SignalR
  • Automatyczne formatowanie i lintowanie przed code review

Efektem był znacznie bardziej przejrzysty przepływ danych, brak pozostałych kaskad requestów w analizowanych miejscach oraz środowisko developerskie, które automatycznie wychwytuje problemy z formatowaniem i podstawową spójnością kodu.

Dlaczego migracja miała tutaj znaczenie

Aplikacja była już przepisywana na Vue 3, ale nowszy framework nie sprawił automatycznie, że stała się lepsza. Rewrite przeniósł część starych nawyków architektonicznych do nowego kodu.

Rozwiązanie tych problemów w trakcie migracji pozwoliło zespołowi zakończyć przejście na Vue 3 z czytelniejszą warstwą danych, mniejszą liczbą ukrytych zależności i mniejszym ryzykiem ponownego wprowadzenia tych samych klas problemów z wydajnością.

Stack

Vue 3, TypeScript, TanStack Query, SignalR, Biome, architektura feature-based.

Tego rodzaju pracę oferuję w ramach audytu wydajności frontendu oraz migracji Vue 2 do Vue 3.

Masz wolną aplikację?

Widziałem gorsze. Porozmawiajmy.

Porozmawiajmy