Układ to na nim przeglądarka określa informacje geometryczne o elementach – ich rozmiarze i położeniu na stronie. Każdy element będzie zawierać wyraźne lub niejawne informacje o rozmiarze ustalone na podstawie użytego kodu CSS, zawartości elementu lub elementu nadrzędnego. Ten proces nazywa się w Chrome Układ.
Układ to na nim przeglądarka określa informacje geometryczne o elementach: ich rozmiar i lokalizację na stronie. Każdy element będzie zawierać wyraźne lub niejawne informacje o rozmiarze ustalone na podstawie użytego kodu CSS, zawartości elementu lub elementu nadrzędnego. Ten proces nazywa się Układ w Chrome (i w przeglądarkach pochodnych, takich jak Edge) i Safari. W Firefoksie nazywa się to Reflow, ale sposób działania jest w praktyce taki sam.
Podobnie jak w przypadku obliczeń stylu, bezpośrednie kwestie związane z kosztami układu są następujące:
- Liczba elementów, które wymagają układu, który jest iloczynem ubocznym rozmiaru DOM strony.
- Złożoność tych układów.
Podsumowanie
- Układ ma bezpośredni wpływ na czas oczekiwania na interakcję.
- Układ jest zwykle ograniczony do całego dokumentu.
- Liczba elementów DOM wpływa na skuteczność. Gdy tylko jest to możliwe, unikaj aktywowania układu.
- Unikaj wymuszonego stosowania układów synchronicznych i niszczycielskich układów. Odczytuj wartości stylów, a następnie wprowadzaj zmiany w stylach.
Wpływ układu na czas oczekiwania na interakcję
Gdy użytkownik wchodzi w interakcję ze stroną, powinny one trwać jak najszybciej. Czas potrzebny na ukończenie interakcji, który kończy się, gdy przeglądarka wyświetli następną klatkę w celu pokazania wyników interakcji, jest nazywany opóźnieniem interakcji. Jest to aspekt wydajności strony mierzony przez dane Od interakcji do kolejnego wyrenderowania.
Czas potrzebny przeglądarce na wyświetlenie następnej klatki w odpowiedzi na interakcję z użytkownikiem jest nazywany opóźnieniem prezentacji interakcji. Celem interakcji jest przekazanie informacji wizualnych, aby zasygnalizować użytkownikowi, że coś się stało, a aktualizacje wizualne mogą wymagać trochę pracy związanej z układem strony, by osiągnąć ten cel.
Aby utrzymać jak najniższy wskaźnik INP witryny, w miarę możliwości unikaj układu. Jeśli nie można całkowicie uniknąć układu, należy ograniczyć ten układ, by przeglądarka mogła szybko zaprezentować następną klatkę.
W miarę możliwości unikaj układu
Gdy zmienisz style, przeglądarka sprawdzi, czy któreś z tych zmian wymagają obliczenia układu i zaktualizowanie tego drzewa renderowania. Zmiany we „właściwościach geometrycznych”, takich jak szerokość, wysokość, Lewo i Góra wymagają układu.
.box {
width: 20px;
height: 20px;
}
/**
* Changing width and height
* triggers layout.
*/
.box--expanded {
width: 200px;
height: 350px;
}
Układ jest niemal zawsze ograniczony do całego dokumentu. Jeśli masz dużo elementów, określenie ich lokalizacji i wymiarów zajmie dużo czasu.
Jeśli nie można uniknąć układu, trzeba jeszcze raz użyć Narzędzi deweloperskich w Chrome, aby sprawdzić, jak długo to zajmuje i ustalić, czy przyczyną wąskiego gardła jest układ. Najpierw otwórz Narzędzia deweloperskie, przejdź na kartę Oś czasu, kliknij „Rejestruj” i wejdź w interakcję ze swoją witryną. Po zatrzymaniu rejestracji zobaczysz zestawienie skuteczności witryny:
Zbadaj ślady w tym przykładzie, że dla każdej klatki w układzie dla każdej klatki jest zajęte ponad 28 milisekund, co oznacza, że jeśli mamy 16 milisekund na ułożenie klatki na ekranie w animacji, jest to znacznie za dużo. Widać też,że z Narzędzi deweloperskich dowiesz się, jaki jest rozmiar drzewa (w tym przypadku 1618 elementów) oraz ile węzłów wymaga układu (w tym przypadku 5).
Pamiętaj, aby unikać układu, gdy tylko jest to możliwe, ale nie zawsze można go uniknąć. W sytuacjach, gdy nie można uniknąć układu, pamiętaj, że koszt układu jest powiązany z rozmiarem DOM. Choć zależność między tymi dwoma elementami nie jest ściśle sprzężona, większe DOM zwykle wiążą się z wyższymi kosztami układu.
Unikaj wymuszonych układów synchronicznych
Dostawa ramki na ekran składa się z takiej kolejności:
Najpierw uruchamia się JavaScript, potem oblicza styl i układ. Można jednak wymusić wcześniejsze wykonanie układu w przeglądarce. Jest to tzw. wymuszony układ synchroniczny.
Przede wszystkim pamiętaj, że gdy JavaScript uruchamia wszystkie wartości układu z poprzedniej ramki, są one znane i możesz wykonywać zapytania. Jeśli więc chcesz zapisać wysokość elementu (nazwijmy ją „box”) na początku ramki, możesz napisać taki kod:
// Schedule our function to run at the start of the frame:
requestAnimationFrame(logBoxHeight);
function logBoxHeight () {
// Gets the height of the box in pixels and logs it out:
console.log(box.offsetHeight);
}
Problemy pojawiają się, jeśli zmienisz style pola przed poproszeniem o jego wysokość:
function logBoxHeight () {
box.classList.add('super-big');
// Gets the height of the box in pixels and logs it out:
console.log(box.offsetHeight);
}
Aby odpowiedzieć na pytanie dotyczące wysokości, przeglądarka musi najpierw zastosować zmianę stylu (dzięki dodaniu klasy super-big
), a następnie uruchomić układ. Dopiero wtedy będzie można zwrócić prawidłową wysokość. To niepotrzebne i potencjalnie kosztowne rozwiązanie.
Z tego względu należy zawsze zgrupować odczyty stylu i wykonać je najpierw (gdzie przeglądarka może użyć wartości układu poprzedniej ramki), a potem wykonać wszelkie zapisy:
Jeśli powyższa funkcja została wykonana poprawnie, wyglądałaby tak:
function logBoxHeight () {
// Gets the height of the box in pixels and logs it out:
console.log(box.offsetHeight);
box.classList.add('super-big');
}
Na ogół nie musisz stosować stylów, a później wysyłać zapytań o wartości. Wystarczy, że użyjesz wartości ostatniej klatki. Synchroniczne i wcześniejsze wykonywanie obliczeń związanych ze stylem oraz układem mogą utrudniać pracę przeglądarki.
Unikanie thrashingu układu
Można też jeszcze bardziej pogorszyć występowanie wymuszonych układów synchronicznych: wykonuj wiele z nich w krótkich odstępach czasu. Spójrz na ten kod:
function resizeAllParagraphsToMatchBlockWidth () {
// Puts the browser into a read-write-read-write cycle.
for (let i = 0; i < paragraphs.length; i++) {
paragraphs[i].style.width = `${box.offsetWidth}px`;
}
}
Kod zapętla grupę akapitów i ustawia szerokość każdego akapitu na szerokość elementu o nazwie „box”. Wydaje się to całkiem niegroźne, ale każda iteracja pętli odczytuje wartość stylu (box.offsetWidth
), a następnie natychmiast używa jej do zaktualizowania szerokości akapitu (paragraphs[i].style.width
). Przy następnej iteracji pętli przeglądarka musi uwzględnić fakt, że style zmieniły się od czasu ostatniego żądania parametru offsetWidth
(w poprzedniej), więc musi zastosować zmiany stylu i uruchomić układ. Będzie to miało miejsce podczas każdej iteracji.
Poprawka w tym przykładzie polega na ponownym odczytaniu wartości read, a następnie write:
// Read.
const width = box.offsetWidth;
function resizeAllParagraphsToMatchBlockWidth () {
for (let i = 0; i < paragraphs.length; i++) {
// Now write.
paragraphs[i].style.width = `${width}px`;
}
}
Jeśli chcesz zagwarantować bezpieczeństwo, rozważ użycie modelu FastDOM, który automatycznie grupuje odczyty i zapisy za Ciebie i zapobiega przypadkowemu wywołaniu wymuszonych układów synchronicznych i atakowania układu.
Baner powitalny z filmu Unsplash autorstwa Hal Gatewood.