Na kolejnego dużego TypeScripta musieliśmy czekać prawie 2 lata. Cierpliwość się jednak opłaciła, bo do TypeScript 5.0 trafiły dekoratory zgodne z standardem TC39 i spora paczka optymalizacji.
1. TypeScript 5.0 beta
W minionym tygodniu ukazała się beta TypeScript 5.0. Warto jednak pamiętać, że TypeScript nie stosuje się do Semantic Versioning. Co za tym idzie wersja ta przynosi raczej nowe funkcjonalności, niż breaking changes (chociaż i tych kilka się znajdzie). My dzisiaj przyjrzymy się 3 najciekawszym naszym zdaniem nowościom, ale jeśli chcecie zgłębić szczegóły samodzielnie, to jak zwykle odsyłam Was do genialnej notatki od Microsoftu.
Dekoratory
Historia dekoratorów w TypeScript to materiał na kilku sezonowy serial pełen zwrotów akcji i cliffhangerów. Przygoda zaczyna się w październiku 2014 roku, kiedy to na spotkaniu TC39 (przyp: grupa standaryzacyjna JavaScript, ja lubię ją porównywać do plemiennej starszyzny) zaprezenotwany został pierwszy proposal dekoratorów. Właściwie równolegle, na konferencji ngEurope ogłoszono, że Angular 2.0 napisany będzie w AtScript. Nowy język od Google maiał być oparty o TypeScript, ale rozszerzać go o kilka nowych funkcjonalności. Wśród nich znajdowały się między innymi tytułowe dekoratory.
Zasadnym wydaje się pytanie, dlaczego Google nie zdecydował się po prostu zainwestować w rozwój TypeScriptu. Stało się tak ze względu na konflikt interesów. Zespołowi z Microsoft zależało, żeby TypeScript był tak blisko JavaScriptu jak to tylko możliwe. To właściwie wykluczało szanse, na dodanie funkcjonalności, która w przyszłości mogłaby kolidować ze standardem. Zespół z Google potrzebował narzędzi, które pozwolą im zbudować ich wymarzony framework. Bez dekoratorów TypeScipt nie był takim narzędziem.
Na szczęście po burzliwych negocjacjach obie firmy doszyły do porozumienia. W maju 2015 roku na jednej z europejskich konferencji ogłoszono, że do TypeScript trafią dekoratory zgodne z Proposalem znajdującym się w Stage 1 (przyp: proces standaryzacyjny JavaSciprt składa się z 4 etapów – dopiero funkcjonalności w 3 etapie uznaje się za w miarę stabilne). Podczas tej samej konferencji ogłoszono, że Angular zostanie jednak opraty o TypeScript.
Od 2015 roku w kwestii dekoratorów sporo się zmieniło. Przede wszystki proposal przedarł się do Stage 3. Nie obyło się jednak bez strat. Z oryginalnego proposala wycięto znaczną część dotyczącą metadanych. To oznacza, że dekoratory będące już u progu standardu JavaScript, nie są zgodne z tymi zaimplementowanymi w TypeScript. Na szczęście na ratunek nam wszystkim przyszedł TypeScript 5.0.
Jeśli do tej pory nie mieliście doczynienia z dekoratorami, to są to po prostu funkcje, które pozwalają nam modyfikować zachowanie innch funckji lub klas. Temat jest na tyle skomplikowany i szeroki, że nie podejmę się przybliżenia go na łamach tego przegląd. Wszystkoch głodnych wiedzy odsysłam do świetnego artykułu Axela Rauschmayer. Po jego przeczytaniu możecie udać się prosto do notatki od Microsoftu, z której dowiecie się jak otypować swoje dekoratory.
// Decorator definition
function debut(originalMethod: any, _context: ClassMethodDecoratorContext) {
function replacementMethod(this: any, ...args: any[]) {
console.log("LOG: Entering method.")
const result = originalMethod.call(this, ...args);
console.log("LOG: Exiting method.")
return result;
}
return replacementMethod;
}
// Decorator usage
class Person {
constructor(private readonly name: string) {}
@debug greet() {
console.log(`Hello, my name is ${this.name}.`);
}
}
new Person("Tomek").greet();
// Expected output:
// LOG: Entering method.
// Hello, my name is Tomek
// LOG: Exiting method.
Co z projektami wykorzystującymi starą implementację dekoratorów (m.in. Angular, Ember i MobX)? Tak długo jak w konfiguracji TypeScript znajdować się będzie flaga --experimentalDecorators
ich zachowanie nie ulegnie zmianie. W dłuższej perspektywie wszystkie te biblioteki czeka jednak migracja.
const
Type Parametrs
Jeśli na codzień pracujecie z TypeScript, to na pewno znacie trik z as const
, który pozwala nam zawęzić inferowany typ.
// Inferred type: string[]
const namesA = ["Alice", "Bob", "Eve"];
// Inferred type: readonly ["Alice", "Bob", "Eve"]
const namesB = ["Alice", "Bob", "Eve"] as const;
Trik ten często wykorzystujemy na przykład do zawężania typu zwracanego przez funkcję.
function getNames<T extends { name: readonly string[]}>(arg: T): T["names"] {
return arg.names;
}
// Inferred type: string[]
const namesA = getNames({ names: ["Alice", "Bob", "Eve"]});
// Inferred type: readonly ["Alice", "Bob", "Eve"]
const namesB = getNames({ names: ["Alice", "Bob", "Eve"]} as const);
TypeScript 5.0 wprowadza mechanizm, który pozwala nam przenieść as const
do definicji typu. W ten sposób zabieramy ten ciężar z pleców naszych użytkowników i bierzemy go na swoje barki.
/* 👇 Hese is the new const type parameter */
function getNames<const T extends { names: readonly string[] }>(arg: T): T["names"] {
return arg.names;
}
// Inferred type: readonly ["Alice", "Bob", "Eve"]
const names = getNames{ names: ["Alice", "Bob", "Eve"] });
Optymalizacje
TypeScript 5.0 to również krok milowy jeśli chodzi o wydajność. Jest tak przede wszystkim ze względu na to, że język w całości został przepisany z archaicznych namespaces do modułów. To otworzyło drogę do wykorzystania całego szeregu narzędzi i mechanizmów optymalizujących zarówno kompilację jak i rozmiar ostatecznej paczki.
Na pełną wersję TypeScript 5.0 przyjdzie nam jeszcze poczekać do 14 marca, ale ja czekam już z wypiekami na twarzy. A Wy czekacie na nową wersję języka od Microsoftu, czy też dawno przestaliście już śledzić jakie nowości przynoszą jego kolejne wersje?
Zainstaluj teraz i czytaj tylko dobre teksty!
2. Astro 2.0
Astro to framework to renderowania po stronie serwera, który zadebiutował w 2021 roku i doczekał się pierwszego stabilnego wydania w 2022 roku. Na tle konkurencji wyróżnia się dwoma cechami: architekturą wysp i całkowitą niezależnością od frameworku.
Architekutra wysp zakłada, że na tworzonej przez nas stronie wśród morza statycznej treści (np. menu nawigacji, artykuł) znajdują się małe wyspy interaktywnych komponentów (np. formularz zapisu do newslettera). Dzięki takiemy założeniu, znacząco można odchudzić proces hydracji, czyli łączenia struktury HTML wyrenderowanej na serwerze z frameworkiem działającym po stronie klienta.
Astro jest też jednym z niewielu narzędzi, które pozwala nam do woli mieszać między sobą frameworki. Na ten moment do wyboru mamy React, Preact, Svelte, Vue, SolidJS i Lit, ale w przyszłości lista będzie zapewne się powiększać.
—
import HomeLayout from '../layouts/HomeLayout.astro'
import MyReactComponent from '../components/MyReactComponent.jsx';
import MySvelteComponent from '../components/MySvelteComponent.svelte';
const data = await fetch('API_URL').then(r => r.json());
---
<HomeLayout>
<MyReactComponent client:load name={data.name}>
<MySvelteComponent avatar={data.avatar}/>
</MyReactComponent>
</HomeLayout>
Rok 2022 był dla Astro pełen sukcesów. W State of JS w kategorii frameworków do renderowania po stronie serwera pod względem satysfakcji deweloperów Astro zajął 1 miejsce. W rankingu JavaScript Rising Star, mierzącym przyrost gwizdek na GitHubie, Astro uplasował się na 7 miejscu w kategorii ogólnej i na 3 miejscu w kategoroii frameworków serwerowych. Jak na debiutanta – naprawdę robi wrażenie!
Zespół stojący za Astro chce kontunuować dobrą passę i w minionym tygodniu opublikował Astro 2.0. W tym przypadku trzymamy się Semantic Versioning, więc pod spodem zaktualizowanych zostało całkiem sporo dependencji (m.in. Vite 4.0). Nie zmienia to jednak faktu, że twórcy upchnęli tu również całkiem sporo nowości.
Type-safe Markdown & MDX
Astro to idealne rozwiązanie do budowania blogów i dokumentacji opartych o Markdown i MDX. Na stronach tego typu powtarzalne fragmenty jak nagłówki czy metadane są kluczowe dla SEO. Jeśli programista zrobi nawet najmniejszą literówkę, to może to doprowadzić do sytuacji, w której dana podstrona będzie indeksowana źle lub nawet wcale. Odpowiednia integracja Markdown i MDX z typowanymi źródłami danych to prawdziwy killer feature.
Mechanizm zaprezentowany w Astro 2.0 opiera się o popularną bibliotekę Zod. Przy jej pomocy definiujemy schemat danych wejściowych. Następnie jeśli programista popełni błąd w pliku Markdown lub MDX, to zostanie on wykryty już na etapie budowania.
const blog = defineCollection({
schema: z.object({
// Define your expected frontmatter properties
title: z.string(),
// Mark certain properties as optional
draft: z.boolean().optional(),
// Transform datestrings to full Date objects
publishDate: z.string().transform((val) => new Date(val))
// Improve SEO with descriptive warnings
description: z.string().max(160, 'Short descriptions have better SEO!')
// ...
}),
});
Hybrid Rendering
Do tej pory korzystając z Astro zmuszeni byliśmy wybierać między renderowaniem po stronie serwera i renderowaniem po stronie klienta. Od Astro 2.0 do naszego arenału trafia również Hybrid Rendering. Odpowiednia konfiguracja tych trzech strategii może dawać naprawdę dobre efekty.
Dla przypomnienia – Hybrid Rendering to technika polegająca na renderowaniu stron na etapie budowania aplikacji, a następnie serwowania ich w statyczny sposób. Dzięki zasosowaniu takiej strategii klient nie czeka już aż serwer pobierze potrzebne dane i wyrenderuje strukturę HTML, tylko od razu pobiera statyczny plik HTML. Oczywiście, podejście to ma też swoje wady – znacząco wydłuża ono czas budowania aplikacji, wymaga podania wszystkich możliwych stron up-front i nie umożliwoia personalizowania treści dla poszczególnych użytkowników.
Jeśli chcecie dowiedzieć się co nowego trafiło jeszcze do Astro 2.0, to polecam Wam notatkę ogłaszającą wersję 2.0 i dedykowaną notatkę dotyczącą typowanego Markdown i MDX. Jeśli macie trochę więcej czasu i chcecie zobaczyć jak w praktyce wykorzystać nowości z Astro 2.0, to Jack Herrington przygotował prawie półgodzinne demo, na którym buduje prostego bloga.