Hono zdobywa rynek - rewolucja w świecie JavaScript frameworków i przyszłość testowania automatycznego

Published on 9/16/2024

Hono - nowy lider wśród JavaScript frameworków

TLDR: Hono, framework serwerowy JavaScript, odnotowuje 11-krotny wzrost popularności w ciągu roku dzięki szybkości, wsparciu dla Web Standards i możliwości działania na każdym runtime JavaScript. Rozwija się w kierunku full-stack meta-frameworka z własnymi komponentami klienckimi i funkcjami RPC.

Obserwujemy fascynujące zjawisko w ekosystemie JavaScript - Hono, framework serwerowy, który jeszcze rok temu był znany głównie wąskiemu gronu deweloperów, teraz przeżywa prawdziwą eksplozję popularności. Liczby mówią same za siebie: 11-krotny wzrost pobrań z npm w ciągu ostatnich dwunastu miesięcy to wynik, który zmusza do refleksji nad tym, co tak naprawdę się dzieje w świecie backend development.

Początkowo Hono przyciągnął uwagę z czterech kluczowych powodów. Po pierwsze, jego architektura oparta na Web Standards oznacza, że może działać na dowolnym runtime JavaScript - od Cloudflare Workers przez Deno po Node.js. To uniwersalność, o której deweloperzy marzyli od lat. Po drugie, framework oferuje imponującą wydajność dzięki RegExpRouter, który twórcy nazywają "najszybszym routerem w świecie JavaScript". Po trzecie, TypeScript jest tutaj obywatelem pierwszej kategorii, a nie dodatkiem wymyślonym po fakcie. I wreszcie - Hono po prostu nie jest Express.js, co dla wielu deweloperów zmęczonych ograniczeniami tego starego frameworka brzmi jak muzyka dla uszu.

Ale Hono nie zatrzymało się na byciu kolejnym frameworkiem serwerowym. Najnowsze wydania, włączając w to wersję 4.6, wprowadzają funkcjonalności, które stawiają go w pozycji kandydata na następny mainstream web framework. Mamy tu komponenty klienckie z JSX i React-podobnymi hookami, helper do generowania stron statycznych, plugin Vite do błyskawicznego tworzenia static pages. Nowa funkcja RPC pozwala serwerowi i klientowi dzielić specyfikacje używając typów TypeScript i zwykłego REST API - niektórzy deweloperzy już używają tego rozwiązania jako zamiennika dla tRPC.

Meta-framework HonoX, choć wciąż w fazie alpha, dostarcza routing oparty na plikach, szybkie SSR, hydrację islands i middleware - wszystko to, co potrzebne do budowy dużych aplikacji. Dla architektów i zespołów deweloperskich oznacza to możliwość budowy aplikacji full-stack z jednym, spójnym API i modelem typów współdzielonym między frontendem a backendem. To podejście może znacząco uprościć architekturę systemów i zmniejszyć cognitive load związany z przełączaniem się między różnymi paradygmatami.

Key takeaways:

  • Hono odnotowuje 11-krotny wzrost popularności dzięki uniwersalności i wydajności
  • Framework rozwija się w kierunku full-stack rozwiązania z komponentami klienckimi i RPC
  • Meta-framework HonoX oferuje funkcjonalności konkurencyjne dla Next.js i podobnych rozwiązań

Link: Bytes #323 - The Hono takeover

RPC w Hono - nowa era type-safe komunikacji

TLDR: Hono wprowadza funkcję RPC, która pozwala na dzielenie specyfikacji API między serwerem a klientem za pomocą typów TypeScript, oferując alternatywę dla OpenAPI i gRPC przy użyciu zwykłego REST API.

Jedną z najbardziej intrygujących innowacji w Hono jest implementacja RPC, która podchodzi do problemu komunikacji client-server w sposób fundamentalnie różny od tradycyjnych rozwiązań. W przeciwieństwie do gRPC czy OpenAPI, które wymagają dodatkowych warstw abstrakcji i generowania kodu, Hono RPC działa z zwykłymi REST API, ale zapewnia pełną type safety między klientem a serwerem.

