Wyślij zapytanie Dołącz do Sii

Mimo że historia komponentów w architekturze frontendowej sięga lat 90-tych, dopiero po roku 2010, wraz z rozwojem JavaScriptowych bibliotek i frameworków, stały się one standardem. Skoro jednak Angular, React, czy Vue.js dostarczają nam kompleksowe rozwiązania oparte na komponentach, to czy jest powód, by wspierać się alternatywnym podejściem, jakim są komponenty webowe?

Zdecydowanie tak – przede wszystkim dlatego, że korzystając z frameworka, jesteśmy związani jego rozwiązaniami. Web Components są natomiast elementami natywnymi, co zapewnia bezcenną elastyczność. Argumentów jest jednak więcej, a przybliżę je w artykule.

Czym są komponenty webowe?

Najprościej mówiąc, komponenty webowe to zestaw standardów i technologii umożliwiających tworzenie elementów interfejsu użytkownika, które są autonomiczne, odizolowane, gotowe do komponowania i wielokrotnego używania. Składają się przede wszystkim z:

  1. Custom Elements – technologii, dzięki której możemy tworzyć elementy HTML działające tak samo, jak te znane nam ze standardu HTML (<p>, <div>, etc.).
  2. HTML Templates – pozwalających na tworzenie szablonów HTML gotowych do użytku w wielu miejscach.
  3. Shadow DOM – dzięki któremu stworzymy alternatywne, odizolowane drzewo DOM dla różnych elementów, a jego skrypty i style będą niezależne od tych użytych na zewnątrz.
  4. HTML Imports – przestarzałe, ale skutecznie zastąpione, m.in.: przez ES Modules, rozwiązanie umożliwiające wpinanie elementów do innych plików HTML.

Technologie te razem pozwalają osiągnąć podobne zyski, jak znane nam frameworki i biblioteki JS, z tą różnicą, że stawiając na komponenty webowe, jesteśmy bardziej niezależni. Między innymi dlatego, mimo popularności Angulara czy Reacta, nie odeszły do lamusa, a przeciwnie – po tym jak zostały formalnie uznane przez W3C, nieustannie zyskują na popularności.

Początki

Mniej więcej we wspomnianym 2010 roku zaczęto podnosić problemy, jakie wynikają z dotychczas stosowanych standardów tworzenia interfejsu użytkownika. Komponenty webowe jako jeszcze niesformalizowana technologia polegająca na stosowaniu samowystarczalnych, reużywalnych elementów, zaczęły być stosowane już w roku 2011.

W rozwijanie tej koncepcji od początku zaangażowana była nie tylko społeczność developerów i rozmaite organizacje, ale i duże firmy jak Google, Apple czy Microsoft. W 2014 roku W3C zaczęło wieloletnią pracę nad ustandaryzowaniem Web Components, a rozwiązania, które obejmuje, zaczęły być stopniowo obsługiwane przez przeglądarki. W3C publikowało różne materiały na ten temat w roku 2018 i 2019, ale ostateczny standard pojawił się w styczniu roku 2021.

Dlaczego warto?

Powodów, dla których coraz więcej aplikacji korzysta z rozwiązań dostarczanych przez Web Components, jest sporo, choć jak pisałem – większość tych zalet znamy z innych JS-owych bibliotek i frameworków:

  1. Możliwość wielokrotnego zastosowania – komponenty są wyizolowane, samowystarczalne (o ile nie potrzebują danych do zaprezentowania) i łatwe w implementacji. Znacząco ogranicza to potrzebę duplikowania kodu,.
  2. Łatwość utrzymania – tak skonstruowane komponenty mają nieduży wpływ na całość aplikacji, co ułatwia aktualizowanie i utrzymywanie.
  3. Niezależne style i funkcjonalności – dzięki Shadow DOM minimalizujemy ryzyko konfliktów.
  4. Łatwość testowania – podział na takie komponenty umożliwia oddzielne testowanie.
  5. Przejrzystość kodu – aplikacja oparta na tych rozwiązaniach jest bardziej czytelna i łatwiejsza w zrozumieniu dla developera.
  6. Bardziej efektywna praca w zespołach – wielokrotne używanie tych samych komponentów ułatwia współpracę pomiędzy korzystającymi z nich zespołami.
  7. Standaryzacja – osiągnięta standaryzacja sprawia, że koncepcja jest spójna i przewidywalna,
  8. Łatwa integracja – zdecydowanie najważniejsza zaleta w kontekście popularności frameworków to możliwość wykorzystywania komponentów webowych niezależnie od innych używanych w aplikacji rozwiązań.

