Tworzenie aplikacji internetowych po stronie frontendu (tego przeglądarkowego) jest coraz bardziej złożone. Od dłuższego czasu coraz więcej projektów korzysta z TypeScript jako bazowej składni JS, co wiąże się też z tym że wymaga to skonfigurowania odpowiedniego środowiska developerskiego.
W swoim projekcie bazującym na TypeScript i styled components spotkałem się z pewnym problemem związanym z brakiem możliwości korzystania z nowych własności CSS. O tym w dalszej części tekstu.
Czym są styled components?
Na początek wyjaśnię czym są styled components. Jest to rozwiązanie bardzo popularne w środowisku programistów React, polegające na tym, aby style CSS były ściśle powiązane z komponentami React. Tylko tyle i aż tyle. Dzięki temu zarządzanie kodem staje się znacznie uproszczone w dłuższym okresie czasu.
Pisanie kodu styled components przypomina miks modułów CSS i SASSa.
Jaki problem rozwiązuje styled components?
Korzystanie ze styled components rozwiązuje szereg problemów z którymi spotykają się na co dzień programiści frontend piszący kod w tradycyjny sposób (czytaj osobno JS i osobno CSS).
Główne problemy które zostały rozwiązane w ten sposób to:
- W znaczący sposób ograniczono scope (czyt. zakres działania) kodu CSS. Kod CSS jest przypisany bezpośrednio do komponentu i jego elementów składowych:
// Item.theme.tsx
export const Item = styled.li`
display: grid;
grid-template-areas:
'title title actions'
'image content content'
'meta ad .';
}
Który może być wykorzystany w następujący sposób:
// List.tsx
import * as React from 'react';
import { Item } from './Item.theme';
export const List = (): JSX.Element => {
return (
);
}
Co ciekawe, jeśli w innym komponencie będzie styled component o nazwie Item
to jego style zostaną przetłumaczone na klasę CSS z innym, unikalnym hashem. Dzięki temu, możemy mieć wiele różnych elementów Item
wykorzystanych w wielu różnych, niepowiązanych komponentach i nie musimy się martwić o to, że style będą kolidowały.
- Do wykonania obliczeń wartości własności CSS możemy wykorzystywać kod JS bezpośrednio wewnątrz styli komponentu:
interface Props {
isImportant: boolean;
}
export const Item = styled.div`
font-size: ${({ isImportant }): string => isImportant ? '32px' : '16px' };
`;
- Ułatwiono długoterminowe zarządzanie stylami komponentu. Jeśli jakiś styled component nie jest używany w kodzie docelowego komponentu, to po prostu usuwamy jego kod bez obawy, że jego usunięcie zepsuje jakiś niepowiązany ficzer. To co ważne, należy unikać pisania kodu w stylu:
export const Item = styled.div`
width: 100%;
div {
padding: 16px;
p {
font-size: 14px;
}
}
`;
W takiej sytuacji nieważne jest to, że styled component o nazwie Item
już nie jest używany. Może się okazać, że zagnieżdżone komponenty korzystały z jego stylów, czyli zadziałała klasyczna kaskadowość stylów CSS.
Do wad na pewno należy zaliczyć potencjalne obniżenie wydajności takiej aplikacji, jeśli w kodzie styled components mamy dużo obliczeń matematycznych przy każdej zmianie propsów przekazywanych do takiego komponentu. Potencjalnym rozwiązaniem tego problemu może być wykorzystanie zmiennych CSS natywnie działających w przeglądarce, ale to już temat na inny artykuł.
ts-styled-plugin - unknown property
To tyle tytułem wstępu do problemu: w moim przypadku kiedy pisałem kod styled components i chciałem wykorzystać najnowsze własności CSS, to spotkałem się z problemem: Unknown property: 'content-visibility' - ts-styled-plugin(9999)
i zastanowiło mnie jak to rozwiązać?
Przez tą informację o błędzie nie mogłem kompilować kodu TypeScript. Okazało się, że rozwiązanie jest zaskakująco proste.
Jak korzystać z nowych własności CSS w kodzie TypeScript?
Aby rozwiązać ten problem, wystarczyło zmodyfikować plik konfiguracyjny TypeScript w następujący sposób:
//tsconfig.json
{
"compilerOptions": {
"plugins": [
{
"name": "typescript-styled-plugin",
"lint": {
"validProperties": ["content-visibility", "contain-intrinsic-size"]
}
}
]
}
}
Dodałem informację o tym, aby TypeScript świadomie akceptował nieznane sobie nazwy własności CSS. Tym samym, jesteśmy w stanie rozwiązać problem z akceptowaniem przez TypeScript nieznanych własności CSS.
Podsumowanie
W tym wpisie wyjaśniłem pokrótce czym są styled components oraz przedstawiłem rozwiązanie problemu jakim może być używanie nieznanych TypeScriptowi własności CSS w kodzie tychże komponentów.
Jeśli interesuje ciebie czym są własności: content-visibility
oraz contain-intrisic-size
to warto zapoznać się tekstem na stronie Google Developers, gdzie zostało to ładnie wyjaśnione. W skrócie, chodzi o optymalizację renderowania elementów na stronie w momencie, gdy nie pojawiają się w widocznej części okna przeglądarki po załadowaniu strony. To potencjalnie może znacząco poprawić performance score w narzędziu Page Speed Insights od Google.