Mechanizm jest elegancko prosty w swojej koncepcji. Definiujemy endpoint na serwerze używając standardowego Hono API, ale eksportujemy typ tego endpointu jako AppType. Następnie na kliencie importujemy ten typ i przekazujemy go do funkcji hc, która tworzy w pełni typowany klient. To oznacza, że IDE wie dokładnie, jakie endpointy są dostępne, jakie parametry oczekują i jakie typy zwracają.

Co czyni to rozwiązanie szczególnie atrakcyjnym, to fakt, że klient pozostaje wrapper'em wokół standardowego fetch API. Oznacza to, że otrzymujemy standardowe obiekty Response, które możemy obsługiwać w znany sposób, ale z dodatkową korzyścią w postaci type safety. Gdy wywołujemy res.json(), TypeScript wie dokładnie, jaki kształt będą miały zwrócone dane.

Dla zespołów pracujących z TypeScript, to podejście oferuje znaczące korzyści w porównaniu z tradycyjnymi rozwiązaniami. Eliminuje potrzebę ręcznego pisania typów dla API calls, redukuje ryzyko błędów związanych z niezgodnością między frontendem a backendem, a także zapewnia doskonałe wsparcie dla refactoring - zmiana na serwerze automatycznie generuje błędy kompilacji w miejscach klienta, które wymagają aktualizacji.

Dla architektów systemów, Hono RPC przedstawia interesującą alternatywę dla GraphQL w scenariuszach, gdzie potrzebujemy type safety, ale nie chcemy complexity związanego z query language. Jest to szczególnie atrakcyjne w mikrousługach, gdzie każda usługa może eksportować swoje typy, a inne usługi mogą je importować dla type-safe komunikacji.

Key takeaways:

  • Hono RPC dzieli specyfikacje API między serwerem a klientem używając typów TypeScript
  • Działa ze standardowym REST API i fetch, bez dodatkowych warstw abstrakcji
  • Oferuje pełną type safety z doskonałym wsparciem dla refactoring i IDE

Link: Hey, this is Hono's RPC

Automatyzacja testów z QA Wolf - koniec ery manual testing

TLDR: QA Wolf oferuje 80% automatycznego pokrycia testów end-to-end w ciągu miesięcy, łącząc AI do analizy błędów z ludzkimi inżynierami QA. AutoTrader zaoszczędził 620 tysięcy dolarów rocznie, przechodząc z testowania manualnego na automatyzację.

W świecie, gdzie szybkość dostarczania oprogramowania często decyduje o sukcesie biznesowym, testowanie manualne staje się wąskim gardłem, które może kosztować organizacje setki tysięcy dolarów rocznie. Historia AutoTrader doskonale ilustruje ten problem - zespół polegał na testerach manualnych z działu customer support, co tworzyło bottleneck zarówno po stronie inżynierskiej, jak i wsparcia klienta.

QA Wolf przedstawia fundamentalnie inne podejście do automatyzacji testów. Zamiast budować wewnętrzny zespół QA, który potrzebowałby miesięcy lub lat na osiągnięcie znaczącego pokrycia, firma oferuje gotowe rozwiązanie, które może dostarczyć 80% pokrycia testów end-to-end w ciągu tygodni. Kluczem do sukcesu jest połączenie AI z ludzkimi ekspertami - sztuczna inteligencja analizuje niepowodzenia testów w ciągu sekund, ale ostateczne decyzje podejmują doświadczeni inżynierowie.

Architektura rozwiązania jest przemyślana pod kątem skalowalności i niezawodności. Testy są pisane w Playwright i uruchamiane w pełni równolegle w oddzielnych kontenerach w chmurze. Każdy test tworzy i czyści własne dane, co eliminuje kolizje i redukuje flaky tests. System automatycznie ponawia testy co najmniej trzy razy, aby wykluczyć tymczasowe problemy sieciowe lub środowiskowe.

Szczególnie interesujący jest trzystopniowy system utrzymania testów. Proste zmiany UI są naprawiane automatycznie, większe zmiany UX są gotowe w ciągu godziny lub dwóch, a nawet kompletny refactoring front-endu nie stanowi problemu - zespół QA Wolf odbudowuje wszystkie testy od podstaw bez dodatkowych kosztów.

Dla zespołów i architektów, to rozwiązanie oznacza możliwość skupienia się na budowaniu funkcjonalności zamiast na tworzeniu i utrzymywaniu infrastruktury testowej. W przypadku AutoTrader, przejście na automatyzację skróciło czas testowania z tygodni do dni, a niektóre projekty, które wcześniej leżały miesiącami w oczekiwaniu na testy, mogły być szybko wdrożone do produkcji.

