Zpět na hlavní stránku

Deno Fresh 🍋

Přidal Filip Kalousek dne

Úvod

Není to dlouho co jsem dělal první test zaměřený na web framework Analog, který by měl konkurovat gigantům Next.js a Nuxt.js, poslední dobou jsem se motal také u Freshe z rodiny Deno.

Jak bude často v článku řečeno, tak Fresh je založen na Island architektuře.

Struktura

Po založení projektu máme strukturu rozdělenou do 5 částí (4 složky)

1. Components

Rozšíření nějakého elementu, nebo vytvoření vlastní komponenty bez možnosti interaktivity (bez JS).

2. Islands

Dynamická "komponenta", po načtení se klientovi odešle JS v minifikované verzi (s JS).

import { useState } from "preact/hooks";

export default function Counter() {
  const [count, setCount] = useState(0); // 0 Počáteční hodnota
  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count - 1)}>-1</button>
      <button onClick={() => setCount(count + 1)}>+1</button>
    </div>
  );
}

A ve výsledku tento island vyjde na ~ 15 kB JS.

3. Routes

Plně nastavitelné routy můžeme vytvořit podsložku, použití např. jako endpoint /routes/api/[NAZEV-SOUBORU] Pro parametry URL používáme hranaté závorky, aby vše bylo funční, tak musíme pojmenovat soubor ve stylu ahoj/[name].tsx

Zdroj toho našeho kódu:

import { PageProps } from "$fresh/server.ts";

export default function Hello(props: PageProps) {
  return <div>Ahoj {props.params.name}</div>;
}

Pro příklad - vytvoření endpointu, který bude vracet vtipy na route /api/vtipy

  1. Vytvoříme soubor vtipy.ts ve složce api
import { HandlerContext } from "$fresh/server.ts";

const JOKES = [
  "Proč jsou weboví vývojáři tak špatní na matematiku? Protože vždycky přepočítávají Body na Procenta.",
  "Proč jsou weboví vývojáři tak špatní na design? Protože vždycky používají Bootstrap.",
  "Proč jsou weboví vývojáři tak špatní na komunikaci? Protože vždycky komunikují pouze s kódem.",
  "Proč weboví vývojáři většinou používají Linux? Protože chtějí mít kontrolu nad svým systémem jako root."
];

export const handler = (_req: Request, _ctx: HandlerContext): Response => {
  const randomIndex = Math.floor(Math.random() * JOKES.length);
  const body = JOKES[randomIndex];
  return new Response(body);
};

Na pozici jednotlivých routes, dejme tomu, že budeme chtít použít index.tsx

import { Handlers, PageProps } from "$fresh/server.ts";

export const handler: Handlers<string> = {
  async GET(_, ctx) {
    const resp = await fetch(`http://localhost:8000/api/vtipy`);
    const joke = await resp.text();
    return ctx.render(joke);
  },
};

export default function Home({data}: PageProps) {
  return (
    <p>
      {data}
    </p>
  );
}

Test

Poslední dobou jsem přemýšlel nad nějakou aplikací, která by využila SSR z nějaké Open Data API, rozhodl jsem se použít Astronomické snímky dne od NASA, vytvořit si pomocí Islandu Canvas editor, kde může člověk vytvořit plakát s vlastním textem + detail dní s možností překladů pomocí DeepL.

Na appce jsem použil také Tailwind (i když nejsem moc velkým fanouškem).

Výsledná stránka vypadá nějako takto:

Hlavní stránka Perf hlavní stránky

Detail dne Perf detailu dne

Editor

Co se dá očekávat, tak nejhůře na tom je optimalizace editoru, to z důvodu načítání obrázku v plné velikosti (někdy až 15Mb).

Perf editoru

Celkově se web skládá z 5 Islandů

  • Editor
  • Menu toggle
  • Tweet buttonu
  • Date pickeru
  • Save CrossOrigin obrázku (handler)

Shrnutí

Dalo by se říct, že je zatím Fresh ještě v plenkách, ale už teď mě nesmírně baví a celkově Deno teď má obrovský hype.

Zatím pro verzi 1.1 dávam tomuto frameworku 8/10 ⭐.

Níže jsem si dovolil napsat pár výhod a nevýho, na které jsem přišel nejen na vytváření tohoto projektu.

Výhody

  • Veliký důraz na SSR
  • Vy výchozím stavu projektu žádný JS
  • Žádná nutná počáteční konfigurace
  • Tailwind podpora

Nevýhody

  • SSR na komponentě nefunkční (má to své důvody, ale škoda)
  • Podpora knihoven
  • Odfláklá dokumentace / příklady

Zdroje

A celkově o Deno si řekneme někdy jindy.