Tydzień bez nowego frameworku to tydzień stracony. Na szczęście ten tydzień uratował framework Mitosis, który stanowi ciekawą alternatywę dla Web Components. Ponadto w zeszłym tygodniu doczekaliśmy się aż 3 ważnych wydań Node.js i Redux’a, który w pełni wykorzystuje możliwości React 18. Łapcie kubek z ciepłą kawą w dłoń i zapraszamy do lektury!
1. Mitosis, ciekawa alternatywa dla WebComponents
Kiedy koncepcja Web Components została po raz pierwszy zaprezentowana, zdawało się, żę będzie ona prawdziwą rewolucją dla Frontend Developerów. Dzięki wyposażeniu przeglądarek w kilka nowych API (Custom Elements + Shadow Dom + HTML Template), możliwe miało stać się tworzenie własnych, zenkapsulowanych znaczników HTML. Tworzone w ten sposób komponenty miały być lżejsze, wydajniejsze i umożliwiać łatwe współdzielenie między projektami. Framweorki takie jak Angular czy React stopniowo miały stać się odpowiedzialne tylko za zarządzanie stanem. Niektórzy posuwali się jeszcze o krok dalej i twierdzili, że będą one kompletnie zbędne.
Jeśli wierzyć statystykom z Can I Use, pierwsze przeglądarki wspierały Web Components już pod koniec 2016 roku, natomiast od końca 2018 roku są one wspierane przez wszystkich znaczących graczy. Oznacza to, że od prawie 3,5 roku Web Components cieszą się uniwersalnym wsparciem. Mimo tego Web Components nadal są raczej rzadkością niż standardem. Co poszło nie tak? Powodów jest całkiem sporo. Zaproponowane przez przeglądarki API było lekko mówiąc toporne. Z czasem pojawiły się frameworki, takie jak Stencil czy Lit, które oferowały bardziej przystępne API. Obu frameworkom udało się zdobyć mocną pozycję na rynku, ale nigdy nie zagościły one wśród frontendowej czołówki. Do tego dochodzą jeszcze problemy z Server Side Renderingiem (bo do wyrenderowania Custom Elements niezbędne jest załadowanie kodu JavaScript z serwera) i integracją z istniejącymi frameworkami (React do dzisiaj nie posiada przystępnego API dla WebComponents) i naszkicowana kilka lat temu bajka zmienia się w szara rzeczywistość.
Kojarzycie firmę Builder.io? Jeśli nie to najwyższy czas zacząć śledzić ich poczynania. Firma zajmuje się rozwojem narzędzia Low Code/No Code do tworzenia własnych aplikacji, ale z punktu widzenia programistów, to nie samo narzędzie jest najciekawsze. Firma wspiera rozwój projektów Open Source takich jak Partytown (biblioteka umożliwiająca załadowanie i inicjalizację zewnętrznych skryptów przez WebWorkery) czy Qwik (HTML-first framework, który do inicjalizacji wymaga mniej niż 1kB JavaScriptu). Do grona ciekawych rozwijanych narzędzi dołącza teraz również framework Mitosis (aktualnie w fazie beta).
Najnowsze dziecko Builder.io stara się wyciągnąc lekcję z historii Web Components i rozwiązać problem współdzielenia komponentów pomiędzy projektami w bardziej optymalny sposób. Framework wykorzystuje podzbiór JSX, który kompilowany jest do pliku JSON. Następnie na podstawie wygenerowanego pliku odpowiednie pluginy generują kod w wybranej technologii. Taka architektura pozwala utrzymywać tylko jeden codebase, który kompilujemy do wykorzystywanych w firmie frameworków. Z punktu widzenia zewnętrznych zespołów, komponenty wyglądają jak paczki przygotowane z myślą o ich frameworku – żadnych wrapperów czy innych hacków. Na ten moment Mitosis jest otwartej becie i kompiluje się aż do 14 technologii. Co interesujące, oprócz webowych frameworków znajdziemy tu również technologie mobilne jak React Native czy Swift. Oznacza to, że Mitosis w odróżnieniu do Web Components, może służyć również do współdzielenia kodu między platformami.
// ============================
// Mitosis component definition
// ============================
import { useState } from "@builder.io/mitosis";
export default function MyComponent(props) {
const [name, setName] = useState("Tomek");
return (
<div>
<input
css={{
color: "red",
}}
value={name}
onChange={(event) => setName(event.target.value)}
/>
Hello! I can run in React, Vue, Solid, or Liquid!
</div>
);
}
// ============================
// Mitosis Angular output component
// ============================
import { Component } from "@angular/core";
@Component({
selector: "my-component",
template: `
<div>
<input
class="input"
[value]="name"
(input)="name = $event.target.value"
/>
Hello! I can run in React, Vue, Solid, or Liquid!
</div>
`,
styles: [
`
.input {
color: red;
}
`,
],
})
export default class MyComponent {
name = "Tomek";
}
// ============================
// Mitosis React output component
// ============================
import { useState } from "react";
export default function MyComponent(props) {
const [name, setName] = useState(() => "Tomek");
return (
<>
<div>
<input
className="input"
value={name}
onChange={(event) => setName(event.target.value)}
/>
Hello! I can run in React, Vue, Solid, or Liquid!
</div>
<style jsx>{`
.input {
color: red;
}
`}</style>
</>
);
}
Zachęcony hasłami marketingowymi postanowiłem sam odrobinę poeksperymentować z Mitosis (framework oferuje bardzo przystępny playground, który możecie znaleźć tutaj). Niestety w trakcie swoich eksperymentów bardzo szybko poczułem rozczarowanie. Po pierwsze wszystkie funkcje zdefiniowane w komponencie tracone są w momencie kompilacji do JSON’a. Co gorsza, kompilator w żaden sposób nie informuje nas, że wygenerowany kod nie będzie działał. Kolejnym rozczarowaniem jest brak kompilacji plików CSS. W teorii możliwe jest więc współdzielenie komponentów między React Native i React. Jak się jednak okazuje z jednym zastrzeżeniem: nasz plik CSS musi być akceptowany zarówno przez przeglądarki jak i React Native. W tej kwestii również nie uświadczymy błędów czy ostrzeżeń ze strony kompilatora. Jeszcze gorzej jest, jeśli spojrzymy na wsparcie dla SwiftUI – tutaj style są całkowicie ignorowane, a wynikowy kod to niezły frankenstein. Jeśli przed wydaniem pełnej wersji twórcy nie dopracują Mitosis, to dla mnie będzie to kolejne narzędzie przeznaczone do zapomnienia.
Źródła:
https://www.builder.io/blog/mitosis-a-quick-guide
Zainstaluj teraz i czytaj tylko dobre teksty!
2. Node 12-final, Node 17-final, Node 18.0.0
Nie, nie przewidzieliście się – w minionym tygodniu ukazały się aż 3 znaczące wersje Node.js. W przeciągu 7 dni doczekaliśmy się ostatecznego wydania dwóch finalnych wersji major Node.js: 12 i 17. Co szczególnie istotne Node 12 był wersją LTS, wydaną prawie ponad 3 lata temu. Czym prędzej sprawdźcie, czy jakieś z Waszych aplikacji nie stoją jeszcze na Node 12 lub 17, bo od maja nie będą one już otrzymywać łatek bezpieczeństwa.
Przejdźmy teraz do creme de la creme ostatniego tygodnia, czyli wydania Node 18. Najnowszy node, zgodnie z konwencją wersji parzystych i nieparzystych, jest wersją LTS i będzie otrzymywał wsparcie aż do końca kwietnia 2025. Jeśli chodzi o nowości, to Node.js nie przynosi rewolucji, ale wprowadza sporo interesujących eksperymentalnych API.
Gigantycznym krokiem milowym dla kompatybilności Node.js i przeglądarek jest wprowadzenie funkcji fetch(). Implementacja oparta jest o bibliotekę Undici i co prawda w jej dokumentacji znajdziemy wzmiankę, że fetch() nie jest jeszcze w pełni kompatybilny z wersją webową, ale twórcy Node.js zapewniają, że kompatybilność jest już na wystarczającym poziomie.
Kolejnym krokiem w stronę kierunku ujednolicenia przeglądarek i serwerów jest wprowadzenie Web Streams API, które to dodaje cały szereg globalnie dostępnych klas. Niby nic wielkiego, ale na pewno ucieszy wiele osób odpowiedzialnych za rozwój bibliotek.
Poza krokami milowymi w stronę kompatybilności z przeglądarkami, nowy Node wprowadza również własny Test Runner. Umożliwi on pisanie testów bez zaciągania zewnętrznych zależności, a wyniki eksportował będzie do powszechnie stosowanego standardu TAP. Całość nabiera kolorytu, jeśli pod uwagę weźmiemy ostatnie zamieszanie wokół Jesta, który utrzymywany jest przez pojedynczego kontrybutora.
Po nudnych wydaniach Node.js 16 i 17 wreszcie doczekaliśmy się naprawdę ciekawego Node.js. Szkoda tylko, że wszystkie interesujące funkcjonalności oznaczone są póki co jako eksperymentalne.
Źródła:
https://nodejs.org/es/blog/release/v12.22.12/
https://nodejs.org/en/blog/announcements/v18-release-announce/
Zainstaluj teraz i czytaj tylko dobre teksty!
3. Redux gotowy na React 18
Pewnie dotarła już do Was wieść, że po prawie dwóch latach od wydania React 17, doczekaliśmy się wreszcie wydania React 18 (jeśli nie, to zapraszam do 81 edycji naszego przeglądu, w całości poświęconego właśnie React 18). Nowa wersja frameworku od Mety przyniosła przede wszystkim opcjonalne współbieżne renderowanie i cały worek nowych API wokół tej funkcjonalności.
Jedną z nowych funkcjonalności był hook `useSyncExternalStore`. Jeśli wcześniej o nim nie słyszeliście, to nie macie się czym martwić – jest on częścią API przeznaczoną specjalnie dla twórców bibliotek odpowiedzialnych za zarządzanie stanem aplikacji. Nowy hook automatycznie wprowadzał memonizację selektorów i umożliwiał współbieżne odczyty, przy równoczesnym zapewnieniu synchroniczności aktualizacji. Dzięki takiej specyfikacji biblioteki do zarządzania stanem w prosty sposób mogą uniknąć równoczesnego renderowania różnych części aplikacji z różnym stanem (a sytuacja taka może mieć miejsce przez przerwanie renderowania, które jest powszechnym zjawiskiem w renderowaniu współbieżnym).
Jak się zapewne domyślacie po tym przydługim wstępie, największą nowością w react-redux jest wykorzystanie nowo wprowadzonego hooka `useSyncExternalStore`. Aby zapewnić kompatybilność wsteczną twórcy biblioteki zmuszeni byli dołączyć do paczki polyfill ważący 600 bajtów. Na szczęście skutecznie możemy się go pozbyć, przez importowanie reduxa pod ścieżką `react-redux/next`
Kolejną sporą nowością w react-redux v8 jest migracja biblioteki do TypeScript. Co prawda w kodzie nadal znajdziemy sporo anotacji `@ts-ignore`, ale jest to krok w dobrą stronę. No i wreszcie można pozbyć się z dependencji utrzymywanych przez community typów `@types/react-redux`.