Key takeaways:

  • QA Wolf łączy AI z ludzkimi ekspertami dla efektywnej automatyzacji testów
  • AutoTrader zaoszczędził $620k rocznie, skracając cykle testowania z tygodni do dni
  • Trzystopniowy system utrzymania testów radzi sobie nawet z kompletnymi refactoringami

Tradeoffs:

  • Automatyzacja zwiększa pokrycie testów ale oznacza utratę kontroli nad infrastrukturą testową
  • Outsourcing QA przyspiesza wdrożenie ale tworzy zależność od zewnętrznego dostawcy

Link: QA Wolf | 80% automated test coverage in 4 months

Infinite Queries w React Query - zrozumienie mechanizmów

TLDR: Artykuł wyjaśnia, jak działają Infinite Queries w React Query, skupiając się na niedawno odkrytym błędzie związanym z retry mechanizmem podczas częściowych niepowodzeń w pobieraniu stron. Problem występował od lat, ale nie był zgłaszany ze względu na zaufanie do jakości biblioteki.

Infinite Queries to jedna z najbardziej zaawansowanych funkcjonalności React Query, umożliwiająca implementację nieskończonego scrollingu w sposób deklaratywny. Choć z poziomu API wyglądają podobnie do zwykłych queries, wewnętrzna implementacja jest znacznie bardziej skomplikowana, co czasami prowadzi do subtelnych błędów.

Niedawno odkryty bug ilustruje złożoność tej funkcjonalności. Problem występował w bardzo specyficznym scenariuszu: gdy Infinite Query, która już wcześniej pobrała wiele stron, wykonywała refetch, a podczas tego procesu niektóre strony zostały pobrane pomyślnie, ale następna strona nie powiodła się, i jednocześnie używany był mechanizm retry. W takiej sytuacji biblioteka mogła wejść w niepożądany stan.

Co fascynujące w tej historii, to fakt, że bug istniał od czterech lat, ale nie był zgłaszany. Użytkownicy, którzy napotykali ten problem, nie wierzyli, że React Query może mieć tak fundamentalną wadę, więc zakładali, że błąd leży po ich stronie. To świadczy o wysokim poziomie zaufania do jakości biblioteki, ale jednocześnie pokazuje, jak ważne jest aktywne zgłaszanie problemów, nawet jeśli wydają się zbyt oczywiste.

Mechanizm Infinite Queries różni się od zwykłych queries tym, że musi zarządzać kolekcją stron, z których każda może mieć inny stan. Podczas refetch, biblioteka musi zdecydować, które strony odświeżyć, jak obsłużyć częściowe niepowodzenia i jak zachować spójność danych. To znacznie bardziej skomplikowane niż obsługa pojedynczego zapytania.

Dla deweloperów pracujących z Infinite Queries, kluczowe jest zrozumienie, że nie są to po prostu "zwykłe queries z więcej danych". Mają one własną logikę zarządzania stanem, własne wzorce błędów i wymagają innego podejścia do testowania. Warto również aktywnie monitorować ich zachowanie w production i nie wahać się zgłaszać nietypowych zachowań - nawet jeśli wydają się zbyt oczywiste, aby być prawdziwymi bugami.

Key takeaways:

  • Infinite Queries mają znacznie bardziej złożoną logikę wewnętrzną niż zwykłe queries
  • Niedawno odkryty bug istniał 4 lata, ale nie był zgłaszany ze względu na zaufanie do biblioteki
  • Mechanizm retry w połączeniu z częściowymi niepowodzeniami może prowadzić do niepożądanych stanów

Link: How Infinite Queries work

Web Clipboard API - wieloformatowe przechowywanie danych

TLDR: Clipboard API w przeglądarce obsługuje przechowywanie danych w wielu formatach jednocześnie (text/plain, text/html, image/png), co pozwala różnym aplikacjom odczytywać najbardziej odpowiedni format. Artykuł wyjaśnia mechanizmy działania i ograniczenia tej funkcjonalności.