Technologie

Custom Elements

W roku 2011 spod rąk Alexa Russella (Google) i Eduardo Lundgrena (Liferay) wyszła koncepcja „webkitCustomElement” zastosowana w projekcie WebKi, czyli silniku używanym m.in.: przez Safari. Ten prototyp stał się zalążkiem Custom Elements v0, które w 2013 roku zostały częścią specyfikacji „HTML Living Standard”, by ostatecznie ewoluować w roku 2016 w Custom Elements v1, ustandaryzowane w W3C. Od tamtej pory kolejne przeglądarki implementowały to rozwiązanie, a same Custom Elements stały się podstawą i najważniejszym elementem komponentów webowych.

Pozwalają one kreować niemal dowolne elementy HTML, które nie są częścią tego standardu. Ich tworzenie odbywa się w trzech prostych krokach.

Na początku definiujemy komponent przy użyciu metody:

kod

Podajemy też nazwę elementu oraz klasę. Następnie dodajemy funkcjonalności, definiując metody w klasie. Na koniec przy użyciu konstruktora tworzymy instancję komponentu.

To, co wymaga krótkiego omówienia, to znany nam z frameworków JS cykl życia nowo utworzonego elementu. Wykonywanie akcji na różnych etapach ułatwia kontrolę nad komponentami. Mamy do dyspozycji m.in.:

  • connectedCallback, gdy nasz element trafia do drzewa DOM,
  • disconnectedCallback, gdy zostaje z niego usunięty,
  • attributeChangedCallback, gdy jego atrybut zostanie zmieniony,
  • adoptedCallback, gdy element zostanie przeniesiony.
Custom Element – schemat lifecycle
Ryc. 1 Custom Element – schemat lifecycle

Przykładowe użycie Custom Element:

kod

HTML:

kod

Shadow DOM

Technologia Shadow DOM, która także w 2011 roku została przedstawiona przez Google, umożliwia tworzenie izolowanych drzew DOM dla różnych elementów – takie drzewa nie są dostępne poza komponentem. Dzięki temu unikamy konfliktów skryptów oraz stylów i uzyskujemy czystszy kod. Izolacja komponentów może być zrealizowana na jednym z trzech poziomów:

  1. Open Shadow DOM – mamy tu ograniczony poziom hermetyzacji, wybierając go, możemy sprawić, że część elementów będzie dostępna na zewnątrz. By tak się stało, atrybut `mode` musi być ustawiony na `open` w metodzie `attachShadow()`, gdy Shadow DOM jest tworzony. Większość stylów i skryptów pozostaje jednak w dalszym ciągu izolowana.
  2. Closed Shadow DOM – na tym poziomie dostęp możliwy jest tylko przez API Shadow DOM.
  3. Scoped Shadow DOM – elementy są całkowicie niedostępne na zewnątrz. Ten poziom osiągamy, stosując odpowiednie selektory CSS, jak :host i ::slotted, by zdefiniować, jakie style będą stosowane w ramach Shadow DOM i co ma zostać przeniesione na zewnątrz komponentu.
Schemat Shadow DOM
Ryc. 2. Schemat Shadow DOM

A jak wygląda implementacja Shadow DOM? Poniżej prosty przykład, w którym elementy `h1` oraz `p` nie są widoczne na stronie, za to pozostają dostępne przez JS:

kod

HTML Templates

Technologię HTML Templates zapoczątkował element `<template>`, który w 2009 roku pojawił się w specyfikacji HTML5. W kolejnych latach rozważano jego użycie przy tworzeniu komponentów interfejsu użytkownika, by w 2013 roku stał się oficjalnie częścią ekosystemu komponentów webowych.

Mówiąc najprościej, jest to mechanizm pozwalający zdefiniować części kodu HTML, które nie będą renderowane podczas ładowania, mogą być jednak przechowywane jako szablony i co najważniejsze – używane do dynamicznego generowania treści w czasie wykonania.

HTML Templates mają kilka zalet, a najważniejsze z nich to:

  • oddzielenie logiki od prezentacji, co wpływa na organizację kodu,
  • możliwość wielokrotnego użycia,
  • wsparcie bezpieczeństwa – pomagają uniknąć ataków typu XSS (Cross-Site Scripting), zapobiegając wstrzykiwaniu niebezpiecznego kodu do danych.

