Simplificați-vă stiva cu un generator de site static personalizat

Publicat: 2022-03-10
Rezumat rapid ↬ În dezvoltarea modernă, există atât de multe instrumente grozave pentru dezvoltarea site-urilor web, dar de multe ori acestea sunt mai mult decât ceea ce este necesar pentru un anumit proiect. În acest articol, vom explora cum să luăm o pagină HTML umilă și să facem conținutul acesteia editabil într-un CMS fără cadre și fără JavaScript la nivel client.

Odată cu apariția mișcării Jamstack, site-urile deservite static au devenit din nou furori. Majoritatea dezvoltatorilor care servesc HTML static nu creează HTML nativ. Pentru a avea o experiență solidă de dezvoltator, apelăm adesea la instrumente numite Static Site Generators (SSG).

Aceste instrumente vin cu multe caracteristici care fac crearea de site-uri statice la scară largă plăcută. Indiferent dacă oferă simple cârlige în API-uri terțe, cum ar fi sursele de date Gatsby, sau oferă o configurație aprofundată, cum ar fi colecția imensă de motoare de șabloane 11ty, există ceva pentru toată lumea în generarea de site-uri statice.

Deoarece aceste instrumente sunt create pentru diverse cazuri de utilizare, ele trebuie să aibă o mulțime de caracteristici. Aceste caracteristici le fac puternice. De asemenea, le fac destul de complexe și opace pentru dezvoltatorii noi. În acest articol, vom duce SSG-ul până la componentele sale de bază și vom crea propriul nostru.

Ce este un generator de site static?

În esență, un generator de site static este un program care efectuează o serie de transformări pe un grup de fișiere pentru a le converti în active statice, cum ar fi HTML. Ce fel de fișiere poate accepta, cum le transformă și ce tipuri de fișiere ies diferențiază SSG-urile.

Jekyll, un SSG timpuriu și încă popular, folosește Ruby pentru a procesa șabloanele Liquid și fișierele de conținut Markdown în HTML.

Gatsby folosește React și JSX pentru a transforma componente și conținut în HTML. Apoi face un pas mai departe și creează o aplicație cu o singură pagină care poate fi servită static.

11ty redă HTML din motoarele de șabloane, cum ar fi Liquid, Handlebars, Nunjucks sau literale șabloane JavaScript.

Fiecare dintre aceste platforme are funcții suplimentare pentru a ne ușura viața. Ele oferă tematică, construiește conducte, arhitectură plugin și multe altele. Cu fiecare caracteristică suplimentară vine mai multă complexitate, mai multă magie și mai multe dependențe. Sunt caracteristici importante, desigur, dar nu orice proiect are nevoie de ele.

Între aceste trei SSG-uri diferite, putem vedea o altă temă comună: date + șabloane = site final. Aceasta pare să fie funcționalitatea de bază a site-urilor statice generatoare. Aceasta este funcționalitatea pe care ne vom baza SSG-ul.

În esență, un generator de site static este un program care efectuează o serie de transformări pe un grup de fișiere pentru a le converti în active statice, cum ar fi HTML.

Noul nostru pachet tehnologic al generatorului de site statice: ghidon, Sanity.io și Netlify

Pentru a construi SSG-ul nostru, vom avea nevoie de un motor șablon, o sursă de date și o gazdă care să poată rula SSG-ul nostru și să ne construiască site-ul. Mulți generatori folosesc Markdown ca sursă de date, dar dacă am face un pas mai departe și am conecta în mod nativ SSG-ul nostru la un CMS?

  • Sursa datelor: Sanity.io
  • Preluare și modelare de date: Node și ghidon
  • Gazdă și implementare: Netlify.

Cerințe preliminare

  • NodeJS instalat
  • Contul Sanity.io
  • Cunoașterea Git
  • Cunoștințe de bază despre linia de comandă
  • Cunoștințe de bază despre implementare în servicii precum Netlify.

