Costruire l'SSG che ho sempre desiderato: un panino 11ty, Vite e JAM
Pubblicato: 2022-03-10Non so voi, ma sono stato sopraffatto da tutti gli strumenti di sviluppo web che abbiamo in questi giorni. Che ti piaccia Markdown, HTML semplice, React, Vue, Svelte, Pug templates, Handlebars, Vibranium, puoi probabilmente mescolarlo con alcuni dati CMS e ottenere un bel cocktail statico del sito.
Non ho intenzione di dirti quali strumenti di sviluppo dell'interfaccia utente utilizzare perché sono tutti fantastici, a seconda delle esigenze del tuo progetto. Questo post riguarda la ricerca del generatore di siti statici perfetto per ogni occasione; qualcosa che ci consente di utilizzare modelli senza JS come markdown per iniziare e portare "isole" di interattività guidata dai componenti secondo necessità.
Sto distillando il valore di un anno di apprendimento in un singolo post qui. Non solo parleremo di codice (aka duct tape 11ty e Vite insieme), ma esploreremo anche perché questo approccio è così universale per i problemi di Jamstack. Toccheremo:
- Due approcci alla generazione di siti statici e perché dovremmo colmare il divario;
- Dove linguaggi di creazione di modelli come Pug e Nunjucks si dimostrano ancora utili;
- Quando dovrebbero entrare in gioco framework di componenti come React o Svelte;
- In che modo il nuovo mondo di Vite con ricarica a caldo ci aiuta a portare l'interattività JS nel nostro HTML con quasi zero configurazioni;
- In che modo questo integra la cascata di dati di 11ty, portando i dati CMS a qualsiasi framework di componenti o modello HTML che potresti desiderare.
Quindi, senza ulteriori indugi, ecco la mia storia di terribili script di costruzione, scoperte di bundler e nastro adesivo per spaghetti che (alla fine) mi ha dato l'SSG che ho sempre desiderato: un sandwich 11ty, Vite e Jam chiamato Slinkity!
Una grande divisione nella generazione di siti statici
Prima di immergermi, voglio discutere di quelli che chiamerò due "campi" nella generazione di siti statici.
Nel primo campo abbiamo il “semplice” generatore di siti statici. Questi strumenti non portano bundle JavaScript, app a pagina singola e qualsiasi altra parola d'ordine che ci aspettiamo. Inchiodano semplicemente i fondamenti di Jamstack: estrai i dati da qualsiasi BLOB JSON di CMS che preferisci e fai scorrere quei dati in semplici modelli HTML + CSS. Strumenti come Jekyll, Hugo e 11ty dominano questo campo, permettendoti di trasformare una directory di markdown e file liquidi in un sito Web completamente funzionante. Vantaggi chiave:
- Curva di apprendimento poco profonda
Se conosci HTML, sei a posto! - Tempi di costruzione rapidi
Non stiamo elaborando nulla di complesso, quindi ogni percorso si costruisce in un attimo. - Tempo istantaneo per interattivo
Non c'è (o molto poco) JavaScript da analizzare sul client.
Ora, nel secondo campo, abbiamo il generatore di siti statici "dinamici". Questi introducono framework di componenti come React, Vue e Svelte per portare l'interattività al tuo Jamstack. Questi soddisfano la stessa promessa fondamentale di combinare i dati CMS con i percorsi del tuo sito in fase di creazione. Vantaggi chiave:
- Costruito per l'interattività
Hai bisogno di un carosello di immagini animate? Modulo a più passaggi? Basta aggiungere un insieme di componenti di HTML, CSS e JS. - Gestione statale
Qualcosa come React Context dei negozi Svelte consente la condivisione dei dati senza interruzioni tra i percorsi. Ad esempio, il carrello sul tuo sito di e-commerce.
Ci sono vantaggi distinti in entrambi gli approcci. Ma cosa succede se scegli un SSG del primo campo come Jekyll, solo per realizzare sei mesi dopo il tuo progetto che hai bisogno di un po' di interattività componente-y? Oppure scegli qualcosa come NextJS per quei potenti componenti, solo per lottare con la curva di apprendimento di React, o inutili KB di JavaScript su un post di blog statico?
Pochi progetti si adattano perfettamente a un campo o all'altro secondo me. Esistono su uno spettro, favorendo costantemente nuovi set di funzionalità man mano che le esigenze di un progetto si evolvono. Quindi, come troviamo una soluzione che ci consenta di iniziare con i semplici strumenti del primo campo e aggiungere gradualmente funzionalità dal secondo quando ne abbiamo bisogno?
Bene, percorriamo un po' il mio viaggio di apprendimento.
Nota: se hai già venduto modelli statici con 11ty per creare i tuoi siti statici, sentiti libero di passare alla succosa procedura dettagliata del codice.
Passando dai componenti ai modelli e alle API Web
Nel gennaio 2020, ho deciso di fare ciò che quasi tutti gli sviluppatori web fanno ogni anno: ricostruire il mio sito personale. Ma questa volta sarebbe stato diverso. Mi sono sfidato a costruire un sito con le mani legate dietro la schiena, nessun framework o pipeline di costruzione sono ammessi!
Questo non era un compito semplice come devoto di React. Ma a testa alta, ho deciso di costruire la mia pipeline di costruzione da zero assoluto. C'è un sacco di codice scritto male che potrei condividere dalla v1 del mio sito personale... ma ti lascerò fare clic su questo LEGGIMI se sei così coraggioso. Invece, voglio concentrarmi sui takeaway di livello superiore che ho imparato facendo morire di fame i miei piaceri colpevoli di JS.
I modelli vanno molto più in là di quanto potresti pensare
Sono venuto a questo progetto un drogato di JavaScript in recupero. Ci sono alcune esigenze relative al sito statico che ho adorato usare framework basati su componenti per soddisfare:
- Vogliamo suddividere il mio sito in componenti dell'interfaccia utente riutilizzabili che possono accettare oggetti JS come parametri (ovvero "oggetti di scena").
- Abbiamo bisogno di recuperare alcune informazioni in fase di costruzione per inserire uno schiaffo in un sito di produzione.
- Abbiamo bisogno di generare una serie di percorsi URL da una directory di file o da un grosso oggetto di contenuto JSON.
Elenco tratto da questo post sul mio blog personale.
Ma potresti aver notato ... nessuno di questi ha davvero bisogno di JavaScript lato client. I framework dei componenti come React sono costruiti principalmente per gestire i problemi di gestione dello stato, come l'app Web di Facebook che ispira React in primo luogo. Se stai semplicemente suddividendo il tuo sito in componenti di dimensioni ridotte o elementi di sistema di progettazione, anche modelli come Pug funzionano abbastanza bene!
Prendi questa barra di navigazione per esempio. In Pug, possiamo definire un "mixin" che riceve i dati come oggetti di scena:
// nav-mixins.pug mixin NavBar(links) // pug's version of a for loop each link in links a(href=link.href) link.text
Quindi, possiamo applicare quel mixin ovunque sul nostro sito.
// index.pug // kinda like an ESM "import" include nav-mixins.pug html body +NavBar(navLinksPassedByJS) main h1 Welcome to my pug playground
Se "renderizziamo" questo file con alcuni dati, otterremo un bellissimo index.html
da servire ai nostri utenti.
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)
Certo, questo non offre sottigliezze come CSS con ambito per i tuoi mixin o JavaScript stateful dove lo desideri. Ma ha alcuni vantaggi molto potenti rispetto a qualcosa come React:
- Non abbiamo bisogno di bundle di fantasia che non capiamo.
Abbiamo appena scritto a mano quella chiamatapug.render
e abbiamo già il primo percorso di un sito pronto per la distribuzione. - Non spediamo JavaScript all'utente finale.
L'uso di React spesso significa inviare un grande runtime ole per l'esecuzione dei browser delle persone. Chiamando una funzione comepug.render
in fase di compilazione, teniamo tutti i JS dalla nostra parte mentre alla fine inviamo un file.html
pulito.
Questo è il motivo per cui penso che i modelli siano un'ottima "base" per i siti statici. Tuttavia, essere in grado di raggiungere framework di componenti in cui ne traiamo davvero vantaggio sarebbe bello. Ne parleremo più avanti.
Letture consigliate : Come creare modelli angolari migliori con Pug di Zara Cooper
Non è necessario un framework per creare app a pagina singola
Mentre ero lì, volevo anche alcune transizioni di pagina sexy sul mio sito. Ma come possiamo realizzare qualcosa del genere senza un framework?
Bene, non possiamo farlo se ogni pagina è il proprio file .html
. L'intero browser si aggiorna quando passiamo da un file HTML all'altro, quindi non possiamo avere quel bel effetto di dissolvenza incrociata (dal momento che mostreremmo brevemente entrambe le pagine una sopra l'altra).
Abbiamo bisogno di un modo per "recuperare" l'HTML e il CSS per il punto in cui stiamo navigando e renderlo visibile utilizzando JavaScript. Sembra un lavoro per le app a pagina singola! Ho usato un semplice miscuglio di API del browser per questo:
- Intercetta tutti i clic sui link utilizzando un listener di eventi.
- fetch API : recupera tutte le risorse per qualsiasi pagina che desideri visitare e prendi in vista il bit che voglio animare: il contenuto al di fuori della barra di navigazione (che voglio rimanere fermo durante l'animazione).
- API di animazioni web : anima il nuovo contenuto in modo che venga visualizzato come fotogramma chiave.
- API history : cambia il percorso visualizzato nella barra degli URL del browser utilizzando
window.history.pushState({}, 'new-route')
. Altrimenti, sembra che tu non abbia mai lasciato la pagina precedente!
Per chiarezza, ecco un'illustrazione visiva del concetto di app a pagina singola utilizzando un semplice trova e sostituisci ( articolo di origine ):
Nota : puoi anche visitare il codice sorgente dal mio sito personale.
Certo, alcuni accoppiamenti di React et al e la tua libreria di animazioni di scelta possono farlo. Ma per un caso d'uso semplice come una transizione di dissolvenza... le API Web sono piuttosto potenti da sole. E se desideri transizioni di pagina più robuste su modelli statici come Pug o HTML semplice, librerie come Swup ti serviranno bene.
Ciò che 11ty ha portato in tavola
Mi sentivo abbastanza bene con il mio piccolo SSG a questo punto. Certo, non poteva recuperare alcun dato CMS in fase di compilazione, non supportava layout diversi per pagina o directory, non ottimizzava le mie immagini e non disponeva di build incrementali.
Ok, potrei aver bisogno di aiuto.
Dato tutto ciò che ho imparato dalla v1, pensavo di essermi guadagnato il diritto di abbandonare la regola "nessuna pipeline di costruzione di terze parti" e di raggiungere gli strumenti esistenti. Si scopre che 11ty ha un tesoro di funzionalità di cui ho bisogno!
- Recupero dei dati in fase di compilazione utilizzando i file
.11ydata.js
; - Dati globali disponibili per tutti i miei modelli da una cartella
_data
; - Ricaricamento a caldo durante lo sviluppo tramite browsersync;
- Supporto per trasformazioni HTML fantasiose;
- ...e innumerevoli altre chicche.
Se hai provato semplici SSG come Jekyll o Hugo, dovresti avere una buona idea di come funziona 11ty. Unica differenza? 11ty utilizza JavaScript in modo completo.
11ty supporta praticamente tutte le librerie di modelli disponibili, quindi è stato felice di eseguire il rendering di tutte le mie pagine Pug su percorsi .html
. L'opzione di concatenamento del layout ha aiutato anche la mia configurazione di app a pagina singola falsa. Avevo solo bisogno di un unico script
per tutti i miei percorsi e di un layout "globale" per importare quello 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?
Finché main.js
intercetta tutti i collegamenti che abbiamo esplorato, abbiamo transizioni di pagina!
Oh, e la cascata di dati
Quindi 11ty ha aiutato a ripulire tutto il mio codice spaghetti dalla v1. Ma ha portato un altro pezzo importante: un'API pulita per caricare i dati nei miei layout. Questo è il pane quotidiano dell'approccio Jamstack. Invece di recuperare i dati nel browser con la manipolazione JavaScript + DOM, puoi:
- Recupera i dati in fase di compilazione utilizzando Node.
Potrebbe trattarsi di una chiamata a un'API esterna, un'importazione JSON o YAML locale o persino il contenuto di altri percorsi sul tuo sito (immagina di aggiornare un sommario ogni volta che vengono aggiunti nuovi percorsi). - Inserisci quei dati nei tuoi percorsi. Ricordiamo quella funzione
.render
che abbiamo scritto prima:
const html = pug.render('/index.pug', { navLinksPassedByJS: [ { href: '/', text: 'Home' }, { href: '/adopt', text: 'Adopt a Pug' } ] })
...ma invece di chiamare ogni volta pug.render
con i nostri dati, lasciamo che 11ty lo faccia dietro le quinte.
Certo, non avevo molti dati per il mio sito personale. Ma è stato fantastico creare un file .yaml
per tutti i miei progetti personali:
# _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 ...
E accedi a quei dati su qualsiasi modello:
// home.pug .project-carousel each work in works h3 #{title} p #{timeframe} each tag in tags ...
Venendo dal mondo del "rendering lato client" con create-react-app, questa è stata una rivelazione piuttosto grande. Non dovrai più inviare chiavi API o grandi BLOB JSON al browser.
Ho anche aggiunto alcune chicche per il recupero di JavaScript e miglioramenti dell'animazione rispetto alla versione 1 del mio sito. Se sei curioso, ecco dove si trovava il mio README a questo punto.
Ero felice a questo punto, ma mancava qualcosa
Sono andato sorprendentemente lontano abbandonando i componenti basati su JS e abbracciando i modelli (con transizioni di pagina animate per l'avvio). Ma so che questo non soddisferà i miei bisogni per sempre. Ricordi quella grande divisione con cui ci ho dato il via? Bene, c'è chiaramente ancora quel burrone tra la mia configurazione di build (fermamente nel campo n. 1) e il paradiso dell'interattività basata su JS (il Next, SvelteKit e altro del campo n. 2). Dì che voglio aggiungere:
- un pop-up modale con un interruttore di apertura/chiusura,
- un sistema di progettazione basato su componenti come Material UI, completo di uno stile con ambito,
- una forma complessa a più fasi, forse guidata da una macchina a stati.
Se sei un semplice purista di JS, probabilmente hai risposte senza framework a tutti quei casi d'uso. Ma c'è un motivo per cui JQuery non è più la norma! C'è qualcosa di interessante nella creazione di componenti di HTML discreti e di facile lettura, stili con ambito e parti di variabili di "stato" JavaScript. React, Vue, Svelte, ecc. offrono così tante sottigliezze per il debug e il test che la manipolazione diretta del DOM non può eguagliare.
Quindi ecco la mia domanda da un milione di dollari:
Possiamo usare modelli HTML semplici per iniziare e aggiungere gradualmente componenti React/Vue/Svelte dove li vogliamo?
La risposta è sì . Proviamolo.
11ty + Vite: Un Match Made In Heaven ️
Ecco il sogno che sto immaginando qui. Ovunque voglio inserire qualcosa di interattivo, voglio lasciare un piccolo flag nel mio modello per "mettere qui il componente X React". Questa potrebbe essere la sintassi dello shortcode supportata da 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' %}
Ma ricorda, il pezzo unico 11ty (di proposito) evita: un modo per raggruppare tutto il tuo JavaScript. Venendo dalla gilda OG del raggruppamento, il tuo cervello probabilmente salta alla creazione di processi Webpack, Rollup o Babel qui. Costruisci un grande file di punto di ingresso ole e genera un bel codice ottimizzato, giusto?
Ebbene sì, ma questo può essere piuttosto coinvolto. Se stiamo usando i componenti React, ad esempio, probabilmente avremo bisogno di alcuni caricatori per JSX, un elaborato processo Babel per trasformare tutto, un interprete per l'importazione di moduli SASS e CSS, qualcosa che aiuti con il ricaricamento live e così via.
Se solo ci fosse uno strumento in grado di vedere i nostri file .jsx
e sapere esattamente cosa farne.
Entra: Vite
Vite è stato il discorso della città negli ultimi tempi. È pensato per essere lo strumento all-in-one per creare praticamente qualsiasi cosa in JavaScript. Ecco un esempio da provare a casa. Creiamo una directory vuota da qualche parte sulla nostra macchina e installiamo alcune dipendenze:
npm init -y # Make a new package.json with defaults set npm i vite react react-dom # Grab Vite + some dependencies to use React
Ora possiamo creare un file index.html
che serva come "punto di ingresso" della nostra app. Lo terremo abbastanza semplice:
<!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>
L'unico bit interessante è che div id="root"
nel mezzo. Questa sarà la radice del nostro componente React tra un momento!
Se lo desideri, puoi attivare il server Vite per vedere il nostro semplice file HTML nel tuo browser. Esegui semplicemente vite
(o npx vite
se il comando non è stato configurato nel tuo terminale) e vedrai questo utile output:
vite vX.XX dev server running at: > Local: http://localhost:3000/ > Network: use `--host` to expose ready in Xms.
Proprio come Browsersync o altri server di sviluppo popolari, il nome di ogni file .html
corrisponde a un percorso sul nostro server. Quindi, se rinominassimo index.html
in about.html
, visiteremo http://localhost:3000/about/
(sì, avrai bisogno di una barra finale!)
Ora facciamo qualcosa di interessante. Accanto a quel file index.html
, aggiungi un componente React di base di qualche tipo. Useremo useState
di React qui per dimostrare l'interattività:
// 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> ) }
Ora carichiamo quel componente sulla nostra pagina. Questo è tutto ciò che dobbiamo aggiungere al nostro index.html
:
<!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>
Sì, è tutto. Non c'è bisogno di trasformare noi stessi il nostro file .jsx
in un file .js
pronto per il browser! Ovunque Vite veda un'importazione .jsx
, convertirà automaticamente quel file in qualcosa che i browser possono capire. Non c'è nemmeno una cartella dist
o build
quando si lavora in fase di sviluppo; Vite elabora tutto al volo, completo di ricarica dei moduli a caldo ogni volta che salviamo le nostre modifiche.
Ok, quindi abbiamo uno strumento di costruzione incredibilmente capace. Come possiamo portare questo ai nostri modelli 11ty?
Esecuzione di Vite insieme a 11ty
Prima di passare alle cose buone, discutiamo di eseguire 11ty e Vite fianco a fianco. Vai avanti e installa 11ty come dipendenza dev nella stessa directory del progetto dall'ultima sezione:
npm i -D @11ty/eleventy # yes, it really is 11ty twice
Ora facciamo un piccolo controllo pre-volo per vedere se 11ty funziona. Per evitare qualsiasi confusione, ti consiglio di:
- Elimina quel file
index.html
da prima; - Sposta quel
TimesWeMispronouncedVite.jsx
all'interno di una nuova directory. Dire,components/
; - Crea una cartella
src
in cui vivere il nostro sito web; - Aggiungi un modello a quella directory
src
per l'elaborazione da parte di 11ty.
Ad esempio, un file blog-post.md
con i seguenti contenuti:
# Hello world! It's markdown here
La struttura del tuo progetto dovrebbe assomigliare a questa:
src/ blog-post.md components/ TimesWeMispronouncedVite.jsx
Ora, esegui 11ty dal tuo terminale in questo modo:
npx eleventy --input=src
Se tutto va bene, dovresti vedere un output di build come questo:
_site/ blog-post/ index.html
Dove _site
è la nostra directory di output predefinita e blog-post/index.html
è il nostro file markdown magnificamente convertito per la navigazione.
Normalmente, eseguiamo npx eleventy --serve
per avviare un server di sviluppo e visitare quella pagina /blog-post
. Ma ora stiamo usando Vite per il nostro server di sviluppo! L'obiettivo qui è quello di:
- Fai in modo che undici costruiscano il nostro markdown, Pug, nunjucks e altro nella directory
_site
. - Punta Vite nella stessa directory
_site
in modo che possa elaborare i componenti React, le importazioni di stile di fantasia e altre cose che 11ty non ha raccolto.
Quindi un processo di costruzione in due fasi, con 11ty che consegna il Vite. Ecco il comando CLI di cui avrai bisogno per avviare 11ty e Vite in modalità "watch" contemporaneamente:
(npx eleventy --input=src --watch) & npx vite _site
Puoi anche eseguire questi comandi in due terminali separati per semplificare il debug.
Con un po' di fortuna, dovresti essere in grado di visitare http://localhost:3000/blog-post/
(di nuovo, non dimenticare la barra finale!) Per vedere quel file Markdown elaborato.
Idratazione parziale con codici brevi
Facciamo un breve riassunto degli shortcode. È ora di rivedere quella sintassi di prima:
{% react '/components/TimesWeMispronouncedVite.jsx' %}
Per chi non ha familiarità con gli shortcode: sono più o meno gli stessi di una chiamata di funzione, in cui la funzione restituisce una stringa di HTML da far scorrere nella pagina. L'”anatomia” del nostro shortcode è:
-
{% … %}
Wrapper che indica l'inizio e la fine dello shortcode. -
react
Il nome della nostra funzione shortcode che configureremo tra poco. -
'/components/TimesWeMispronouncedVite.jsx'
Il primo (e unico) argomento della nostra funzione shortcode. Puoi avere tutti gli argomenti che vuoi.
Connettiamo il nostro primo shortcode! Aggiungi un file .eleventy.js
alla base del tuo progetto e aggiungi questa voce di configurazione per il nostro shortcode di 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', } } }
Ora, ravviviamo il nostro blog-post.md
con il nostro nuovo shortcode. Incolla questo contenuto nel nostro file markdown:
# 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' %}
E se esegui un rapido npx eleventy
, dovresti vedere questo output nella tua directory _site
in /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>
Scrivere il nostro shortcode dei componenti
Ora facciamo qualcosa di utile con quello shortcode. Ricordi quel tag di script
che abbiamo scritto mentre provavamo Vite? Bene, possiamo fare la stessa cosa nel nostro shortcode! Questa volta useremo l'argomento componentPath
per generare l'importazione, ma manterremo il resto più o meno lo stesso:
// .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', } } }
Ora, una chiamata al nostro shortcode (es. {% react '/components/TimesWeMispronouncedVite.jsx' %}
) dovrebbe produrre qualcosa del genere:
<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>
Visitando il nostro server di sviluppo utilizzando (npx eleventy --watch) & vite _site
, dovremmo trovare un elemento contatore meravigliosamente cliccabile.
Buzzword Alert — Idratazione parziale e architettura delle isole
Abbiamo appena dimostrato "l'architettura delle isole" nella sua forma più semplice. Questa è l'idea che i nostri alberi dei componenti interattivi non devono occupare l'intero sito web. Invece, possiamo far girare mini-alberi, o "isole", in tutta la nostra app a seconda di dove abbiamo effettivamente bisogno di tale interattività. Hai una landing page di base di link senza alcuno stato da gestire? Grande! Non c'è bisogno di componenti interattivi. Ma hai un modulo multi-step che potrebbe trarre vantaggio dalla libreria X React? Nessun problema. Usa tecniche del genere per react
allo shortcode per creare un'isola Form.jsx
.
Questo va di pari passo con l'idea di "idratazione parziale". Probabilmente hai sentito il termine "idratazione" se lavori con SSG componenti come NextJS o Gatsby. In breve, è un modo per:
- Eseguire prima il rendering dei componenti in HTML statico.
Ciò offre all'utente qualcosa da visualizzare quando visita inizialmente il tuo sito web. - "Idrata" questo HTML con l'interattività.
È qui che colleghiamo i nostri hook di stato e renderer, beh, in modo che i clic sui pulsanti attivino effettivamente qualcosa.
Questo pugno 1-2 rende i framework basati su JS fattibili per i siti statici. Finché l'utente ha qualcosa da visualizzare prima che il tuo JavaScript abbia terminato l'analisi, otterrai un punteggio decente su quelle metriche del faro.
Bene, finché non lo fai. Può essere costoso "idratare" un intero sito Web poiché avrai bisogno di un bundle JavaScript pronto per elaborare ogni ultimo elemento DOM . Ma la nostra tecnica scrappy shortcode non copre l'intera pagina! Invece, idratiamo “parzialmente” il contenuto che c'è, inserendo componenti solo dove necessario.
Non preoccuparti, c'è un plugin per tutto questo: Slinkity
Ricapitoliamo cosa abbiamo scoperto qui:
- Vite è un bundler incredibilmente capace in grado di elaborare la maggior parte dei tipi di file (
jsx
,vue
esvelte
per citarne alcuni) senza configurazione aggiuntiva. - Gli shortcode sono un modo semplice per inserire blocchi di HTML nei nostri modelli, in stile componente.
- Possiamo utilizzare gli shortcode per eseguire il rendering di bundle JS dinamici e interattivi ovunque desideriamo utilizzando l'idratazione parziale.
Che dire quindi delle build di produzione ottimizzate? Caricare correttamente gli stili con ambito? Diamine, usi .jsx
per creare intere pagine? Bene, ho raggruppato tutto questo (e molto altro!) in un progetto chiamato Slinkity. Sono entusiasta di vedere la calorosa accoglienza della comunità al progetto e mi piacerebbe che tu, caro lettore, lo facessi tu stesso!
Prova la guida rapida
Anche Astro è fantastico
I lettori con gli occhi puntati sulla tecnologia all'avanguardia probabilmente hanno pensato ad Astro almeno una volta ormai. E non posso biasimarti! È costruito con un obiettivo abbastanza simile in mente: iniziare con un semplice HTML e inserire componenti con stato ovunque ne abbiate bisogno. Diamine, ti permetteranno persino di iniziare a scrivere componenti React all'interno di componenti Vue o Svelte all'interno di file modello HTML! È come l'edizione MDX Xtreme.
Tuttavia, il loro approccio ha un costo piuttosto importante: devi riscrivere la tua app da zero. Ciò significa un nuovo formato di modello basato su JSX (con cui potresti non essere a tuo agio), una pipeline di dati completamente nuova a cui mancano un paio di sottigliezze in questo momento e bug generali mentre risolvono i nodi.
Ma girare un cocktail 11ty + Vite con uno strumento come Slinkity? Bene, se hai già un sito 11ty, Vite dovrebbe essere installato senza alcuna riscrittura e gli shortcode dovrebbero coprire molti degli stessi casi d'uso dei file .astro
. Devo ammettere che è tutt'altro che perfetto in questo momento. Ma ehi, finora è stato utile e penso che sia un'alternativa piuttosto forte se vuoi evitare le riscritture a livello di sito!
Avvolgendo
Questo esperimento Slinkity ha soddisfatto le mie esigenze finora (e anche alcuni di voi!). Sentiti libero di usare qualsiasi stack funzioni per la tua JAM. Sono solo entusiasta di condividere i risultati del mio anno di dissolutezza negli strumenti di costruzione e sono così entusiasta di vedere come possiamo colmare il grande divario di Jamstack.
Ulteriori letture
Vuoi immergerti più a fondo nell'idratazione parziale, o ESM, o SSG in generale? Dai un'occhiata a questi:
- Architettura delle isole
Questo post sul blog di Jason Format ha davvero dato il via a una discussione su "isole" e "idratazione parziale" nello sviluppo web. È pieno zeppo di diagrammi utili e della filosofia dietro l'idea. - Semplifica la tua statica con un generatore di siti statici personalizzato
Un altro articolo di SmashingMag che ti guida nella creazione da zero di costruttori di siti Web basati su Node. È stata una grande ispirazione per me! - Come i moduli ES hanno ridefinito lo sviluppo web
Un post personale su come i moduli ES hanno cambiato il gioco dello sviluppo web. Questo si tuffa un po 'più nel "allora e ora" della sintassi di importazione sul Web. - Un'introduzione ai componenti web
Un'eccellente guida dettagliata su quali sono i componenti Web, come funziona il DOM ombra e dove i componenti Web si rivelano utili. Ho usato questa guida per applicare componenti personalizzati al mio framework!