HTML Templates są równie proste w implementacji, co inne rozwiązania z zakresu Web Components:

kod

JS:

kod

HTML Imports oraz ES Modules

Pomysł wykorzystania elementu `<link>`, by importować dokumenty HTML zawierające m.in.: kod komponentów, pojawił się w 2011 roku. Rok później powstała specyfikacja dla HTML Imports, zakładająca wykorzystanie atrybutu `rel` elementu `<link>`. Korzystanie w przeglądarkach z elementu `<link rel=”import”>` zaczęło być możliwe w roku 2014, jednak już dwa lata później rozwiązanie to zaczęło być wypierane przez ES Modules, oferujące metodę bardziej elastyczną i zgodną z ECMAScript 6.

Nie mniej, zarówno HTML Imports jak i ES Modules to mechanizmy umożliwiające importowanie oraz organizowanie zewnętrznych skryptów i modułów w aplikacji. Różnią się głównie:

  • Składnia – odpowiednio `<link rel=”import” href=”ścieżka.html”>` dla HTML Imports i `import, np.: import { funkcja } from 'ścieżka’;` dla ES Modules. Warto tu wspomnieć, że pierwsze z tych rozwiązań skutkuje importem wszystkich zależności, podczas gdy moduły ES Modules zawierają tylko to, co zostało zaimportowane bezpośrednio.
  • Zakres – HTML Imports umożliwia jedynie import globalny, narażamy się więc na wystąpienie konfliktów nazw. ES Modules mają własne zakresy.
  • Wsparcie – HTML Imports nie są wspierane przez nowsze przeglądarki, analogicznie ES Modules mają problem ze wsparciem tych starszych. Rozwiązaniem w obu przypadkach mogą być polyfille (np. Babel).
Ryc. 3 HTML Imports i ES Modules
Ryc. 3 HTML Imports i ES Modules

Które wybrać?

Kiedy sięgnąć po HTML Imports, a kiedy po ES Modules?

  • HTML Imports – będą pomocne przy pracy ze starszymi przeglądarkami lub wtedy, gdy chcemy świadomie zaimportować pełny pakiet zależności.
  • ES Modules – gdy pracujemy w nowszym projekcie i korzystamy z ES co najmniej w wersji 6 oraz potrzebujemy większej izolacji. Na ES Modules warto postawić również wtedy, gdy przydadzą nam się dostarczane przez nie rozwiązania jak eksport domyślny, który pozwala na eksportowanie jednej wartości lub obiektu jako domyślnego eksportu z modułu (to oznacza, że można zdefiniować jedno główne wyjście modułu, które jest używane jako wartość domyślna, gdy inny moduł importuje ten moduł bez podawania konkretnej nazwy eksportowanej wartości).

Standardem jest już jednak korzystanie z ES Modules i ewentualne wykorzystanie narzędzi umożliwiających wsparcie starszych przeglądarek.

Wbudowane i zewnętrzne komponenty webowe

W standardzie HTML mamy już sporo przydatnych wbudowanych Web Components. Są to m.in.: `<select>` czy `<input>` umożliwiające użytkownikowi wprowadzenie wartości, `<video>` i `<audio>`, dzięki którym możemy osadzić pliki dźwiękowe oraz wideo, czy wreszcie `<canvas>`, który pozwala tworzyć grafiki lub animacje.

Nieco ciekawsze są komponenty, które znajdziemy w zewnętrznych bibliotekach. Warto tu sięgnąć po takie zbiory jak Google’owskie LitElement oraz Polymer lub Stencil czy Ionic. Większość z nich łatwo zaimplementować przy pomocy NPM lub linków CDN.

Komunikacja

Komunikacja między komponentami webowymi może się odbywać na kilka sposobów. Najważniejsze z nich omówiłem poniżej.

Eventy

To kluczowy mechanizm służący do komunikacji między komponentami. Dzięki niemu możemy przekazać informacje o zdarzeniach i zmianach, co stanowi podstawę interakcji wewnątrz aplikacji.

Komponent, chcąc wysłać event, powinien stworzyć instancję obiektu Event albo potomka klasy CustomEvent. Następnie należy użyć metody dispatchEvent() na danym elemencie HTML – będzie on emitentem eventu:

kod

Do nasłuchiwania służy z kolei metoda `addEventListener()`. Po emisji nasłuchujący komponent przechwytuje event i wykonuje akcję:

kod

Propagowanie eventów