Notă : Pentru a urma, puteți găsi codul în acest depozit pe GitHub.

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

Configurarea structurii documentelor noastre în HTML

Pentru a începe structura documentului, vom scrie HTML simplu. Nu este nevoie să complici lucrurile încă.

În structura proiectului nostru, trebuie să creăm un loc unde să trăiască fișierele noastre sursă. În acest caz, vom crea un director src și vom pune index.html în interior.

În index.html , vom schița conținutul pe care îl dorim. Aceasta va fi o pagină relativ simplă.

 <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>Title of the page!</title> </head> <body> <h1>The personal homepage of Bryan Robinson</h1> <p>Some pagraph and rich text content next</p> <h2>Bryan is on the internet</h2> <ul> <li><a href="linkURL">List of links</a></li> </ul> </body> </html>

Să rămânem simplu. Vom începe cu un h1 pentru pagina noastră. Vom urma asta cu câteva paragrafe de informații biografice și vom ancora pagina cu o listă de link-uri pentru a vedea mai multe.

Transformați HTML-ul nostru într-un șablon care acceptă date

După ce avem structura noastră de bază, trebuie să setăm un proces pentru a combina acest lucru cu o anumită cantitate de date. Pentru a face acest lucru, vom folosi motorul de șablon Ghidon.

În esență, Handlebars preia un șir asemănător HTML, inserează date prin regulile definite în document și apoi scoate un șir HTML compilat.

Pentru a folosi Handlebars, va trebui să inițializam pachetul.json și să instalăm pachetul.

Rulați npm init -y pentru a crea structura unui fișier package.json cu conținut implicit. Odată ce avem acest lucru, putem instala Ghidon.

 npm install handlebars

Scriptul nostru de compilare va fi un script Node. Acesta este scriptul pe care îl vom folosi local pentru a construi, dar și ceea ce furnizorul și gazda noastră de implementare vor folosi pentru a construi HTML-ul nostru pentru site-ul live.

Pentru a începe scriptul, vom crea un fișier index.js și vom avea nevoie de două pachete în partea de sus. Primul este Handlebars, iar al doilea este un modul implicit în Node pentru accesarea sistemului de fișiere curent.

 const fs = require('fs'); const Handlebars = require('handlebars');

Vom folosi modulul fs pentru a accesa fișierul sursă, precum și pentru a scrie într-un fișier de distribuție. Pentru a începe construcția noastră, vom crea o funcție main pentru ca fișierul nostru să ruleze atunci când este apelat și o funcție buildHTML pentru a combina datele și marcajul.

 function buildHTML(filename, data) { const source = fs.readFileSync(filename,'utf8').toString(); const template = Handlebars.compile(source); const output = template(data); return output } async function main(src, dist) { const html = buildHTML(src, { "variableData": "This is variable data"}); fs.writeFile(destination, html, function (err) { if (err) return console.log(err); console.log('index.html created'); }); } main('./src/index.html', './dist/index.html');

Funcția main() acceptă două argumente: calea către șablonul nostru HTML și calea pe care vrem să trăiască fișierul nostru construit. În funcția noastră principală, rulăm buildHTML pe calea sursă a șablonului cu o anumită cantitate de date.

Funcția de compilare convertește documentul sursă într-un șir și transmite acel șir la Handlebars. Handlebars compilează un șablon folosind acel șir. Apoi ne transmitem datele în șablonul compilat, iar Handlebars redă un șir HTML nou, înlocuind orice variabilă sau logica șablonului cu datele de ieșire.

Returnăm acel șir în funcția noastră main și folosim metoda writeFile furnizată de modulul de sistem de fișiere al lui Node pentru a scrie noul fișier în locația specificată, dacă directorul există.

Pentru a preveni o eroare, adăugați un director dist în proiectul dvs. cu un fișier .gitkeep în el. Nu vrem să comitem fișierele noastre construite (procesul nostru de compilare va face acest lucru), dar vom dori să ne asigurăm că avem acest director pentru scriptul nostru.

