Zgodność z platformami

Zgodność w ekosystemie platform JavaScript

Shubhie Panicker
Shubhie Panicker

wstępnym wpisie na blogu opisaliśmy, jak wiele nauczyliśmy się podczas tworzenia i używania frameworków oraz narzędzi do tworzenia i utrzymywania dużych aplikacji internetowych, takich jak wyszukiwarka Google, Mapy Google czy Zdjęcia. Chroniąc deweloperów przed pisaniem kodu, który może negatywnie wpływać na wrażenia użytkownika, udowodniliśmy, że frameworki mogą odgrywać kluczową rolę w zwiększaniu wydajności i jakości aplikacji.

W Google używamy wewnętrznie terminu „zgodność” na określenie tej metodologii. W tym artykule opisujemy, jak planujemy udostępnić tę koncepcję w ekosystemie frameworków JavaScript.

Co to jest zgodność?

W Google Conformance było ewolucją. Zespoły polegały na niewielkiej grupie bardzo doświadczonych deweloperów, którzy przeprowadzili dogłębną weryfikację kodu, zgłaszając problemy wpływające na jakość i łatwość utrzymania aplikacji, a nie tylko związane z poprawnością. Aby umożliwić to rosnącym zespołom deweloperów aplikacji, opracowaliśmy system zgodności, który pozwala skodyfikować sprawdzone metody w sposób zautomatyzowany i egzekwowalny. Dzięki temu udało się utrzymać wysoki poziom jakości aplikacji i łatwości utrzymania kodu źródłowego niezależnie od liczby osób pracujących nad kodem.

Zgodność to system, który zapewnia programistom pozostawanie na właściwej ścieżce. Buduje on zaufanie i gwarantuje przewidywalne wyniki. Dzięki temu zespoły są bardziej produktywne, a to kluczowe zagadnienie w przypadku rozwijania się – gdy zespoły się powiększają i jednocześnie rozwijają więcej funkcji. Umożliwia ona deweloperom skupienie się na tworzeniu funkcji produktu, co uwalnia ich od konieczności zajmowania się szczegółami i zmieniającymi się warunkami w różnych obszarach, takich jak wydajność, dostępność, bezpieczeństwo itp. Każdy może w dowolnym momencie zrezygnować z zgody z zasadami. Powinna ona być dostosowywalna w takim zakresie, aby zespoły miały możliwość egzekwowania tego, co zdecydują się zaakceptować.

Zgodność opiera się na mocnych domyślnych wartościach i zapewnia reguły, które można wdrożyć w momencie pisania kodu. Składa się ona z tych 3 zasad:

1. Silne ustawienia domyślne

Podstawowym aspektem zgodności jest zapewnienie, aby narzędzia używane przez deweloperów miały silne ustawienia domyślne. Oznacza to, że rozwiązania są nie tylko wbudowane w ramy, ale także wzorce projektowania ram ułatwiają podejmowanie właściwych decyzji i utrudniają stosowanie nieprawidłowych wzorców. Platforma ta pomaga programistom w projektowaniu aplikacji i strukturze kodu.

Aby zapewnić wydajność wczytywania, należy zoptymalizować wszystkie zasoby (czcionki, CSS, JavaScript, obrazy itp.). Jest to złożone zadanie, które wymaga skracania bajtów, zmniejszania liczby połączeń i oddzielania tego, co jest potrzebne do pierwszego renderowania, gotowości wizualnej i interakcji z użytkownikiem. Na przykład wyodrębnianie kluczowych elementów CSS i ustawianie priorytetów dla ważnych obrazów.

2. Reguły z możliwością działania

Nawet po wprowadzeniu podstawowych optymalizacji deweloperzy muszą podejmować decyzje. Istnieje wiele możliwości optymalizacji, które wymagają zaangażowania programistów:

  • domyślne wartości, które nie wymagają udziału dewelopera, np. wstawianie kodu CSS krytycznego;
  • Wymagaj włączenia przez dewelopera. Możesz na przykład użyć komponentu obrazu udostępnionego przez framework do kadrowania i przeskalowywania obrazów.
  • Wymagać akceptacji i dostosowywania przez dewelopera. Możesz na przykład oznaczyć ważne obrazy, aby były wczytywane wcześniej.
  • Nie chodzi o konkretną funkcję, ale o rzeczy, które nadal wymagają decyzji dewelopera. Na przykład unikanie czcionek lub skryptów synchronicznych, które opóźniają wczesne renderowanie.

