Construirea SSG pe care mi l-am dorit întotdeauna: un sandwich de 11 ani, Vite și JAM

Publicat: 2022-03-10
Rezumat rapid ↬ În ianuarie 2020, Ben Holmes și-a propus să facă ceea ce aproape fiecare dezvoltator web face în fiecare an: să-și reconstruiască site-ul personal. În acest articol, el împărtășește povestea sa despre cum și-a propus să-și construiască propria conductă de construcție de la punctul zero absolut și a creat Slinkity.

Nu știu despre tine, dar am fost copleșit de toate instrumentele de dezvoltare web pe care le avem în aceste zile. Indiferent dacă vă plac Markdown, HTML simplu, React, Vue, Svelte, șabloane Pug, Ghidon, Vibranium — probabil că le puteți combina cu niște date CMS și puteți obține un cocktail static frumos de site.

Nu vă voi spune la ce instrumente de dezvoltare a interfeței de utilizare să folosiți, deoarece toate sunt grozave – în funcție de nevoile proiectului dumneavoastră. Această postare este despre găsirea generatorului de site static perfect pentru orice ocazie; ceva care ne permite să folosim șabloane fără JS, cum ar fi markdown, pentru a începe și să aducem „insule” de interactivitate bazată pe componente, după cum este necesar.

Am învățat în valoare de un an într-o singură postare aici. Nu numai că vom vorbi despre cod (alias duct-taping 11ty și Vite împreună), dar vom explora și de ce această abordare este atât de universală pentru problemele Jamstackiene. Vom atinge:

  • Două abordări ale generării de site-uri statice și de ce ar trebui să reducem decalajul;
  • În cazul în care limbile șablon precum Pug și Nunjucks încă se dovedesc utile;
  • Când cadrele componente precum React sau Svelte ar trebui să intre în joc;
  • Cum noua lume Vite, cu reîncărcare la cald, ne ajută să aducem interactivitate JS în HTML-ul nostru cu aproape zero configurații;
  • Cum completează acest lucru cascada de date a 11ty, aducând date CMS în orice cadru component sau șablon HTML pe care l-ați putea dori.

Așa că, fără alte prelungiri, iată povestea mea despre scenarii teribile de construcție, descoperiri în bundler și bandă adezivă care (în cele din urmă) mi-a dat SSG pe care mi l-am dorit întotdeauna: un sandviș de 11ty, Vite și Jam numit Slinkity!

O mare diviziune în generarea de site-uri statice

Înainte de a mă scufunda, vreau să discut despre ceea ce voi numi două „tabere” în generarea de site-uri statice.

În prima tabără, avem generatorul de site static „simplu”. Aceste instrumente nu aduc pachete JavaScript, aplicații cu o singură pagină și orice alte cuvinte la care ne-am așteptat. Aceștia găsesc doar elementele fundamentale ale Jamstack: extrageți date din orice blob JSON de CMS pe care îl preferați și introduceți acele date în șabloane HTML simple + CSS. Instrumente precum Jekyll, Hugo și 11ty domină această tabără, permițându-vă să transformați un director cu reduceri și fișiere lichide într-un site web complet funcțional. Beneficii cheie:

  • Curbă de învățare superficială
    Dacă știi HTML, ești gata!
  • Timp de construcție rapid
    Nu procesăm nimic complex, așa că fiecare rută se construiește într-o clipă.
  • Timp instantaneu pentru interactiv
    Nu există (sau foarte puțin) JavaScript de analizat pe client.

Acum, în a doua tabără, avem generatorul de site static „dinamic”. Acestea introduc cadre componente precum React, Vue și Svelte pentru a aduce interactivitate în Jamstack-ul dvs. Acestea îndeplinesc aceeași promisiune de bază de a combina datele CMS cu rutele site-ului dvs. în timpul construirii. Beneficii cheie:

  • Construit pentru interactivitate
    Ai nevoie de un carusel de imagini animate? Formular cu mai multe etape? Doar adăugați un nugget component de HTML, CSS și JS.
  • Conducerea statului
    Ceva de genul magazinelor React Context of Svelte permite partajarea fără probleme a datelor între rute. De exemplu, coșul de pe site-ul dvs. de comerț electronic.