Înainte de a crea un CMS pentru a gestiona această pagină, să confirmăm că funcționează. Pentru a testa, vom modifica documentul HTML pentru a folosi datele pe care tocmai le-am transmis în el. Vom folosi sintaxa variabilei Handlebars pentru a include conținutul variableData .

 <h1>{{ variableData }}</h1>

Acum că HTML-ul nostru are o variabilă, suntem gata să rulăm scriptul nostru nod.

 node index.js

Odată ce scriptul se termină, ar trebui să avem un fișier la /dist/index.html . Dacă citim că deschidem acest lucru într-un browser, vom vedea marcarea noastră redată, dar și șirul nostru „Aceasta este date variabile”.

Conectarea la un CMS

Avem o modalitate de a pune datele împreună cu un șablon, acum avem nevoie de o sursă pentru datele noastre. Această metodă va funcționa cu orice sursă de date care are un API. Pentru această demonstrație, vom folosi Sanity.io.

Sanity este o sursă de date API care tratează conținutul ca date structurate. Au un sistem de gestionare a conținutului open-source pentru a face gestionarea și adăugarea datelor mai convenabile atât pentru editori, cât și pentru dezvoltatori. CMS-ul este ceea ce se numește adesea CMS „fără cap”. În loc de un sistem tradițional de management în care datele sunt strâns legate de prezentarea dvs., un CMS fără cap creează un strat de date care poate fi consumat de orice front-end sau serviciu (și posibil de multe în același timp).

Sanity este un serviciu plătit, dar au un plan „Standard” care este gratuit și are toate caracteristicile de care avem nevoie pentru un site ca acesta.

Configurarea Sanity

Cea mai rapidă modalitate de a începe și rula cu un nou proiect Sanity este să folosești Sanity CLI. Vom începe prin a-l instala la nivel global.

 npm install -g @sanity/cli

CLI ne oferă acces la un grup de asistenți pentru gestionarea, implementarea și crearea. Pentru a începe lucrurile, vom rula sanity init . Acest lucru ne va conduce printr-un chestionar pentru a ajuta la pornirea Studioului nostru (ceea ce Sanity numește CMS-ul lor open-source).

 Select a Project to Use: Create new project HTML CMS Use the default dataset configuration? Y // this creates a "Production" dataset Project output path: studio // or whatever directory you'd like this to live in Select project template Clean project with no predefined schemas

Acest pas va crea un nou proiect și un set de date în contul dvs. Sanity, va crea o versiune locală de Studio și va lega datele și CMS-ul împreună pentru dvs. În mod implicit, directorul studio va fi creat în rădăcina proiectului nostru. În proiectele la scară mai mare, poate doriți să configurați aceasta ca un depozit separat. Pentru acest proiect, este bine să păstrați acest lucru legat împreună.

Pentru a rula Studioul nostru local, vom schimba directorul în directorul studio și vom rula sanity start . Aceasta va rula Studio la localhost:3333 . Când vă conectați, vi se va afișa un ecran pentru a vă anunța că aveți „Schema goală”. Cu asta, este timpul să adăugăm schema noastră, care este modul în care datele noastre vor fi structurate și editate.

Crearea unei scheme de sanitate

Modul în care creați documente și câmpuri în Sanity Studio este să creați scheme în fișierul schemas/schema.js .

Pentru site-ul nostru, vom crea un tip de schemă numit „Despre detalii”. Schema noastră va curge din HTML-ul nostru. În general, am putea face din cea mai mare parte a paginii noastre web un singur câmp de text îmbogățit, dar este o practică bună să ne structuram conținutul într-un mod decuplat. Acest lucru oferă o mai mare flexibilitate în ceea ce privește modul în care am putea dori să folosim aceste date în viitor.