Diagram przedstawiający spektrum automatycznych i ręcznych optymalizacji

Optymalizacje, które wymagają podjęcia decyzji przez deweloperów, stanowią zagrożenie dla wydajności aplikacji. Wraz z dodawaniem nowych funkcji i rozwojem zespołu nawet najbardziej doświadczeni deweloperzy nie nadążają za ciągle zmieniającymi się sprawdzonymi metodami. Nie jest to też najlepszy sposób na wykorzystanie ich czasu. W przypadku zgodności odpowiednie reguły są tak samo ważne jak silne domyślne ustawienia, ponieważ zapewniają, że aplikacja będzie nadal spełniać określone standardy, nawet jeśli deweloperzy wprowadzą zmiany.

3. Czas tworzenia

Ważne jest, aby wykrywać i zapobiegać problemom z wydajnością na wczesnym etapie cyklu życia aplikacji. Czas pisania kodu, czyli czas przed jego zatwierdzeniem, jest idealny do wychwytywania i rozwiązywania problemów. Im później problem zostanie wykryty w cyklu życia aplikacji, tym trudniejsze i droższe będzie jego rozwiązanie. Dotyczy to problemów z poprawnością, ale także problemów z wydajnością, ponieważ wiele z nich nie zostanie rozwiązanych wstecznie po wprowadzeniu zmian w kodzie źródłowym.

Obecnie większość informacji o skuteczności jest przekazywana poza systemem przez dokumentację, jednorazowe kontrole lub pojawia się zbyt późno w ramach regresji danych po wdrożeniu w produkcji. Chcemy wprowadzić to w czasie tworzenia.

Zgodność w ramach

Aby zapewnić użytkownikom wysoką jakość wczytywania, należy odpowiedzieć na te pytania:

  1. Co oznacza optymalne wczytywanie i jakie są typowe problemy, które mogą mieć na to niekorzystny wpływ?
  2. Które rozwiązania mogą być wbudowane i nie wymagają udziału dewelopera?
  3. Jak możemy mieć pewność, że deweloper korzysta z tych rozwiązań i optymalnie je wykorzystuje?
  4. Jakie inne decyzje może podjąć deweloper, aby wpłynąć na szybkość wczytywania?
  5. Jakie wzorce kodu mogą nam powiedzieć o tych wyborach (3 i 4 powyżej) na wczesnym etapie tworzenia?
  6. Jakie reguły możemy sformułować, aby ocenić te wzorce kodu? Jak można wyświetlać je deweloperom podczas tworzenia, zapewniając przy tym płynną integrację z ich przepływem pracy?

Aby zastosować model zgodności, który stosujemy wewnętrznie w Google, w ramach frameworków open source, nasz zespół przeprowadził wiele eksperymentów z użyciem Next.js. Z przyjemnością dzielimy się naszą ulepszoną wizją i planami. Zdaliśmy sobie sprawę, że najlepszy zestaw reguł, które mogą oceniać wzorce kodu, musi być kombinacją statycznej analizy kodusprawdzeń dynamicznych. Te reguły mogą obejmować wiele usług, w tym:

  • ESLint
  • TypeScript
  • dynamiczne sprawdzanie na serwerze deweloperskim użytkownika (po utworzeniu DOM-u);
  • Moduł bundler (webpack)
  • narzędzia do obsługi usługi porównywania cen (w fazie wstępnej),

Dzięki korzystaniu z reguł w różnych narzędziach możemy zapewnić ich spójność, a także uwzględnić wszystkie problemy związane z wygodą użytkowników, które mają bezpośredni wpływ na wydajność wczytywania. Dodatkowo te reguły mogą być wyświetlane deweloperom w różnych momentach:

  • Podczas lokalnego tworzenia na serwerze programistycznym przeglądarka i IDE użytkownika wyświetlają ostrzeżenia, aby poinformować programistów o konieczności wprowadzenia drobnych zmian w kodzie.
  • W momencie kompilacji nierozwiązane problemy będą ponownie wyświetlane w terminalu użytkownika.

Krótko mówiąc, zespoły będą wybierać interesujące je wyniki, takie jak podstawowe wskaźniki internetowe czy wydajność wczytywania, i włączać odpowiednie zestawy reguł, którymi powinni się kierować wszyscy współtwórcy kodu.