Există avantaje distincte pentru oricare dintre abordări. Dar ce se întâmplă dacă alegi un SSG din prima tabără, cum ar fi Jekyll, doar pentru a realiza șase luni de la începutul proiectului tău că ai nevoie de o interactivitate componentă? Sau alegi ceva de genul NextJS pentru acele componente puternice, doar ca să te lupți cu curba de învățare a lui React sau cu KB inutile de JavaScript într-o postare de blog static?

În opinia mea, puține proiecte se potrivesc într-o tabără sau alta. Ele există într-un spectru, favorizând în mod constant noile seturi de caracteristici pe măsură ce nevoile unui proiect evoluează. Așadar, cum găsim o soluție care să ne permită să începem cu instrumentele simple ale primei tabere și să adăugăm treptat funcții din a doua atunci când avem nevoie de ele?

Ei bine, hai să ne plimbăm puțin prin călătoria mea de învățare.

Notă: dacă sunteți deja vândut pentru șabloane statice cu 11ty pentru a vă construi site-urile statice, nu ezitați să accesați explicația suculentă a codului.

Mai multe după săritură! Continuați să citiți mai jos ↓

Trecerea de la componente la șabloane și API-uri web

În ianuarie 2020, mi-am propus să fac ceea ce face aproape fiecare dezvoltator web în fiecare an: să-mi reconstruiesc site-ul personal. Dar de data asta avea să fie diferit. M-am provocat să construiesc un site cu mâinile legate la spate, fără cadre sau conducte permise!

Aceasta nu a fost o sarcină simplă ca adept al React. Dar cu capul sus, mi-am propus să-mi construiesc propria conductă de construcție de la punctul zero absolut. Există o mulțime de coduri prost scrise pe care le-aș putea împărtăși din v1 a site-ului meu personal... dar vă voi lăsa să faceți clic pe acest README dacă sunteți atât de curajos. În schimb, vreau să mă concentrez asupra lucrurilor de nivel superior pe care le-am învățat înfometându-mă de plăcerile mele vinovate JS.

Șabloanele merg mult mai departe decât ați putea crede

Am venit la acest proiect un junky JavaScript care se recuperează. Există câteva nevoi legate de site-uri statice pe care mi-a plăcut să folosesc cadre bazate pe componente pentru a le îndeplini:

  1. Dorim să defalcăm site-ul meu în componente reutilizabile ale interfeței de utilizare care pot accepta obiecte JS ca parametri (numite „recuzite”).
  2. Trebuie să luăm niște informații în timpul construcției pentru a pătrunde într-un loc de producție.
  3. Trebuie să generăm o mulțime de rute URL fie dintr-un director de fișiere, fie dintr-un obiect de conținut JSON gras.

Lista preluată din această postare de pe blogul meu personal.

Dar poate ați observat... niciuna dintre acestea nu are nevoie cu adevărat de JavaScript pentru clienți. Cadrele componente precum React sunt construite în principal pentru a gestiona preocupările legate de managementul statului, cum ar fi aplicația web Facebook care inspiră React în primul rând. Dacă doar vă descompuneți site-ul în componente de dimensiuni mici sau elemente de sistem de proiectare, șabloanele precum Pug funcționează și ele destul de bine!

Luați această bară de navigare de exemplu. În Pug, putem defini un „mixin” care primește date ca elemente de recuzită:

 // nav-mixins.pug mixin NavBar(links) // pug's version of a for loop each link in links a(href=link.href) link.text

Apoi, putem aplica acel mixin oriunde pe site-ul nostru.

 // index.pug // kinda like an ESM "import" include nav-mixins.pug html body +NavBar(navLinksPassedByJS) main h1 Welcome to my pug playground

Dacă „radăm” acest fișier cu niște date, vom obține un frumos index.html pe care îl vom oferi utilizatorilor noștri.

 const html = pug.render('/index.pug', { navLinksPassedByJS: [ { href: '/', text: 'Home' }, { href: '/adopt', text: 'Adopt a Pug' } ] }) // use the NodeJS filesystem helpers to write a file to our build await writeFile('build/index.html', html)