W związku z tym, że eventy nie są w stanie wyjść poza Shadow DOM, korzystając z niego, musimy użyć jego własnego mechanizmu propagacji. W tym celu wykorzystamy opcję `composed` ustawioną na `true`:

kod

Z kolei nasłuchiwanie skonstruujemy tak:

kod

Przekazywanie danych pomiędzy komponentami

Samo przekazywanie danych możemy zrealizować przez:

  • Wykorzystanie atrybutów – emiter przekazuje dane w atrybucie elementu HTML, z kolei element nasłuchujący wykorzystuje metodę `getAttribute()` lub któreś z rozwiązań dostępnych w zewnętrznych bibliotekach.
  • CustomEvent – taki obiekt w atrybucie `detail` może zawierać złożone dane dostępne dla komponentu nasłuchującego.
  • Wspólne zmienne – wystarczy, by zmienna przechowująca dane miała zakres, który będzie dostępny dla całego DOM lub zakres globalny.
  • Biblioteki do zarządzania stanem – jeśli nasza aplikacja jest bardziej złożona, warto sięgnąć po rozwiązania dostarczane przez Redux, Mobx lub Vuex.

Bezpieczeństwo

Decydując się na korzystanie z komponentów webowych, musimy być świadomi różnych zagrożeń, m.in.: ataków typu Cross-Site Request Forgery, Cross-Site Scripting czy też związanych z zarządzaniem danymi, bibliotekami lub aktualizacjami.

Przed dużą częścią z nich zabezpieczymy się, pilnując przestrzegania kilku zasad:

  1. Pilnowanie uprawnień – komponent powinien wpływać wyłącznie na przypisany do niego element DOM, nie ingerując w inne elementy oraz w ich zawartość.
  2. Ostrożna wymiana danych – korzystanie z atrybutów czy Custom Events to bezpieczne formy wymiany danych i tylko tego typu form powinniśmy się trzymać.
  3. Aktualizacje i testy bezpieczeństwa – jedno i drugie powinno być przeprowadzane regularnie.
  4. Walidacja – atakom typu XSS oraz wyciekom zapobiegniemy, filtrując i walidując dane wykorzystywane do generowania treści.
  5. Unikanie niebezpiecznych mechanizmów – np. funkcja `eval()` pozwala wykonać kod jako string; takie rozwiązania mogą zostać użyte przeciwko nam.
  6. Shadow DOM – do jego licznych zalet należy m.in.: izolacja stylów i logiki, co zapobiega nie tylko konfliktom, ale i manipulacjom.

Podsumowanie

Integracja z frameworkami, bibliotekami i narzędziami developerskimi, postępująca standaryzacja oraz nowe specyfikacje dowodzą, że popularność Web Components stale rośnie. Trudno się dziwić – dzięki nim zyskujemy możliwość wielokrotnego używania tych samych elementów, izolację, poprawę bezpieczeństwa, czy niezależność od frameworków.

Nie jest już praktycznie możliwe tworzenie warstwy frontendowej aplikacji z pominięciem standardów tej technologii, dlatego nawet jeśli nie używamy jej w projekcie bezpośrednio, warto być na bieżąco z tym, co słychać w świecie komponentów webowych.

***

Jeśli interesuje Cię tematyka „Komponenty niestandardowe w Power Apps” oraz „React. Stylowanie komponentów za pomocą styled-components„, zajrzyj koniecznie do artykułów naszych ekspertów.

5/5 ( głosy: 9)
Ocena:
5/5 ( głosy: 9)
Autor
Avatar
Rafał Bedlewicz

Front-end Developer w Sii Polska. Aktualnie związany z Angularem. Wolny czas lubi spędzać aktywnie – entuzjasta podróży i każdej formy sportu

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *

Może Cię również zainteresować

Pokaż więcej artykułów

Bądź na bieżąco

Zasubskrybuj naszego bloga i otrzymuj informacje o najnowszych wpisach.

Otrzymaj ofertę

Jeśli chcesz dowiedzieć się więcej na temat oferty Sii, skontaktuj się z nami.

Wyślij zapytanie Wyślij zapytanie

Natalia Competency Center Director

Get an offer

Dołącz do Sii

Znajdź idealną pracę – zapoznaj się z naszą ofertą rekrutacyjną i aplikuj.

Aplikuj Aplikuj

Paweł Process Owner

Join Sii

ZATWIERDŹ

This content is available only in one language version.
You will be redirected to home page.

Are you sure you want to leave this page?