Clipboard w przeglądarce to znacznie bardziej zaawansowany mechanizm, niż mogłoby się wydawać na pierwszy rzut oka. Gdy kopiujemy treść z strony internetowej i wklejamy ją do różnych aplikacji, każda z nich może otrzymać inną reprezentację tych samych danych - Google Docs zachowuje formatowanie HTML, podczas gdy VS Code otrzymuje tylko plain text.

Mechanizm ten działa dzięki temu, że Clipboard API pozwala przechowywać dane w wielu reprezentacjach jednocześnie, każda powiązana z określonym typem MIME. Specyfikacja W3C wymaga obsługi trzech podstawowych typów: text/plain dla zwykłego tekstu, text/html dla HTML i image/png dla obrazów PNG. To minimum zapewnia interoperacyjność między różnymi aplikacjami i przypadkami użycia.

Implementacja zapisu do schowka wymaga tworzenia obiektów Blob dla każdej reprezentacji, a następnie przekazania ich do konstruktora ClipboardItem w formie key-value store, gdzie klucze to typy MIME, a wartości to blobs. To eleganckie rozwiązanie API, które sprawia, że niemożliwe stany stają się niereprezentowalne - nie można przypadkowo przypisać błędnego typu do danych.

Odczyt ze schowka jest równie prosty - iterujemy przez elementy, sprawdzamy dostępne typy i wybieramy ten, który nas interesuje. API jest asynchroniczne, co pozwala przeglądarce obsługiwać duże ilości danych bez blokowania głównego wątku.

Dla deweloperów aplikacji webowych, zrozumienie mechanizmów Clipboard API otwiera możliwości tworzenia bardziej wyrafinowanych funkcji kopiowania i wklejania. Możemy zapewnić, że nasze dane będą odpowiednio interpretowane przez różne aplikacje docelowe, a użytkownicy otrzymają najlepsze możliwe doświadczenie niezależnie od tego, gdzie wklejają skopiowaną treść.

Ograniczenia API, szczególnie w kontekście niestandardowych formatów danych, prowadzą do interesujących rozwiązań obejściowych stosowanych przez duże firmy. Propozycje takie jak Web Custom Formats mają na celu rozszerzenie możliwości API o obsługę bardziej specjalistycznych typów danych.

Key takeaways:

  • Clipboard API przechowuje dane w wielu formatach jednocześnie dla różnych aplikacji
  • Specyfikacja wymaga obsługi text/plain, text/html i image/png jako minimum
  • API używa eleganckich key-value stores, które zapobiegają nieprawidłowym stanom

Link: The web's clipboard, and how it stores data of different types

Safe-await pattern - eleganckie obsługiwanie błędów w JavaScript

TLDR: Wzorzec safe-await inspirowany obsługą błędów z języka Go pozwala uniknąć zagnieżdżonych bloków try/catch w JavaScript. Zwraca tuple [error, result], co czyni kod bardziej czytelnym i łatwiejszym w utrzymaniu, choć kosztem niewielkiej dodatkowej szczegółowości.

Zagnieżdżone bloki try/catch to jeden z najbardziej frustrujących aspektów pracy z asynchronicznym kodem JavaScript. Gdy mamy serię promises, z których każdy zależy od wyniku poprzedniego, tradycyjne podejście prowadzi do kodu, który przypomina callback hell, ale w wersji error handling.

Wzorzec safe-await oferuje eleganckie rozwiązanie inspirowane językiem Go, gdzie funkcje zwracają zarówno wynik, jak i błąd jako osobne wartości. W JavaScript implementujemy to za pomocą destructuring assignment, otrzymując tuple w formie [error, result]. Jeśli operacja się powiedzie, error jest null, a result zawiera dane. W przypadku błędu, error zawiera informacje o problemie, a result jest undefined.

To podejście ma kilka znaczących zalet. Po pierwsze, eliminuje potrzebę zagnieżdżania bloków try/catch, co znacznie poprawia czytelność kodu. Po drugie, każdy błąd jest obsługiwany w miejscu, gdzie występuje, co ułatwia debugging i utrzymanie. Po trzecie, flow control staje się bardziej eksplicitny - każda operacja może się nie powieść, a kod musi to uwzględnić.

Wzorzec jest szczególnie użyteczny w scenariuszach, gdzie mamy do czynienia z długimi łańcuchami operacji asynchronicznych, każda z własną logiką obsługi błędów. Zamiast jednego catch block, który obsługuje wszystkie możliwe błędy, możemy reagować specyficznie na każdy typ problemu.

