
W każdym projekcie istnieją pewne elementy wspólne, wykorzystywane podczas stylowania komponentów. Do elementów tych mogą należeć zmienne definiujące kolory czy wymiary, mixiny i funkcje sass, ale także definicje klas.
Nieumiejętne ułożenie i ich użycie może narazić nas, na znaczny wzrost wielkości builda. Ja też raz wpadłem w tę pułapkę i dziwiłem się, dlaczego w buildzie produkcyjnym, każdy, nawet najmniejszy komponent waży kilkanaście kb!?
Problem
Aby zapewnić dostępność stylów, mixin i zmiennych w komponentach, wszystkie te elementy były zabrane w jeden plik tempalte.scss
, który to zaimportowany bezpośrednio do komponentu, gwarantował ich dostępność.
Wyglądał on mniej więcej tak:
I wszystkie te style, importowane były w każdym z komponentów mniej więcej w taki sposób:
I wszystko fajnie działało, jednak jak się okazało, build produkcyjny zaczął strasznie szybko puchnąć. Uruchomiłem więc Webpack Bundle Analyzer i co ja widzę? Każdy z komponentów posiadał plik scss ważący kilkanaście kb i stawał się tym większy, im więcej elementów wrzucimy do template.scss
.
Zacząłem szukać rozwiązań w stylu W jaki sposób usunąć nieużywane style z komponentu?, ale problem leży w innym miejscu, a mianowicie w niewłaściwej organizacji importów. Dlaczego?
Rozwiązanie
Gdy komponent dostanie style zaimportowane w ten sposób, każdą otrzymaną klasę css enkapsuluje i tym samym powiela, prefixując odpowiednio wygenerowanym id. To sprawiało, że im więcej nowych klas pojawiało się w składowych pliku _template.scss
, tym większy stawał się nasz komponent. Bo każda taka klasa dostawała id enkapsulacji i była pakowana co css komponentu! Nawet jak nie była używana.
Szkoda, że nie ma mechanizmu przypominającego treeshaking dla stylów (przynajmniej nie znam), który byłby w stanie pozbyć się nieużywanych klas. Ale to nie problem!
Przy większej analizie okazuje się, że style komponentu potrzebują wyłącznie zmiennych, fukcji czy mixinów, a podczas kompilacji, w wygenerowanym pliku css zmienne zostają zastąpione odpowiednimi wartościami.
I żadne klasy z vendorów w tym pliku nie są potrzebne! I to był mój największy błąd! Idąc na łatwiznę, chciałem wszystko dostarczyć w jednym imporcie.
Podzieliłem zatem style na 2 główne części, tools i theme:
Zgodnie ze sztuką klasy są zaimportowane wyłącznie 1 raz w aplikacji (w pliku styles.scss), a wszystkie niezbędne do generowania cssów tools
są do dyspozycji na poziomie pliku scss komponentu. Niby proste i oczywiste, jednak czasami dla wygody, można zapomnieć o konsekwencjach nieodpowiednich importów. A taki elementarny błąd sprawił, że każdy z komponentów rozrósł się do ogromnych rozmiarów.