Pentru pagina noastră web, dorim un set de date care să includă următoarele:

  • Titlu
  • Numele complet
  • Biografie (cu editare de text bogat)
  • O listă de site-uri web cu un nume și o adresă URL.

Pentru a defini acest lucru în schema noastră, creăm un obiect pentru documentul nostru și definim câmpurile acestuia. O listă adnotată a conținutului nostru cu type său de câmp:

  • Titlu — șir
  • Nume complet — șir
  • Biografie - o serie de „blocuri”
  • Listă de site-uri web — matrice de obiecte cu câmpuri de nume și șir URL.
 types: schemaTypes.concat([ /* Your types here! */ { title: "About Details", name: "about", type: "document", fields: [ { name: 'title', type: 'string' }, { name: 'fullName', title: 'Full Name', type: 'string' }, { name: 'bio', title: 'Biography', name: 'content', type: 'array', of: [ { type: 'block' } ] }, { name: 'externalLinks', title: 'Social media and external links', type: 'array', of: [ { type: 'object', fields: [ { name: 'text', title: 'Link text', type: 'string' }, { name: 'href', title: 'Link url', type: 'string' } ] } ] } ] } ])

Adăugați acest lucru la tipurile dvs. de schemă, salvați și Studioul dvs. vă va recompila și vă va prezenta primele documente. De aici, vom adăuga conținutul nostru în CMS creând un nou document și completând informațiile.

Structurarea conținutului într-un mod reutilizabil

În acest moment, s-ar putea să vă întrebați de ce avem un „nume complet” și un „titlu”. Acest lucru se datorează faptului că dorim ca conținutul nostru să aibă potențialul de a fi multifuncțional. Prin includerea unui câmp de nume în loc de a include numele doar în titlu, oferim acestor date mai multă utilizare. Apoi putem folosi informațiile din acest CMS pentru a alimenta și o pagină de CV sau un PDF. Câmpul biografiei ar putea fi utilizat în mod programatic în alte sisteme sau site-uri web. Acest lucru ne permite să avem o singură sursă de adevăr pentru mare parte din acest conținut, în loc să fim dictați de cazul direct de utilizare al acestui site particular.

Introducerea datelor noastre în proiectul nostru

Acum că ne-am făcut datele disponibile printr-un API, să le introducem în proiectul nostru.

Instalați și configurați clientul JavaScript Sanity

În primul rând, avem nevoie de acces la datele din Node. Putem folosi clientul JavaScript Sanity pentru a crea acea conexiune.

 npm install @sanity/client

Aceasta va prelua și instala setul SDK JavaScript. De aici, trebuie să-l configuram pentru a prelua date din proiectul pe care l-am configurat mai devreme. Pentru a face asta, vom configura un script utilitar în /utils/SanityClient.js . Oferim SDK-ului ID-ul proiectului și numele setului de date și suntem gata să-l folosim în scriptul nostru principal.

 const sanityClient = require('@sanity/client'); const client = sanityClient({ projectId: '4fs6x5jg', dataset: 'production', useCdn: true }) module.exports = client;

Preluarea datelor noastre cu GROQ

Înapoi în fișierul nostru index.js , vom crea o nouă funcție pentru a ne prelua datele. Pentru a face acest lucru, vom folosi limbajul de interogare nativ al lui Sanity, GROQ open-source.

Vom construi interogarea într-o variabilă și apoi vom folosi clientul pe care l-am configurat pentru a prelua datele pe baza interogării. În acest caz, construim un obiect cu o proprietate numită about . În acest obiect, dorim să returnăm datele pentru documentul nostru specific. Pentru a face acest lucru, interogăm pe baza documentului _id care este generat automat atunci când creăm documentul nostru.

Pentru a găsi _id -ul documentului, navigăm la documentul în Studio și fie îl copiam de la adresa URL, fie trecem în modul „Inspectare” pentru a vedea toate datele de pe document. Pentru a intra în Inspect, fie faceți clic pe meniul „kabob” din dreapta sus, fie utilizați comanda rapidă Ctrl + Alt + I. Această vizualizare va lista toate datele din acest document, inclusiv _id -ul nostru. Sanity va returna o serie de obiecte document, așa că, din motive de simplitate, vom returna a 0th -a intrare.