Dla zespołów deweloperskich, wprowadzenie tego wzorca może znacznie poprawić jakość kodu i zmniejszyć liczbę błędów związanych z nieodpowiednią obsługą wyjątków. Jest to szczególnie wartościowe w aplikacjach, gdzie różne typy błędów wymagają różnych strategii recovery.

Warto jednak pamiętać, że wzorzec wprowadza pewną dodatkową szczegółowość - każda operacja asynchroniczna wymaga sprawdzenia błędu przed kontynuowaniem. W niektórych przypadkach, gdzie wszystkie błędy są obsługiwane jednakowo, tradycyjny try/catch może być prostszy.

Key takeaways:

  • Safe-await eliminuje zagnieżdżone try/catch blocks poprzez zwracanie tuple [error, result]
  • Wzorzec inspirowany językiem Go czyni obsługę błędów bardziej eksplicitną
  • Każdy błąd jest obsługiwany w miejscu występowania, co ułatwia debugging

Tradeoffs:

  • Zyskujemy czytelność i eksplicitną obsługę błędów ale poświęcamy zwięzłość kodu
  • Lepsze flow control oznacza więcej boilerplate code dla każdej operacji asynchronicznej

Link: Cleaner JavaScript promises with safe-await

MDX w Next.js - konfiguracja i integracja treści

TLDR: MDX łączy Markdown z JSX, pozwalając na tworzenie bogatej, dynamicznej treści. W Next.js można go skonfigurować używając oficjalnego pakietu @next/mdx lub alternatywnych rozwiązań. Artykuł przedstawia step-by-step setup dla App Router.

MDX reprezentuje jedno z najbardziej eleganckich rozwiązań dla deweloperów, którzy chcą łączyć prostotę pisania w Markdown z mocą komponentów React. To format treści, który pozwala na używanie składni Markdown dla podstawowego formatowania, jednocześnie umożliwiając wplatanie interaktywnych komponentów JSX bezpośrednio w treść.

W kontekście Next.js, MDX nie działa out-of-the-box, co wymaga odpowiedniej konfiguracji. Oficjalne podejście wykorzystuje pakiet @next/mdx wraz z @mdx-js/loader i @mdx-js/react. Konfiguracja wymaga modyfikacji next.config.js, gdzie musimy rozszerzyć listę obsługiwanych rozszerzeń plików i opakować naszą konfigurację funkcją withMDX.

Kluczowym elementem jest plik mdx-components.tsx, który służy jako punkt konfiguracyjny dla custom components. To tutaj możemy definiować, jak poszczególne elementy Markdown powinny być renderowane - na przykład, czy chcemy zastąpić standardowe nagłówki własnymi komponentami ze specjalnymi stylami lub funkcjonalnością.

Oficjalne podejście Next.js ma jednak ograniczenie - pliki MDX muszą znajdować się wewnątrz katalogu app, co oznacza, że stają się częścią routingu aplikacji. To może być problematyczne, gdy chcemy używać MDX jako źródła treści, ale nie chcemy, żeby każdy plik automatycznie tworzył nową stronę.

Dla zespołów tworzących content-heavy aplikacje, MDX oferuje potężne możliwości. Możemy tworzyć interaktywne tutoriale, dokumentację z live examples, blog posty z embedded komponenty czy landing pages z dynamicznymi elementami. Wszystko to przy zachowaniu prostoty pisania w Markdown.

Architekci systemów docenią fakt, że MDX pozwala na separację concerns - content creators mogą skupić się na treści używając znajomej składni Markdown, podczas gdy deweloperzy dostarczają komponenty, które mogą być używane w treści. To podejście skaluje się dobrze w większych organizacjach, gdzie różne zespoły odpowiadają za różne aspekty produktu.

Key takeaways:

  • MDX łączy prostotę Markdown z mocą komponentów React dla dynamicznej treści
  • Next.js wymaga konfiguracji przez @next/mdx i rozszerzenie pageExtensions
  • Plik mdx-components.tsx pozwala na customizację renderowania elementów Markdown

Link: MDX in Next.js


Disclaimer: This article was generated using newsletter-ai powered by claude-sonnet-4-20250514 LLM. While we strive for accuracy, please verify critical information independently.