Zgodność z platformami

Zgodność w ekosystemie platform JavaScript

wstępnym wpisie na blogu opisaliśmy, jak wiele się nauczyliśmy, tworząc i korzystając z ramek oraz narzędzi do tworzenia i utrzymywania dużych aplikacji internetowych, takich jak wyszukiwarka Google, Mapy Google, Zdjęcia itp. 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 zmianie wyników dotyczących 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 to ewolucja. Zespoły polegały na niewielkiej grupie doświadczonych deweloperów, którzy przeprowadzili dogłębną weryfikację kodu, zgłaszając problemy wpływające na jakość i możliwość utrzymania aplikacji, a nie tylko związane z poprawnością. Aby umożliwić korzystanie z nich rosnącym zespołom deweloperów aplikacji, opracowaliśmy system zgodności, który pozwala stosować sprawdzone metody w zautomatyzowany i egzekwowalny sposób. Dzięki temu zapewniliśmy wysoki poziom jakości aplikacji i łatwość utrzymania kodu źródłowego niezależnie od liczby osób, które współtworzyły kod.

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 skalowania – 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 tworzenia. 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 domyślne ustawienia. 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 wzorów. Framework 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 istotnego kodu CSS i ustawianie priorytetu 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 zaakceptowania przez dewelopera. Możesz na przykład użyć komponentu obrazu udostępnionego przez framework do skalowania obrazów.
  • Wymagaj 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 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 gdy deweloperzy będą wprowadzać zmiany.

3. Czas tworzenia

Ważne jest, aby wykrywać i zapobiegać problemom z wydajnością na wczesnym etapie cyklu życia aplikacji. Czas autoryzacji, czyli czas przed zatwierdzeniem kodu, jest idealny do wykrywania 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 środowisku produkcyjnym. Chcemy, aby ta funkcja była dostępna podczas tworzenia.

Zgodność z platformami

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

  1. Co oznacza wczytywanie z optymalną szybkością i jakie są najczęstsze problemy, które mogą negatywnie wpływać na szybkość wczytywania?
  2. Które rozwiązania można wbudować, nie wymagając od dewelopera żadnych dodatkowych działań?
  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 ich 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ę z Wami 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ż to rozwiązanie sprawdza się w przypadku nowych projektów, nie jest łatwo uaktualnić duże bazy kodu, aby były zgodne ze wszystkimi regułami. W Google mamy rozbudowany system rezygnacji na różnych poziomach, np. w poszczególnych wierszach kodu źródłowego, całych katalogach, starszych bazach kodu lub częściach 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.0 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 ramówką 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 font, 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 powiadomienia 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 frameworki (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

Sprawdzone metody są kodyfikowane w regułach, które są przydatne dla programistó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 ważne.

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 pakietu technologicznego. Zgodność z wymaganiami zwiększa produktywność zespołów i gwarantuje wysoką jakość aplikacji, nawet gdy zespoły i bazy kodu się rozrastają.