Apoi trecem interogarea la metoda de fetch a clientului nostru Sanity și va returna un obiect JSON cu toate datele din documentul nostru. În această demonstrație, returnarea tuturor datelor nu este mare lucru. Pentru implementări mai mari, GROQ permite o „proiecție” opțională pentru a returna numai câmpurile explicite pe care le doriți.

 const client = require('./utils/SanityClient') // at the top of the file // ... async function getSanityData() { const query = `{ "about": *[_id == 'YOUR-ID-HERE'][0] }` let data = await client.fetch(query); }

Conversia câmpului text îmbogățit în HTML

Înainte de a putea returna datele, trebuie să facem o transformare în câmpul nostru de text îmbogățit. În timp ce multe CMS-uri folosesc editori de text îmbogățit care returnează HTML direct, Sanity utilizează o specificație open-source numită Text portabil. Textul portabil returnează o serie de obiecte (gândiți-vă la textul îmbogățit ca o listă de paragrafe și alte blocuri media) cu toate datele despre stilul textului îmbogățit și proprietăți precum linkuri, note de subsol și alte adnotări. Acest lucru permite ca textul să fie mutat și utilizat în sisteme care nu acceptă HTML, cum ar fi asistenții vocali și aplicațiile native.

Pentru cazul nostru de utilizare, înseamnă că trebuie să transformăm obiectul în HTML. Există module NPM care pot fi folosite pentru a converti textul portabil în diverse utilizări. În cazul nostru vom folosi un pachet numit block-content-to-html.

 npm install @sanity/block-content-to-html

Acest pachet va reda toate markupurile implicite din editorul de text îmbogățit. Fiecare tip de stil poate fi suprascris pentru a se conforma cu orice marcaj de care aveți nevoie pentru cazul dvs. de utilizare. În acest caz, vom lăsa pachetul să facă treaba pentru noi.

 const blocksToHtml = require('@sanity/block-content-to-html'); // Added to the top async function getSanityData() { const query = `{ "about": *[_type == 'about'][0] }` let data = await client.fetch(query); data.about.content = blocksToHtml({ blocks: data.about.content }) return await data }

Utilizarea conținutului de la Sanity.io în ghidon

Acum că datele sunt într-o formă pe care o putem folosi, vom transmite aceasta funcției noastre buildHTML ca argument de date.

 async function main(src, dist) { const data = await getSanityData(); const html = buildHTML(src, data) fs.writeFile(dist, html, function (err) { if (err) return console.log(err); console.log('index.html created'); }); }

Acum, ne putem schimba HTML pentru a folosi noile date. Vom folosi mai multe apeluri variabile în șablonul nostru pentru a extrage majoritatea datelor.

Pentru a reda variabila noastră de content text îmbogățit, va trebui să adăugăm un strat suplimentar de acolade variabilei noastre. Acest lucru va spune Handlebars-ului să redea HTML-ul în loc să afișeze HTML-ul ca șir.

