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.