Kas tas Deno ir kodėl jis iš viso atsirado?
Jei sekate JavaScript ekosistemą, tikriausiai jau girdėjote apie Deno – runtime aplinką, kurią sukūrė tas pats Ryan Dahl, Node.js tėvas. Tik šįkart jis nusprendė pataisyti savo paties klaidas. 2018 metais konferencijoje JSConf jis pasakė garsią kalbą „10 dalykų, kurių gailisi apie Node.js”, ir štai rezultatas – Deno.
Bet Fresh framework’as yra dar naujesnis dalykas. Tai web framework’as, sukurtas specialiai Deno ekosistemoje, kuris 2022 metais pristatė gana radikalią idėją: o gal galima daryti šiuolaikiškus web projektus be build step’o? Be webpack’o, be vite’o, be jokių bundler’ių? Skamba kaip fantastika, ypač jei paskutinius kelerius metus praleidote konfigūruodami babel, typescript, ir dar dešimt kitų įrankių.
Fresh žada grąžinti paprastumą, bet tuo pačiu išlaikyti visus modernius funkcionalumus. Tai ne grįžimas į 2010-uosius – tai šuolis į priekį, tik kitu keliu.
No-build architektūros esmė
Tradiciškai, kai kuriate React, Vue ar bet kokį kitą modernų web projektą, jūsų workflow atrodo maždaug taip: rašote kodą, paleidžiate build procesą, kuris viską sukompiliuoja, optimizuoja, sujungia į bundle’us, ir tik tada galite matyti rezultatą naršyklėje. Development režime tai vyksta automatiškai background’e, bet vis tiek – tas procesas egzistuoja.
Fresh’as veikia fundamentaliai kitaip. Jūsų TypeScript kodas vykdomas tiesiogiai serveryje be jokio transpiliavimo. Komponentai renderinami server-side, o į klientą siunčiamas minimalus JavaScript kiekis – tik tai, kas tikrai reikalinga interaktyvumui.
Kaip tai įmanoma? Deno natively palaiko TypeScript ir modernius ES modulius. Naršyklės šiais laikais taip pat palaiko ES modulius. Taigi, kam tas tarpininkas? Fresh tiesiog eliminuoja šį perteklinį sluoksnį.
Praktiškai tai reiškia, kad jūs išsaugote failą ir iš karto matote pakeitimus. Ne po 3 sekundžių, ne po 10 sekundžių kaip sudėtingesniuose projektuose – iš karto. Hot module replacement čia nėra magiška technologija, kurią reikia konfigūruoti – tai tiesiog natūrali sistemos dalis.
Kaip Fresh veikia po gaubtu
Fresh architektūra remiasi keliais pagrindiniais principais. Pirma, Islands Architecture – koncepcija, kurią populiarino Astro framework’as. Idėja paprasta: dauguma jūsų puslapio yra statinis HTML, o interaktyvumas yra tik „salelėse” – atskiruose komponentuose, kuriems tikrai reikia JavaScript.
Pavyzdžiui, turite straipsnį su komentarų sekcija. Straipsnis – statinis HTML, renderintas serveryje. Komentarų forma su real-time validacija – tai „sala”, kuri gauna JavaScript ir tampa interaktyvi. Fresh automatiškai identifikuoja šias salas ir siunčia tik reikalingą kodą.
Antra, file-based routing. Jei dirbote su Next.js ar SvelteKit, tai jums pažįstama. Sukuriate failą `routes/about.tsx` – turite route’ą `/about`. Paprasta, intuityvu, nereikia konfigūruoti jokių router’ių.
Trečia, Preact kaip UI biblioteka. Fresh naudoja Preact – React alternatyvą, kuri yra tik 3KB dydžio. Ji turi beveik identišką API kaip React, tad jei mokate React, mokate ir Preact. Bet ji daug mažesnė ir greitesnė.
Ketvirta, zero config filosofija. Jūs neatidarysite `fresh.config.js` failo su 200 eilučių konfigūracijos. Tokio failo tiesiog nėra. Framework’as turi protingus defaults, kurie veikia 95% atvejų. Jei reikia kažko specifinio, galite customizuoti, bet pradžiai – tiesiog pradėkite kurti.
Praktinis pavyzdys: sukuriame pirmą projektą
Užtenka teorijos, pažiūrėkime, kaip tai atrodo praktikoje. Pirma, jums reikia Deno. Įdiegimas paprastas:
„`bash
curl -fsSL https://deno.land/install.sh | sh
„`
Dabar sukuriame Fresh projektą:
„`bash
deno run -A -r https://fresh.deno.dev my-project
cd my-project
deno task start
„`
Ir viskas. Jūsų projektas veikia `localhost:8000`. Nereikėjo instaliuoti `node_modules` su 300MB priklausomybių. Nereikėjo laukti, kol npm įdiegs pusę interneto.
Pažiūrėkime į paprastą route’ą. Sukuriate `routes/index.tsx`:
„`typescript
import { Head } from „$fresh/runtime.ts”;
import Counter from „../islands/Counter.tsx”;
export default function Home() {
return (
<>
Sveiki atvykę!
Tai statinis turinys, renderintas serveryje.
>
);
}
„`
O dabar interaktyvi „sala” – `islands/Counter.tsx`:
„`typescript
import { Signal, useSignal } from „@preact/signals”;
interface CounterProps {
start: number;
}
export default function Counter(props: CounterProps) {
const count = useSignal(props.start);
return (
Skaičius: {count}
);
}
„`
Atkreipkite dėmesį: `routes/` kataloge – server-side komponentai, `islands/` kataloge – client-side interaktyvūs komponentai. Fresh automatiškai supranta skirtumą. Jums nereikia rašyti `”use client”` ar kitų direktyvų.
Signals: reaktyvumas be overhead’o
Fresh naudoja Preact Signals – naują reaktyvumo sistemą, kuri yra greitesnė už tradicinį React state management. Signals yra primityvios reaktyvios reikšmės, kurios automatiškai atnaujina UI, kai pasikeičia.
Kodėl tai svarbu? Tradiciniame React, kai pasikeičia state, komponentas re-renderinamas visas. Su Signals, atnaujinamos tik tos DOM dalys, kurios tikrai priklauso nuo pasikeitusios reikšmės. Tai labai efektyvu.
Pavyzdys su forma:
„`typescript
import { useSignal } from „@preact/signals”;
export default function ContactForm() {
const name = useSignal(„”);
const email = useSignal(„”);
const message = useSignal(„”);
const isValid = useComputed(() =>
name.value.length > 0 &&
email.value.includes(„@”) &&
message.value.length > 10
);
const handleSubmit = async (e: Event) => {
e.preventDefault();
if (!isValid.value) return;
await fetch(„/api/contact”, {
method: „POST”,
body: JSON.stringify({
name: name.value,
email: email.value,
message: message.value
})
});
};
return (
);
}
„`
`useComputed` automatiškai perskaičiuoja reikšmę, kai pasikeičia bet kuris iš signals, nuo kurių ji priklauso. Nereikia `useEffect`, `useMemo`, ar kitų React hooks’ų sudėtingumo.
API routes ir duomenų gavimas
Fresh turi integruotą API routes sistemą. Bet koks failas `routes/api/` kataloge automatiškai tampa API endpoint’u. Pavyzdžiui, `routes/api/users.ts`:
„`typescript
import { Handlers } from „$fresh/server.ts”;
interface User {
id: number;
name: string;
email: string;
}
export const handler: Handlers
async GET(_req, _ctx) {
// Čia galite kreiptis į duomenų bazę
const users = await db.users.findMany();
return new Response(JSON.stringify(users), {
headers: { „Content-Type”: „application/json” },
});
},
async POST(req, _ctx) {
const body = await req.json();
const newUser = await db.users.create({ data: body });
return new Response(JSON.stringify(newUser), {
status: 201,
headers: { „Content-Type”: „application/json” },
});
},
};
„`
Duomenų gavimas puslapiuose taip pat paprastas. Galite naudoti `handler` funkciją bet kuriame route:
„`typescript
import { Handlers, PageProps } from „$fresh/server.ts”;
interface Post {
id: number;
title: string;
content: string;
}
export const handler: Handlers
async GET(_req, ctx) {
const posts = await db.posts.findMany();
return ctx.render(posts);
},
};
export default function BlogPage({ data }: PageProps
return (
Tinklaraštis
{data.map((post) => (
{post.title}
{post.content}
))}
);
}
„`
Duomenys gaunami serveryje, renderinami į HTML, ir siunčiami klientui. Nėra loading state’ų, nėra skeleton screens – vartotojas iš karto mato turinį.
Deployment ir production aplinka
Vienas didžiausių Fresh privalumų – deployment’o paprastumas. Kadangi nėra build step’o, jums nereikia konfigūruoti CI/CD pipeline’ų su build procesais. Tiesiog deploy’inate kodą ir paleidžiate.
Rekomenduojama platforma – Deno Deploy. Tai serverless platforma, sukurta specialiai Deno projektams. Deployment’as atrodo taip:
1. Sukuriate GitHub repository
2. Prijungiate jį prie Deno Deploy
3. Kiekvieną kartą push’indami į main branch, projektas automatiškai deploy’inamas
Nėra Dockerfile’ų, nėra Kubernetes konfigūracijų, nėra serverių administravimo. Deno Deploy automatiškai scale’ina jūsų aplikaciją globally – ji veikia edge’e, arti jūsų vartotojų.
Alternatyviai, galite deploy’inti į bet kokį serverį, kuris palaiko Deno. Pavyzdžiui, Docker konteineris:
„`dockerfile
FROM denoland/deno:1.40.0
WORKDIR /app
COPY . .
RUN deno cache main.ts
EXPOSE 8000
CMD [„deno”, „task”, „start”]
„`
Arba tiesiog VPS su Deno įdiegtu:
„`bash
git clone your-repo
cd your-repo
deno task start –port 80
„`
Performance production’e yra įspūdingas. Kadangi Fresh siunčia minimalų JavaScript kiekį, puslapiai užsikrauna greitai net lėtame internete. Server-side rendering reiškia, kad SEO yra puikus – search engine’ai mato visą turinį iš karto.
Realūs use case’ai ir apribojimai
Fresh nėra silver bullet. Yra scenarijai, kur jis puikiai tinka, ir yra scenarijai, kur geriau rinktis ką nors kita.
Kur Fresh puikiai tinka:
– Content-heavy websites – tinklaraščiai, dokumentacijos puslapiai, marketing sites
– E-commerce projektai su daugiau turinio nei interaktyvumo
– Admin panelės su formomis ir CRUD operacijomis
– MVP projektai, kur reikia greitai paleisti produktą
– Projektai, kur SEO ir performance yra kritiniai
Kur Fresh gali būti ne geriausias pasirinkimas:
– Labai interaktyvios aplikacijos (pvz., Figma tipo tools)
– Real-time collaborative apps
– Projektai, kur jau turite didelę React ekosistemą ir bibliotekų priklausomybes
– Situacijos, kur komanda neturi patirties su Deno
Deno ekosistema dar auga. Nors daugelis populiarių npm paketų veikia Deno, ne visi. Jei jūsų projektas labai priklauso nuo specifinių Node.js bibliotekų, migravimas gali būti sudėtingas.
Kita vertus, Deno turi puikų npm compatibility layer. Galite importuoti npm paketus tiesiogiai:
„`typescript
import React from „npm:react@18.2.0”;
import lodash from „npm:lodash@4.17.21”;
„`
Tai veikia, bet prarandate kai kuriuos Deno privalumus – pavyzdžiui, tuos paketus vis tiek reikia „build’inti” runtime’e.
Ateitis be build step’ų?
Fresh framework’as rodo įdomią kryptį, kuria gali judėti web development. Build step’ai atsirado ne be priežasties – jie išsprendė realias problemas. Bet technologijos evoliucionuoja, ir dabar turime runtime’us, kurie natively palaiko TypeScript, turime naršykles, kurios palaiko ES modulius, turime edge computing platformas.
Galbūt už kelių metų build step’ai atrodys kaip legacy dalykas, kaip dabar atrodo jQuery ar PHP templates. O gal ne – gal build time optimizacijos visada bus vertingos. Sunku pasakyti.
Bet viena aišku: Fresh įrodo, kad galima kurti modernius, greitus, SEO-friendly web projektus be sudėtingų build pipeline’ų. Tai ne kompromisas – tai tiesiog kitoks požiūris.
Jei dar nenaudojote Fresh, rekomenduoju išbandyti bent mažam side projektui. Net jei nuspręsite grįžti prie Next.js ar kito framework’o, patirtis su no-build architektūra duos naują perspektyvą. Kartais paprasčiausi sprendimai yra geriausi, ir Fresh tai puikiai demonstruoja.
Development turėtų būti malonumas, ne kova su tooling’u. Fresh grąžina tą malonumą – tiesiog rašote kodą ir kuriate produktus, be pašalinių triukšmų.