Pentru matricea noastră externalLinks , va trebui să folosim funcționalitatea de buclă încorporată din Handlebars pentru a afișa toate linkurile pe care le-am adăugat la Studioul nostru.

 <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>{{ about.title }}</title> </head> <body> <h1>The personal homepage of {{ about.fullName }}</h1> {{{ about.content }}} <h2>Bryan is on the internet</h2> <ul> {{#each about.externalLinks }} <li><a href="{{ this.href }}">{{ this.text }}</a></li> {{/each}} </ul> </body> </html>

Configurarea implementării

Să primim asta live. Avem nevoie de două componente pentru a face acest lucru. În primul rând, dorim o gazdă statică care să ne construiască fișierele pentru noi. În continuare, trebuie să declanșăm o nouă versiune a site-ului nostru atunci când conținutul este modificat în CMS-ul nostru.

Implementarea în Netlify

Pentru găzduire, vom folosi Netlify. Netlify este o gazdă de site static. Servește active statice, dar are caracteristici suplimentare care vor face site-ul nostru să funcționeze fără probleme. Au o infrastructură de implementare încorporată care poate rula scriptul nostru nod, webhook-uri pentru a declanșa versiuni și un CDN distribuit la nivel global pentru a se asigura că pagina noastră HTML este difuzată rapid.

Netlify poate urmări depozitul nostru pe GitHub și poate crea o versiune bazată pe o comandă pe care o putem adăuga în tabloul de bord.

Mai întâi, va trebui să împingem acest cod în GitHub. Apoi, în tabloul de bord Netlify, trebuie să conectăm noul depozit la un nou site în Netlify.

Odată ce este conectat, trebuie să îi spunem lui Netlify cum să ne construim proiectul. În tabloul de bord, ne vom îndrepta către Setări > Build & Deploy > Build Settings. În această zonă, trebuie să ne schimbăm „comanda Build” la „node index.js” și „Publish directory” la „./dist”.

Când Netlify construiește site-ul nostru, va rula comanda noastră și apoi va verifica conținutul din folderul pe care îl listăm și va publica conținutul din interior.

Configurarea unui webhook

De asemenea, trebuie să îi spunem lui Netlify să publice o nouă versiune atunci când cineva actualizează conținutul. Pentru a face asta, vom configura un Webhook pentru a notifica Netlify că avem nevoie de reconstruire a site-ului. Un Webhook este o adresă URL care poate fi accesată programatic de un alt serviciu (cum ar fi Sanity) pentru a crea o acțiune în serviciul de origine (în acest caz Netlify).

Putem configura un anume „Build hook” în tabloul de bord Netlify la Setări > Build & Deploy > Build hooks. Adaugă un cârlig, dă-i un nume și salvează. Aceasta va oferi o adresă URL care poate fi utilizată pentru a declanșa de la distanță o construcție în Netlify.

Apoi, trebuie să îi spunem Sanity să facă o solicitare la această adresă URL atunci când publicați modificări.

Putem folosi Sanity CLI pentru a realiza acest lucru. În interiorul directorului nostru /studio , putem rula sanity hook create pentru a vă conecta. Comanda va cere un nume, un set de date și o adresă URL. Numele poate fi orice doriți, setul de date ar trebui să fie de production pentru produsul nostru, iar adresa URL ar trebui să fie adresa URL furnizată de Netlify.

Acum, ori de câte ori publicăm conținut în Studio, site-ul nostru web va fi actualizat automat. Nu este necesar nici un cadru.

  • Codul poate fi găsit în acest depozit GitHub →

Pasii urmatori

Acesta este un exemplu foarte mic de ceea ce puteți face atunci când vă creați propriul instrument. În timp ce mai multe SSG-uri complete ar putea fi ceea ce aveți nevoie pentru majoritatea proiectelor, crearea propriului dvs. mini-SSG vă poate ajuta să înțelegeți mai multe despre ce se întâmplă în generatorul ales.

  • Acest site publică o singură pagină, dar cu puțin în plus în scriptul nostru de compilare, am putea publica mai multe pagini. Ar putea chiar să publice o postare pe blog.
  • „Experiența dezvoltatorului” lipsește puțin în depozit. Am putea rula scriptul nostru Node pe orice fișier salvat prin implementarea unui pachet precum Nodemon sau adăugând „reîncărcare la cald” cu ceva de genul BrowserSync.
  • Datele care trăiesc în Sanity pot alimenta mai multe site-uri și servicii. Puteți crea un site de CV care să folosească acest lucru și să publice un PDF în loc de o pagină web.
  • Ați putea adăuga CSS și face ca acesta să arate ca un site real.