Sigur, acest lucru nu oferă detalii cum ar fi CSS cu scop pentru mixurile dvs. sau JavaScript cu stare acolo unde doriți. Dar are câteva beneficii foarte puternice față de ceva de genul React:

  1. Nu avem nevoie de pachete de lux pe care nu le înțelegem.
    Tocmai am scris acel apel pug.render de mână și avem deja prima rută a unui site gata de implementare.
  2. Nu livrăm niciun JavaScript utilizatorului final.
    Utilizarea React înseamnă adesea trimiterea unui timp de execuție mare pentru ca browserele oamenilor să ruleze. Apelând o funcție cum ar fi pug.render în timpul construirii, păstrăm toate JS-urile de partea noastră în timp ce trimitem un fișier .html curat la sfârșit.

Acesta este motivul pentru care cred că șabloanele sunt o „bază” excelentă pentru site-urile statice. Totuși, ar fi bine să poți ajunge la cadre de componente de care beneficiem cu adevărat de pe urma lor. Mai multe despre asta mai târziu.

Lectură recomandată : Cum să creați șabloane unghiulare mai bune cu Pug de Zara Cooper

Nu aveți nevoie de un cadru pentru a construi aplicații cu o singură pagină

În timp ce eram la asta, îmi doream și câteva tranziții sexy de pagină pe site-ul meu. Dar cum reușim așa ceva fără un cadru?

Fade încrucișată cu tranziție de ștergere verticală
Fade încrucișată cu tranziție de ștergere verticală. (Previzualizare mare)

Ei bine, nu putem face asta dacă fiecare pagină are propriul fișier .html . Întregul browser se reîmprospătează atunci când sărim de la un fișier HTML la altul, așa că nu putem avea acel efect de decolorare încrucișată (deoarece am arăta pe scurt ambele pagini una peste alta).

Avem nevoie de o modalitate de a „prelua” HTML și CSS pentru oriunde navigăm și de a le anima în vizualizare folosind JavaScript. Aceasta pare o treabă pentru aplicațiile cu o singură pagină! Am folosit un amestec simplu API de browser pentru asta:

  1. Interceptați toate clicurile pe link folosind un ascultător de evenimente.
  2. fetch API : Preluați toate resursele pentru orice pagină pe care doriți să o vizitați și obțineți fragmentul pe care vreau să-l animez pentru vizualizare: conținutul din afara barei de navigare (pe care vreau să rămână staționar în timpul animației).
  3. API pentru animații web : animați noul conținut în vizualizare ca cadru cheie.
  4. history API : Schimbați traseul afișat în bara de adrese URL a browserului dvs. utilizând window.history.pushState({}, 'new-route') . Altfel, se pare că nu ai părăsit pagina anterioară!

Pentru claritate, iată o ilustrare vizuală a conceptului de aplicație cu o singură pagină folosind o simplă căutare și înlocuire ( articol sursă ):

Procesul de rutare pas cu pas la client: 1. Se returnează un hamburger mediu rar, 2. Solicităm un burger bine făcut folosind API-ul fetch, 3. Masăm răspunsul, 4. Scoatem elementul „chiftă” și îl aplicăm la pagina noastră curentă.
Procesul de rutare pas cu pas la client: 1. Se returnează un hamburger mediu rar, 2. Solicităm un burger bine făcut folosind API-ul fetch, 3. Masăm răspunsul, 4. Scoatem elementul „chiftă” și îl aplicăm la pagina noastră curentă. (Previzualizare mare)

Notă : Puteți vizita și codul sursă de pe site-ul meu personal.

Sigur, o împerechere dintre React et al și biblioteca de animație aleasă de dvs. poate face acest lucru. Dar pentru un caz de utilizare la fel de simplu ca o tranziție de fade... API-urile web sunt destul de puternice de la sine. Și dacă doriți tranziții de pagină mai robuste pe șabloane statice precum Pug sau HTML simplu, biblioteci precum Swup vă vor servi bine.

Ce a adus 110 la masă

Mă simțeam destul de bine în legătură cu micul meu SSG în acest moment. Sigur că nu a putut prelua date CMS în timpul construirii și nu a acceptat diferite aspecte în funcție de pagină sau de director și nu a optimizat imaginile mele și nu a avut versiuni incrementale.

Bine, s-ar putea să am nevoie de ajutor.

Având în vedere toate învățările mele de la v1, am crezut că mi-am câștigat dreptul de a renunța la regula „fără crearea de conducte de la terți” și de a apela la instrumentele existente. Se pare că 11ty are o comoară de funcții de care am nevoie!

  • Preluarea datelor în timpul construirii folosind fișiere .11ydata.js ;
  • Date globale disponibile pentru toate șabloanele mele dintr-un folder _data ;
  • Reîncărcare la cald în timpul dezvoltării folosind browsersync;
  • Suport pentru transformări HTML fantastice;
  • … și nenumărate alte bunătăți.