Chociaż jest to bardzo przydatne w przypadku nowych projektów, uaktualnianie dużych baz kodu, aby były zgodne z pełnymi zestawami reguł, nie jest łatwe. W Google mamy rozbudowany system rezygnacji na różnych poziomach, np. w przypadku poszczególnych linii kodu źródłowego, całych katalogów, starszych baz kodu lub części aplikacji, które nie są aktywnie rozwijane. Aktywnie szukamy skutecznych strategii udostępniania tych informacji zespołom korzystającym z ramek open source.

Zgodność w Next.js

ESLint jest powszechnie używany przez programistów JavaScriptu, a ponad 50% aplikacji Next.js korzysta z ESLint w niektórych częściach procesu kompilacji. W wersji 11. Next.js wprowadzono wbudowane wsparcie dla ESLint, które obejmuje własny wtyczekkonfigurację możliwą do udostępnienia, aby ułatwić wykrywanie typowych problemów związanych z ramami podczas tworzenia i kompilowania. Może to pomóc deweloperom w rozwiązywaniu poważnych problemów w momencie tworzenia. Przykłady obejmują przypadki, gdy dany komponent jest używany lub nie jest używany w sposób, który może mieć negatywny wpływ na skuteczność, np. Brak linku HTML do strony. Może to być też spowodowane tym, że określony krój pisma, arkusz stylów lub skrypt może negatywnie wpływać na wczytywanie zasobów na stronie. Na przykład Brak skryptu synchronicznego.

Oprócz ESLint w wersji 9 i nowszych z obsługą TypeScripta w Next.js obsługiwane jest zintegrowane sprawdzanie typów zarówno w procesie tworzenia, jak i w produkcji. Wiele komponentów udostępnianych przez framework (obraz, skrypt, link) zostało utworzonych jako rozszerzenie elementów HTML (<img>, <script>, <a>), aby zapewnić deweloperom wydajne podejście do dodawania treści do strony internetowej. Sprawdzanie typu umożliwia odpowiednie korzystanie z tych funkcji, ponieważ zapewnia, że przypisane właściwości i opcje mieszczą się w zakresie obsługiwanych wartości i typów. Przykład: wymagany rozmiar obrazu.

Wyświetlanie błędów za pomocą powiadomień i nakładek

Jak już wspomnieliśmy, reguły zgodności mogą być wyświetlane w różnych obszarach. Obecnie testujemy toasty i nakładki jako sposób na wyświetlanie błędów bezpośrednio w przeglądarce w lokalnym środowisku programistycznym użytkownika.

błędy wyświetlane w powiadomieniach typu toast;

Wiele narzędzi do sprawdzania błędów i audytów, z których korzystają deweloperzy (Lighthouse, karta Problemy w Narzędziach deweloperskich w Chrome), działa pasywnie i wymaga pewnej formy interakcji użytkownika, aby pobrać informacje. Programiści chętniej podejmują działania, gdy błędy są wyświetlane bezpośrednio w ich obecnych narzędziach i gdy podają konkretne działania, które należy podjąć, aby rozwiązać problem.

Zgodność z innymi platformami

Zgodność jest najpierw testowana w Next.js, a potem ma zostać rozszerzona na inne platformy (np. Nuxt czy Angular). ESLint i TypeScript są już używane w wielu ramach w wiele różnych sposobów, ale aktywnie badamy koncepcję spójnego systemu czasu wykonywania na poziomie przeglądarki.

Podsumowanie

Zgodność ze sprawdzonymi metodami sprowadza się do skodyfikowania sprawdzonych metod w regułach, które są przydatne dla deweloperów jako proste wzorce kodu. Zespół Aurora skupił się na wydajności wczytywania, ale inne sprawdzone metody, takie jak dostępność i bezpieczeństwo, są równie przydatne.

Przestrzeganie zasad zgodności powinno skutkować przewidywalnymi wynikami, a osiągnięcie wysokiego poziomu wrażeń użytkowników może być efektem ubocznym tworzenia architektury technologicznej. Zgodność z wymaganiami zwiększa produktywność zespołów i gwarantuje wysoką jakość aplikacji, nawet gdy zespoły i bazy kodu się rozrastają.