Dacă ați încercat SSG-uri simple precum Jekyll sau Hugo, ar trebui să aveți o idee destul de bună despre cum funcționează 11ty. Doar diferenta? 11ty utilizează JavaScript continuu.

11ty acceptă practic fiecare bibliotecă de șabloane, așa că am fost bucuros să redau toate paginile mele Pug la rute .html . Opțiunea de înlănțuire a aspectului a ajutat și la configurarea mea falsă pentru o singură pagină. Aveam nevoie doar de un singur script pentru toate rutele mele și de un aspect „global” pentru a importa acel script:

 // _includes/base-layout.html <html> <body> <!--load every page's content between some body tags--> {{ content }} <!--and apply the script tag just below this--> <script src="main.js"></script> </body> </html> // random-blog-post.pug --- layout: base-layout --- article h2 Welcome to my blog p Have you heard the story of Darth Plagueis the Wise?

Atâta timp cât acel main.js interceptează toate linkurile pe care le-am explorat, avem tranziții de pagină!

Oh, și cascada de date

Așa că 11ty a ajutat la curățarea întregului cod de spaghete din v1. Dar a adus o altă piesă importantă: un API curat pentru a încărca date în machetele mele. Aceasta este pâinea și untul abordării Jamstack. În loc să preluați date în browser cu manipularea JavaScript + DOM, puteți:

  1. Preluați date în timpul construirii folosind Node.
    Acesta poate fi un apel către un API extern, un import local JSON sau YAML sau chiar conținutul altor rute de pe site-ul dvs. (imaginați-vă că actualizați un cuprins ori de câte ori sunt adăugate rute noi).
  2. Introduceți acele date în rutele dvs. Amintiți-vă că funcția .render am scris mai devreme:
 const html = pug.render('/index.pug', { navLinksPassedByJS: [ { href: '/', text: 'Home' }, { href: '/adopt', text: 'Adopt a Pug' } ] })

…dar în loc să apelăm pug.render cu datele noastre de fiecare dată, îi lăsăm pe 11ty să facă asta în culise.

Sigur, nu am avut multe date pentru site-ul meu personal. Dar m-am simțit grozav să creez un fișier .yaml pentru toate proiectele mele personale:

 # _data/works.yaml - title: Bits of Good Homepage hash: bog-homepage links: - href: https://bitsofgood.org text: Explore the live site - href: https://github.com/GTBitsOfGood/bog-web text: Scour the Svelt-ified codebase timeframe: May 2019 - present tags: - JAMstack - SvelteJS - title: Dolphin Audio Visualizer ...

Și accesați acele date prin orice șablon:

 // home.pug .project-carousel each work in works h3 #{title} p #{timeframe} each tag in tags ...

Venind din lumea „redării la client” cu aplicația create-react, aceasta a fost o revelație destul de mare. Nu mai trimiteți chei API sau blob-uri JSON mari către browser.

Am adăugat, de asemenea, câteva bunătăți pentru preluarea JavaScript și îmbunătățiri ale animației față de versiunea 1 a site-ului meu. Dacă ești curios, iată unde a fost README-ul meu în acest moment.

Eram fericit în acest moment, dar lipsea ceva

Am mers surprinzător de departe, abandonând componentele bazate pe JS și îmbrățișând șabloane (cu tranziții de pagină animate la pornire). Dar știu că asta nu îmi va satisface nevoile pentru totdeauna. Îți amintești de acea mare diviziune cu care ne-am dat drumul? Ei bine, în mod clar există încă acea râpă între configurația mea de construcție (firm în tabăra # 1) și paradisul interactivității JS (Următorul, SvelteKit și multe altele din tabăra #2). Spune că vreau să adaug:

  • un mod pop-up cu un comutator de deschidere/închidere,
  • un sistem de proiectare bazat pe componente, cum ar fi Material UI, complet cu stiluri definite,
  • o formă complexă în mai multe etape, poate condusă de o mașină de stat.

Dacă sunteți un purist simplu JS, probabil că aveți răspunsuri fără cadru la toate acele cazuri de utilizare. Dar există un motiv pentru care JQuery nu mai este norma! Există ceva atrăgător în crearea de componente discrete, ușor de citit ale HTML, stiluri cu scop și bucăți de variabile de „stare” JavaScript. React, Vue, Svelte etc. oferă atât de multe frumuseți pentru depanare și testare, încât manipularea directă a DOM nu se poate egala.

Deci, iată întrebarea mea de un milion de dolari:

Putem folosi șabloane HTML drepte pentru a începe și să adăugăm treptat componente React/Vue/Svelte acolo unde le dorim?

Răspunsul este da . Hai sa incercam.

11ty + Vite: A Match Made In Heaven ️

Iată visul pe care mi-l imaginez aici. Oriunde vreau să inserez ceva interactiv, vreau să las un mic steag în șablon pentru a „pune componenta X React aici”. Aceasta ar putea fi sintaxa shortcode-ului pe care o acceptă 11ty:

 # Super interesting programming tutorial Writing paragraphs has been fun, but that's no way to learn. Time for an interactive code example! {% react './components/FancyLiveDemo.jsx' %}

Dar amintiți-vă, 11ty dintr-o singură bucată (intenționat) evită: o modalitate de a vă grupa tot JavaScript. Venind din breasla OG a grupării, creierul tău probabil trece la construirea proceselor Webpack, Rollup sau Babel aici. Construiți un fișier mare de punct de intrare și scoateți un cod frumos optimizat, nu?

Ei bine, da, dar asta se poate implica destul de mult. Dacă folosim componente React, de exemplu, probabil că vom avea nevoie de niște încărcătoare pentru JSX, un proces Babel elegant pentru a transforma totul, un interpret pentru importurile de module SASS și CSS, ceva care să ajute la reîncărcarea live și așa mai departe.

Dacă ar exista un instrument care ar putea să vadă fișierele noastre .jsx și să știe exact ce să facă cu ele.

Intră: Vite

Vite s-a vorbit în oraș în ultima vreme. Este menit să fie instrumentul all-in-one pentru a construi aproape orice în JavaScript. Iată un exemplu pe care să-l încercați acasă. Să facem un director gol undeva pe mașina noastră și să instalăm câteva dependențe:

 npm init -y # Make a new package.json with defaults set npm i vite react react-dom # Grab Vite + some dependencies to use React

Acum, putem crea un fișier index.html care să servească drept „punct de intrare” al aplicației noastre. Vom rămâne destul de simplu:

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Document</title> </head> <body> <h1>Hello Vite! (wait is it pronounced "veet" or "vight"...)</h1> <div></div> </body> </html>

Singurul bit interesant este acel div id="root" din mijloc. Aceasta va fi rădăcina componentei noastre React într-un moment!

Dacă doriți, puteți porni serverul Vite pentru a vedea fișierul HTML simplu în browserul dvs. Doar rulați vite (sau npx vite dacă comanda nu a fost configurată în terminalul dvs.) și veți vedea această ieșire utilă:

 vite vX.XX dev server running at: > Local: http://localhost:3000/ > Network: use `--host` to expose ready in Xms.

La fel ca Browsersync sau alte servere de dezvoltare populare, numele fiecărui fișier .html corespunde unei rute pe serverul nostru. Deci, dacă am redenumit index.html în about.html , am vizita http://localhost:3000/about/ (da, veți avea nevoie de o bară oblică!)

Acum hai să facem ceva interesant. Pe lângă acel fișier index.html , adăugați o componentă de bază React de un fel. Vom folosi useState de la React aici pentru a demonstra interactivitatea:

 // TimesWeMispronouncedVite.jsx import React from 'react' export default function TimesWeMispronouncedVite() { const [count, setCount] = React.useState(0) return ( <div> <p>I've said Vite wrong {count} times today</p> <button onClick={() => setCount(count + 1)}>Add one</button> </div> ) }

Acum, să încărcăm acea componentă pe pagina noastră. Acesta este tot ce avem de adăugat la index.html -ul nostru:

 <!DOCTYPE html> ... <body> <h1>Hello Vite! (wait is it pronounced "veet" or "vight"...)</h1> <div></div> <!--Don't forget type="module"! This lets us use ES import syntax in the browser--> <script type="module"> // path to our component. Note we still use .jsx here! import Component from './TimesWeMispronouncedVite.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; const componentRoot = document.getElementById('root'); ReactDOM.render(React.createElement(Component), componentRoot); </script> </body> </html>

Da, asta e. Nu este nevoie să transformăm noi înșine fișierul nostru .jsx într-un fișier .js pregătit pentru browser! Oriunde Vite vede un import .jsx , va converti automat acel fișier în ceva ce browserul poate înțelege. Nu există nici măcar un folder dist sau build atunci când lucrezi în dezvoltare; Vite procesează totul din mers - complet cu reîncărcarea la cald a modulului de fiecare dată când salvăm modificările.

Bine, deci avem un instrument de construcție incredibil de capabil. Cum putem aduce asta în cele 110 șabloane ale noastre?

Running Vite Alături de 11ty

Înainte de a trece la lucrurile bune, să discutăm despre rularea 11ty și Vite unul lângă altul. Continuați și instalați 11ty ca dependență de dezvoltare în același director de proiect din ultima secțiune:

 npm i -D @11ty/eleventy # yes, it really is 11ty twice

Acum să facem o mică verificare înainte de zbor pentru a vedea dacă 11ty funcționează. Pentru a evita orice confuzie, vă sugerez:

  1. Ștergeți acel fișier index.html de mai devreme;
  2. Mutați acel TimesWeMispronouncedVite.jsx într-un director nou. Să zicem, components/ ;
  3. Creați un folder src în care să locuiască site-ul nostru;
  4. Adăugați un șablon în acel director src pentru ca 11ty să îl proceseze.

De exemplu, un fișier blog-post.md cu următorul conținut:

 # Hello world! It's markdown here

Structura proiectului dvs. ar trebui să arate cam așa:

 src/ blog-post.md components/ TimesWeMispronouncedVite.jsx

Acum, rulați 11ty de pe terminalul dvs. astfel:

 npx eleventy --input=src

Dacă totul merge bine, ar trebui să vedeți o ieșire de compilare ca aceasta:

 _site/ blog-post/ index.html

Unde _site este directorul nostru de ieșire implicit, iar blog-post/index.html este fișierul nostru de reducere, convertit frumos pentru navigare.

În mod normal, am rula npx eleventy --serve pentru a porni un server de dezvoltare și a vizita acea pagină /blog-post . Dar acum folosim Vite pentru serverul nostru de dezvoltare! Scopul aici este de a:

  1. Pune unsprezece să construiască reducerile noastre, Pug, nunjucks și multe altele în directorul _site .
  2. Indicați Vite în același director _site , astfel încât să poată procesa componentele React, importurile de stil fancy și alte lucruri pe care 11ty nu le-a preluat.

Deci, un proces de construire în doi pași, cu 11ty predarea Vite. Iată comanda CLI de care veți avea nevoie pentru a porni 11ty și Vite în modul „watch” simultan:

 (npx eleventy --input=src --watch) & npx vite _site

De asemenea, puteți rula aceste comenzi în două terminale separate pentru o depanare mai ușoară.

Cu ceva noroc, ar trebui să puteți vizita http://localhost:3000/blog-post/ (din nou, nu uitați slash-ul final!) pentru a vedea acel fișier Markdown procesat.

Hidratare parțială cu coduri scurte

Să facem o scurtă prezentare a codurilor scurte. Este timpul să revizuiți sintaxa de mai devreme:

 {% react '/components/TimesWeMispronouncedVite.jsx' %}

Pentru cei care nu sunt familiarizați cu codurile scurte: acestea sunt aproximativ la fel ca un apel de funcție, în care funcția returnează un șir de HTML pentru a glisa în pagina dvs. „Anatomia” codului nostru scurt este:

  • {% … %}
    Wrapper care indică începutul și sfârșitul codului scurt.
  • react
    Numele funcției noastre de cod scurt îl vom configura într-un moment.
  • '/components/TimesWeMispronouncedVite.jsx'
    Primul (și singurul) argument al funcției noastre de cod scurt. Puteți avea câte argumente doriți.

Să conectăm primul nostru cod scurt! Adăugați un fișier .eleventy.js la baza proiectului dvs. și adăugați această intrare de configurare pentru codul nostru scurt de react :

 // .eleventy.js, at the base of the project module.exports = function(eleventyConfig) { eleventyConfig.addShortcode('react', function(componentPath) { // return any valid HTML to insert return `<div>This is where we'll import ${componentPath}</div>` }) return { dir: { // so we don't have to write `--input=src` in our terminal every time! input: 'src', } } }

Acum, să condimentăm blog-post.md cu noul nostru shortcode. Lipiți acest conținut în fișierul nostru de reducere:

 # Super interesting programming tutorial Writing paragraphs has been fun, but that's no way to learn. Time for an interactive code example! {% react '/components/TimesWeMispronouncedVite.jsx' %}

Și dacă rulați un npx eleventy , ar trebui să vedeți această ieșire în directorul dvs. _site sub /blog-post/index.html :

 <h1>Super interesting programming tutorial</h1> <p>Writing paragraphs has been fun, but that's no way to learn. Time for an interactive code example!</p> <div>This is where we'll import /components/TimesWeMispronouncedVite.jsx</div>

Scrierea codului scurt al componentei noastre

Acum să facem ceva util cu acel shortcode. Vă amintiți acea etichetă de script pe care am scris-o în timp ce încercam Vite? Ei bine, putem face același lucru în codul nostru scurt! De data aceasta vom folosi argumentul componentPath pentru a genera importul, dar restul rămâne aproape la fel:

 // .eleventy.js module.exports = function(eleventyConfig) { let idCounter = 0; // copy all our /components to the output directory // so Vite can find them. Very important step! eleventyConfig.addPassthroughCopy('components') eleventyConfig.addShortcode('react', function (componentPath) { // we'll use idCounter to generate unique IDs for each "root" div // this lets us use multiple components / shortcodes on the same page idCounter += 1; const componentRootId = `component-root-${idCounter}` return ` <div></div> <script type="module"> // use JSON.stringify to // 1) wrap our componentPath in quotes // 2) strip any invalid characters. Probably a non-issue, but good to be cautious! import Component from ${JSON.stringify(componentPath)}; import React from 'react'; import ReactDOM from 'react-dom'; const componentRoot = document.getElementById('${componentRootId}'); ReactDOM.render(React.createElement(Component), componentRoot); </script> ` }) eleventyConfig.on('beforeBuild', function () { // reset the counter for each new build // otherwise, it'll count up higher and higher on every live reload idCounter = 0; }) return { dir: { input: 'src', } } }

Acum, un apel la codul nostru scurt (ex. {% react '/components/TimesWeMispronouncedVite.jsx' %} ) ar trebui să scoată ceva de genul acesta:

 <div></div> <script type="module"> import Component from './components/FancyLiveDemo.jsx'; import React from 'react'; import ReactDOM from 'react-dom'; const componentRoot = document.getElementById('component-root-1'); ReactDOM.render(React.createElement(Component), componentRoot); </script>

Vizitând serverul nostru de dezvoltare folosind (npx eleventy --watch) & vite _site , ar trebui să găsim un element de contor frumos pe care se poate face clic.

Buzzword Alert — Hidratarea parțială și arhitectura insulelor

Tocmai am demonstrat „arhitectura insulelor” în cea mai simplă formă. Aceasta este ideea că arborii noștri de componente interactive nu trebuie să consume întregul site web. În schimb, putem învârti mini-copaci, sau „insule”, în aplicația noastră, în funcție de locul în care avem nevoie de acea interactivitate. Aveți o pagină de destinație de bază cu linkuri fără nicio stare de gestionat? Grozav! Nu este nevoie de componente interactive. Dar aveți un formular în mai mulți pași care ar putea beneficia de biblioteca X React? Nici o problemă. Folosiți tehnici precum codul scurt de react pentru a crea o insulă Form.jsx .

Acest lucru merge mână în mână cu ideea de „hidratare parțială”. Probabil că ați auzit termenul „hidratare” dacă lucrați cu SSG-uri componente, cum ar fi NextJS sau Gatsby. Pe scurt, este o modalitate de a:

  1. Redați mai întâi componentele în HTML static.
    Acest lucru oferă utilizatorului ceva de văzut atunci când vă vizitează inițial site-ul web.
  2. „Hidratați” acest HTML cu interactivitate.
    Aici ne conectăm cârligele de stat și redarele pentru a face ca clicurile pe buton să declanșeze ceva.

Acest punch 1-2 face cadrele bazate pe JS viabile pentru site-uri statice. Atâta timp cât utilizatorul are ceva de vizualizat înainte de finalizarea analizei JavaScript, veți obține un scor decent la acele valori de far.

Ei bine, până nu o faci. Poate fi costisitor să „hidratezi” un întreg site, deoarece vei avea nevoie de un pachet JavaScript gata să proceseze fiecare element DOM . Dar tehnica noastră de coduri scurte scrappy nu acoperă întreaga pagină! În schimb, hidratăm „parțial” conținutul care este acolo, inserând componente doar acolo unde este necesar.

Nu vă faceți griji, există un plugin pentru toate acestea: Slinkity

Să recapitulăm ceea ce am descoperit aici:

  1. Vite este un bundler incredibil de capabil care poate procesa majoritatea tipurilor de fișiere ( jsx , vue și svelte , pentru a numi câteva) fără configurare suplimentară.
  2. Shortcode-urile sunt o modalitate ușoară de a insera bucăți de HTML în șabloanele noastre, în stil component.
  3. Putem folosi coduri scurte pentru a reda pachete JS dinamice, interactive oriunde dorim, folosind hidratarea parțială.

Deci, cum rămâne cu versiunile optimizate de producție? Încărcați corect stilurile cu scop? La naiba, folosind .jsx pentru a crea pagini întregi? Ei bine, am combinat toate acestea (și multe altele!) într-un proiect numit Slinkity. Sunt încântat să văd primirea caldă a comunității față de proiect și mi-ar plăcea ca tu, dragă cititor, să-i dai o învârtire!

Încercați ghidul de pornire rapidă

Astro este și el destul de grozav

Cititorii cu ochii pe tehnologia de ultimă oră s-au gândit probabil la Astro cel puțin o dată până acum. Și nu te pot învinovăți! Este construit cu un obiectiv destul de similar în minte: începeți cu HTML simplu și inserați componente cu stare oriunde aveți nevoie de ele. La naiba, vă vor permite chiar să începeți să scrieți componente React în componentele Vue sau Svelte în fișierele șablon HTML! Este ca MDX Xtreme edition.

Există totuși un cost destul de mare pentru abordarea lor: trebuie să vă rescrieți aplicația de la zero. Acest lucru înseamnă un nou format de șablon bazat pe JSX (cu care s-ar putea să nu vă simțiți confortabil), o conductă de date cu totul nouă, căreia îi lipsesc câteva detalii în acest moment și probleme generale pe măsură ce rezolvă problemele.

Dar învârtirea unui cocktail 11ty + Vite cu un instrument precum Slinkity? Ei bine, dacă aveți deja un site de 110 de ani, Vite ar trebui să se instaleze fără rescriere, iar codurile scurte ar trebui să acopere multe dintre aceleași cazuri de utilizare ca fișierele .astro . Recunosc că este departe de a fi perfect acum. Dar hei, a fost util până acum și cred că este o alternativă destul de puternică dacă doriți să evitați rescrierile la nivel de site!

Încheierea

Acest experiment Slinkity mi-a satisfăcut destul de bine nevoile până acum (și și câțiva dintre voi!). Simțiți-vă liber să utilizați orice stivă care funcționează pentru JAM-ul dvs. Sunt doar încântat să vă împărtășesc rezultatele anului meu de desfrânare a instrumentelor de construcție și sunt atât de entuziasmat să văd cum putem depăși marea diviziune Jamstack.

Lectură suplimentară

Doriți să vă scufundați mai adânc în hidratarea parțială, sau ESM, sau SSG în general? Verificați acestea:

  • Arhitectura Insulelor
    Această postare pe blog de la Jason Format a dat startul unei discuții despre „insule” și „hidratare parțială” în dezvoltarea web. Este plin de diagrame utile și de filozofia din spatele ideii.
  • Simplificați-vă statica cu un generator de site static personalizat
    Un alt articol SmashingMag care vă ghidează prin crearea de la zero a creatorilor de site-uri bazate pe Node. A fost o mare inspirație pentru mine!
  • Cum modulele ES au redefinit dezvoltarea web
    O postare personală despre modul în care modulele ES au schimbat jocul de dezvoltare web. Acest lucru se scufundă puțin mai departe în „atunci și acum” a sintaxei de import pe web.
  • O introducere în componentele web
    O prezentare excelentă despre componentele web, cum funcționează DOM-ul umbră și unde componentele web se dovedesc utile. Am folosit acest ghid pentru a aplica componente personalizate propriului cadru!