Budowanie SSG, którego zawsze chciałem: kanapka 11ty, Vite i JAM

Opublikowany: 2022-03-10
Krótkie podsumowanie ↬ W styczniu 2020 r. Ben Holmes postanowił zrobić to, co prawie każdy programista WWW robi każdego roku: odbudować swoją osobistą witrynę. W tym artykule dzieli się swoją historią o tym, jak postanowił zbudować własny potok budowania od absolutnego punktu zerowego i stworzył Slinkity.

Nie wiem jak wy, ale jestem przytłoczony wszystkimi narzędziami do tworzenia stron internetowych, jakie mamy w dzisiejszych czasach. Niezależnie od tego, czy lubisz Markdown, zwykły HTML, React, Vue, Svelte, szablony Mops, kierownice, Vibranium — prawdopodobnie możesz pomieszać je z danymi CMS i uzyskać fajny koktajl ze statycznej strony.

Nie powiem ci, po które narzędzia do tworzenia interfejsu użytkownika sięgnąć, ponieważ wszystkie są świetne — w zależności od potrzeb twojego projektu. Ten post dotyczy znalezienia idealnego generatora stron statycznych na każdą okazję; coś, co pozwala nam na rozpoczęcie korzystania z szablonów pozbawionych JS, takich jak przeceny, i w razie potrzeby wprowadza „wyspy” interaktywności opartej na komponentach.

Koncentruję się na rocznej wiedzy w jednym poście. Nie tylko porozmawiamy o kodzie (czyli oklejaniu 11ty i Vite razem), ale także zbadamy, dlaczego to podejście jest tak uniwersalne dla problemów Jamstacka. Dotkniemy:

  • Dwa podejścia do statycznego generowania witryn i dlaczego powinniśmy wypełnić lukę;
  • Tam, gdzie języki szablonowe, takie jak mops i nunjucks, wciąż okazują się przydatne;
  • Kiedy do gry powinny wejść frameworki komponentów, takie jak React lub Svelte;
  • W jaki sposób nowy, ładowany na gorąco świat Vite pomaga nam wprowadzić interaktywność JS do naszego HTML z prawie zerową konfiguracją;
  • W jaki sposób uzupełnia to kaskadę danych 11ty, przenosząc dane CMS do dowolnej struktury komponentów lub szablonu HTML, jaki chcesz.

Więc bez zbędnych ceregieli, oto moja opowieść o okropnych scenariuszach budowy, przełomach w pakietach i taśmie klejącej z kodem spaghetti, która (ostatecznie) dała mi SSG, o którym zawsze marzyłem: kanapkę 11ty, Vite and Jam o nazwie Slinkity!

Wielki podział w generowaniu stron statycznych

Zanim zanurkuję, chcę omówić to, co nazywam dwoma „obozami” w statycznym generowaniu miejsc.

W pierwszym obozie mamy „prosty” generator stron statycznych. Te narzędzia nie dostarczają pakietów JavaScript, aplikacji jednostronicowych ani żadnych innych modnych słów, których możemy się spodziewać. Po prostu utrwalają podstawy Jamstack: pobierają dane z dowolnego preferowanego obiektu JSON w systemie CMS i wsuwają te dane do zwykłych szablonów HTML + CSS. Narzędzia takie jak Jekyll, Hugo i 11ty dominują w tym obozie, umożliwiając przekształcenie katalogu przecen i plików płynnych w w pełni funkcjonalną stronę internetową. Kluczowe korzyści:

  • Płytka krzywa uczenia się
    Jeśli znasz HTML, jesteś gotowy!
  • Szybkie czasy budowy
    Nie przetwarzamy niczego skomplikowanego, więc każda trasa jest tworzona w mgnieniu oka.
  • Natychmiastowy czas na interaktywność
    Nie ma (lub jest bardzo mało) JavaScript do przeanalizowania na kliencie.

Teraz w drugim obozie mamy „dynamiczny” generator stron statycznych. Wprowadzają one struktury komponentów, takie jak React, Vue i Svelte, aby zapewnić interaktywność w Twoim Jamstack. Spełniają one tę samą podstawową obietnicę łączenia danych CMS z trasami witryny w czasie tworzenia. Kluczowe korzyści:

  • Stworzony z myślą o interaktywności
    Potrzebujesz karuzeli z animowanymi obrazami? Formularz wieloetapowy? Wystarczy dodać skomponentowany model użytkowy HTML, CSS i JS.
  • Zarządzanie państwowe
    Coś takiego jak React Context ze sklepów Svelte umożliwia bezproblemowe udostępnianie danych między trasami. Na przykład koszyk w Twojej witrynie e-commerce.

Każde podejście ma swoje zalety. Ale co, jeśli wybierzesz SSG z pierwszego obozu, takiego jak Jekyll, tylko po to, by po sześciu miesiącach zdać sobie sprawę, że potrzebujesz interaktywności komponentowej? A może wybierasz coś takiego jak NextJS dla tych potężnych komponentów, tylko po to, by zmagać się z krzywą uczenia się Reacta lub niepotrzebnym KB JavaScript w statycznym poście na blogu?

Niewiele projektów wpisuje się wprost w jeden lub drugi obóz. Istnieją w szerokim spektrum, stale faworyzując nowe zestawy funkcji w miarę ewolucji potrzeb projektu. Jak więc znaleźć rozwiązanie, które pozwoli nam zacząć od prostych narzędzi z pierwszego obozu i stopniowo dodawać funkcje z drugiego, kiedy ich potrzebujemy?

Cóż, przejdźmy trochę przez moją podróż edukacyjną.

Uwaga: jeśli masz już sprzedane szablony statyczne z 11ty do tworzenia witryn statycznych, możesz wskoczyć do soczystego przewodnika po kodzie.

Więcej po skoku! Kontynuuj czytanie poniżej ↓

Przechodzenie od komponentów do szablonów i internetowych interfejsów API

W styczniu 2020 r. postanowiłem zrobić to, co robi prawie każdy programista WWW co roku: odbudować moją osobistą witrynę. Ale tym razem miało być inaczej. Rzuciłem sobie wyzwanie, aby zbudować witrynę z rękami związanymi za plecami, niedozwolone są frameworki lub budowanie potoków!

Nie było to proste zadanie dla wielbiciela React. Ale z wysoko uniesioną głową postanowiłem zbudować własny potok budowania od absolutnego punktu zerowego. Jest dużo źle napisanego kodu, który mógłbym udostępnić z v1 mojej osobistej strony… ale pozwolę ci kliknąć to README, jeśli jesteś tak odważny. Zamiast tego chcę skupić się na wynosach wyższego poziomu, których się nauczyłem, głodząc się z moich winnych przyjemności JS.

Szablony idą znacznie dalej, niż mogłoby się wydawać

Przyszedłem do tego projektu jako odzyskujący śmieci JavaScript. Jest kilka potrzeb związanych ze statyczną witryną, które uwielbiałem, korzystając z frameworków opartych na komponentach:

  1. Chcemy podzielić moją witrynę na komponenty UI wielokrotnego użytku, które akceptują obiekty JS jako parametry (czyli „rekwizyty”).
  2. Musimy pobrać pewne informacje w czasie kompilacji, aby trafić do witryny produkcyjnej.
  3. Musimy wygenerować kilka tras URL z katalogu plików lub grubego obiektu treści JSON.

Lista zaczerpnięta z tego posta na moim osobistym blogu.

Ale być może zauważyłeś… żaden z nich tak naprawdę nie wymaga JavaScriptu po stronie klienta. Struktury komponentów, takie jak React, są budowane głównie w celu rozwiązywania problemów związanych z zarządzaniem stanem, podobnie jak aplikacja internetowa Facebook, która w pierwszej kolejności inspiruje Reacta. Jeśli po prostu dzielisz swoją witrynę na niewielkie komponenty lub elementy systemu projektowania, szablony takie jak Mops również działają całkiem dobrze!

Weźmy na przykład ten pasek nawigacyjny. W Pug możemy zdefiniować „mixin”, który odbiera dane jako props:

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

Następnie możemy zastosować tę mieszankę w dowolnym miejscu na naszej stronie.

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

Jeśli „renderujemy” ten plik z pewnymi danymi, otrzymamy piękny index.html , który będzie udostępniany naszym użytkownikom.

 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)

Jasne, to nie daje takich drobiazgów, jak CSS z zakresem dla twoich mixinów lub stanowy JavaScript tam, gdzie chcesz. Ale ma kilka bardzo potężnych zalet w stosunku do czegoś takiego jak React:

  1. Nie potrzebujemy wymyślnych pakowaczy, których nie rozumiemy.
    Właśnie napisaliśmy to wywołanie pug.render ręcznie i mamy już pierwszą trasę witryny gotową do wdrożenia.
  2. Nie wysyłamy żadnego kodu JavaScript do użytkownika końcowego.
    Korzystanie z Reacta często oznacza wysyłanie dużego, starego środowiska wykonawczego do uruchamiania przeglądarek użytkowników. Wywołując funkcję taką jak pug.render w czasie kompilacji, zachowujemy cały JS po naszej stronie, podczas gdy na końcu wysyłamy czysty plik .html .

Dlatego uważam, że szablony są świetną „bazą” dla statycznych witryn. Mimo to, możliwość sięgnięcia po frameworki komponentów, z których naprawdę skorzystamy, byłaby fajna. Więcej o tym później.

Zalecana literatura : Jak tworzyć lepsze szablony kątowe za pomocą Mopsa autorstwa Zara Cooper

Nie potrzebujesz frameworka do tworzenia aplikacji jednostronicowych

Kiedy to robiłem, chciałem też trochę seksownych przejść między stronami w mojej witrynie. Ale jak zrobić coś takiego bez ram?

Przenikanie z pionowym przejściem przez wycieranie
Przenikanie z pionowym przejściem przez wycieranie. (duży podgląd)

Cóż, nie możemy tego zrobić, jeśli każda strona jest własnym plikiem .html . Cała przeglądarka odświeża się, gdy przeskakujemy z jednego pliku HTML do drugiego, więc nie możemy uzyskać tego ładnego efektu przenikania (ponieważ pokrótce pokazaliśmy obie strony jedna na drugiej).

Potrzebujemy sposobu na „pobranie” kodu HTML i CSS dla każdego miejsca, do którego nawigujemy, i animowanie go w widoku za pomocą JavaScript. To brzmi jak praca dla aplikacji jednostronicowych! Użyłem do tego prostej składanki API przeglądarki:

  1. Przechwytuj wszystkie kliknięcia linków za pomocą detektora zdarzeń.
  2. fetch API : Pobierz wszystkie zasoby dla dowolnej strony, którą chcesz odwiedzić, i chwyć fragment, który chcę animować: zawartość poza paskiem nawigacyjnym (który chcę pozostać nieruchomy podczas animacji).
  3. Web Animation API : Animuj nową zawartość w widoku jako klatkę kluczową.
  4. history API : Zmień trasę wyświetlaną w pasku adresu przeglądarki za pomocą window.history.pushState({}, 'new-route') . W przeciwnym razie wygląda na to, że nigdy nie opuściłeś poprzedniej strony!

Dla jasności, oto wizualna ilustracja koncepcji aplikacji jednostronicowej przy użyciu prostego narzędzia Znajdź i zamień ( artykuł źródłowy ):

Krok po kroku proces routingu po stronie klienta: 1. Zwracany jest średnio wysmażony hamburger, 2. Żądamy dobrze wysmażonego burgera za pomocą interfejsu API pobierania, 3. Masujemy odpowiedź, 4. Wyciągamy element „patty” i nakładamy go do naszej aktualnej strony.
Krok po kroku proces routingu po stronie klienta: 1. Zwracany jest średnio wysmażony hamburger, 2. Żądamy dobrze wysmażonego burgera za pomocą interfejsu API pobierania, 3. Masujemy odpowiedź, 4. Wyciągamy element „patty” i nakładamy go do naszej aktualnej strony. (duży podgląd)

Uwaga : Możesz również odwiedzić kod źródłowy z mojej osobistej witryny.

Jasne, może to zrobić kilka par Reacta i wsp. z wybraną biblioteką animacji. Ale w przypadku użycia tak prostego, jak przejście zanikające… internetowe interfejsy API same w sobie są dość potężne. A jeśli potrzebujesz bardziej niezawodnych przejść między stronami w statycznych szablonach, takich jak Pug lub zwykły HTML, biblioteki takie jak Swap będą Ci dobrze służyć.

Co 11ty przyniosło do stołu

W tym momencie czułem się całkiem dobrze z moim małym SSG. Jasne, że nie mógł pobrać żadnych danych CMS w czasie kompilacji, nie obsługiwał różnych układów według strony lub katalogu, nie optymalizował moich obrazów i nie miał kompilacji przyrostowych.

Dobra, może potrzebuję pomocy.

Biorąc pod uwagę wszystkie moje wnioski z v1, pomyślałem, że zasłużyłem na prawo do porzucenia zasady „brak potoków kompilacji stron trzecich” i sięgnięcia po istniejące narzędzia. Okazuje się, że 11ty ma skarbnicę funkcji, których potrzebuję!

  • Pobieranie danych w czasie budowania przy użyciu plików .11ydata.js ;
  • Dane globalne dostępne dla wszystkich moich szablonów z folderu _data ;
  • Ponowne ładowanie na gorąco podczas opracowywania przy użyciu przeglądarki browsersync;
  • Wsparcie dla fantazyjnych przekształceń HTML;
  • …i niezliczone inne gadżety.

Jeśli wypróbowałeś proste SSG, takie jak Jekyll lub Hugo, powinieneś mieć całkiem dobre pojęcie o tym, jak działa 11ty. Tylko różnica? 11ty korzysta z JavaScriptu na wskroś.

11ty obsługuje w zasadzie każdą bibliotekę szablonów, więc z przyjemnością renderowałem wszystkie moje strony Mopsa do tras .html . Ta opcja łączenia układów pomogła również w konfiguracji mojej fałszywej aplikacji z jedną stroną. Potrzebowałem tylko jednego script dla wszystkich moich tras i „globalnego” układu do zaimportowania tego skryptu:

 // _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?

Tak długo, jak ten main.js przechwytuje wszystkie linki, które zbadaliśmy, mamy przejścia między stronami!

Och, i kaskada danych

Więc 11ty pomogło wyczyścić cały mój kod spaghetti z wersji 1. Ale przyniósł kolejny ważny element: czysty interfejs API do ładowania danych do moich układów. To jest chleb powszedni podejścia Jamstack. Zamiast pobierać dane w przeglądarce za pomocą manipulacji JavaScript + DOM, możesz:

  1. Pobieraj dane w czasie kompilacji za pomocą węzła.
    Może to być wywołanie jakiegoś zewnętrznego interfejsu API, lokalny import JSON lub YAML, a nawet zawartość innych tras w Twojej witrynie (wyobraź sobie aktualizowanie spisu treści za każdym razem, gdy dodawane są nowe trasy ).
  2. Umieść te dane w swoich trasach. Przypomnij sobie funkcję .render , którą napisaliśmy wcześniej:
 const html = pug.render('/index.pug', { navLinksPassedByJS: [ { href: '/', text: 'Home' }, { href: '/adopt', text: 'Adopt a Pug' } ] })

…ale zamiast za każdym razem dzwonić do pug.render z naszymi danymi, pozwalamy 11ty robić to za kulisami.

Jasne, nie miałem dużo danych na mojej osobistej stronie. Ale fajnie było przygotować plik .yaml dla wszystkich moich osobistych projektów:

 # _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 uzyskaj dostęp do tych danych w dowolnym szablonie:

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

Pochodząc ze świata „renderowania po stronie klienta” za pomocą aplikacji create-react, była to całkiem spora rewelacja. Koniec z wysyłaniem kluczy API lub dużych obiektów blob JSON do przeglądarki.

Dodałem również kilka gadżetów związanych z pobieraniem JavaScript i ulepszeniami animacji w stosunku do wersji 1 mojej witryny. Jeśli jesteście ciekawi, oto gdzie w tym momencie znajdowało się moje README.

Byłem szczęśliwy w tym momencie, ale czegoś brakowało

Zaszedłem zaskakująco daleko, porzucając komponenty oparte na JS i stosując szablony (z animowanymi przejściami stron do rozruchu). Ale wiem, że to nie zaspokoi moich potrzeb na zawsze. Pamiętasz ten wielki podział, którym nas wyrzuciłem? Cóż, najwyraźniej wciąż jest ten wąwóz między moim zestawem buildów (mocno w obozie 1) a przystanią interaktywności JS (Next, SvelteKit i więcej z obozu nr 2). Powiedz, że chcę dodać:

  • wyskakujący modal z przełącznikiem otwórz/zamknij,
  • system projektowania oparty na komponentach, taki jak Material UI, wraz ze stylizacją w zakresie,
  • złożona, wieloetapowa forma, być może napędzana przez maszynę stanową.

Jeśli jesteś czystym purystą JS, prawdopodobnie masz odpowiedzi bez frameworka na wszystkie te przypadki użycia. Ale jest powód, dla którego JQuery nie jest już normą! Jest coś pociągającego w tworzeniu oddzielnych, łatwych do odczytania komponentów HTML, stylów o ograniczonym zakresie i fragmentów zmiennych „stanowych” JavaScriptu. React, Vue, Svelte, itp. oferują tak wiele udogodnień do debugowania i testowania, że ​​zwykła manipulacja DOM nie może się równać.

Oto moje pytanie za milion dolarów:

Czy możemy zacząć używać prostych szablonów HTML i stopniowo dodawać komponenty React/Vue/Svelte tam, gdzie chcemy?

Odpowiedź brzmi: tak . Spróbujmy.

11ty + Vite: Mecz stworzony w niebie ️

Oto sen, który sobie tutaj wyobrażam. Gdziekolwiek chcę wstawić coś interaktywnego, chcę zostawić małą flagę w moim szablonie, aby „umieścić tutaj komponent X React”. Może to być składnia shortcode obsługiwana przez 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' %}

Pamiętaj jednak, że jednoczęściowe 11ty (celowo) unikają: sposobu na spakowanie całego kodu JavaScript. Pochodzący z gildii sprzedaży wiązanej OG, twój mózg prawdopodobnie przeskakuje do budowania tutaj procesów Webpack, Rollup lub Babel. Zbuduj duży, stary plik punktu wejścia i wypisz piękny, zoptymalizowany kod, prawda?

No tak, ale to może być bardzo zaangażowane. Jeśli na przykład używamy komponentów React, prawdopodobnie będziemy potrzebować programów ładujących dla JSX, wymyślnego procesu Babel do przekształcenia wszystkiego, interpretera dla importu modułów SASS i CSS, czegoś , co pomoże w ponownym ładowaniu na żywo i tak dalej.

Gdyby tylko istniało narzędzie, które mogłoby po prostu zobaczyć nasze pliki .jsx i dokładnie wiedzieć, co z nimi zrobić.

Wpisz: Vite

Ostatnio miasto mówiło o Vite. Ma być uniwersalnym narzędziem do budowania niemal wszystkiego w JavaScript. Oto przykład, który możesz wypróbować w domu. Stwórzmy pusty katalog gdzieś na naszej maszynie i zainstalujmy kilka zależności:

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

Teraz możemy utworzyć plik index.html , który będzie służył jako „punkt wejścia” naszej aplikacji. Zachowamy to całkiem prosto:

 <!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>

Jedynym interesującym fragmentem jest ten div id="root" w środku. Za chwilę będzie to podstawa naszego komponentu React!

Jeśli chcesz, możesz uruchomić serwer Vite, aby zobaczyć nasz zwykły plik HTML w przeglądarce. Po prostu uruchom vite (lub npx vite , jeśli polecenie nie zostało skonfigurowane w twoim terminalu), a zobaczysz ten pomocny wynik:

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

Podobnie jak Browsersync lub inne popularne serwery deweloperskie, nazwa każdego pliku .html odpowiada trasie na naszym serwerze. Więc gdybyśmy zmienili nazwę index.html na about.html , odwiedzilibyśmy http://localhost:3000/about/ (tak, będziesz potrzebować końcowego ukośnika!)

Zróbmy teraz coś ciekawego. Oprócz tego pliku index.html dodaj pewnego rodzaju podstawowy komponent React. Użyjemy tutaj useState , aby zademonstrować interaktywność:

 // 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> ) }

Teraz załadujmy ten komponent na naszą stronę. To wszystko, co musimy dodać do naszego 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>

Tak, to jest to. Nie ma potrzeby samodzielnego przekształcania naszego pliku .jsx w gotowy do przeglądarki plik .js ! Gdziekolwiek Vite zobaczy import .jsx , automatycznie przekonwertuje ten plik na zrozumiały dla przeglądarek. Podczas pracy nad programowaniem nie ma nawet folderu dist ani build ; Vite przetwarza wszystko w locie — wraz z ponownym ładowaniem gorącego modułu za każdym razem, gdy zapisujemy nasze zmiany.

OK, więc mamy niesamowicie wydajne narzędzie do budowania. Jak możemy wprowadzić to do naszych 11-tysięcznych szablonów?

Bieganie Vite obok 11tys

Zanim przejdziemy do dobrych rzeczy, omówmy prowadzenie 11ty i Vite obok siebie. Śmiało i zainstaluj 11ty jako zależność dev w tym samym katalogu projektu z ostatniej sekcji:

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

Teraz zróbmy mały test przed lotem, aby sprawdzić, czy 11ty działa. Aby uniknąć nieporozumień, proponuję:

  1. Usuń wcześniejszy plik index.html ;
  2. Przenieś ten TimesWeMispronouncedVite.jsx do nowego katalogu. Powiedz, components/ ;
  3. Utwórz folder src , w którym będzie mieszkać nasza strona internetowa;
  4. Dodaj szablon do tego katalogu src do przetworzenia przez 11ty.

Na przykład plik blog-post.md z następującą zawartością:

 # Hello world! It's markdown here

Struktura twojego projektu powinna wyglądać mniej więcej tak:

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

Teraz uruchom 11ty z terminala w ten sposób:

 npx eleventy --input=src

Jeśli wszystko pójdzie dobrze, powinieneś zobaczyć wynik kompilacji w następujący sposób:

 _site/ blog-post/ index.html

Gdzie _site jest naszym domyślnym katalogiem wyjściowym, a blog-post/index.html to nasz plik przekonwertowany do przeglądania.

Normalnie uruchomilibyśmy npx eleventy --serve , aby uruchomić serwer deweloperski i odwiedzić tę stronę /blog-post . Ale teraz używamy Vite na naszym serwerze deweloperskim! Celem jest:

  1. Jedenaście zbuduje naszą przecenę, mopsa, nunjucks i więcej w katalogu _site .
  2. Wskaż Vite na ten sam katalog _site , aby mógł przetwarzać komponenty React, importy fantazyjnych stylów i inne rzeczy, których 11ty nie wykrył.

A więc dwuetapowy proces budowania, z 11tymi przekazaniem Vite. Oto polecenie CLI, którego potrzebujesz, aby jednocześnie uruchomić 11ty i Vite w trybie „zegarka”:

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

Możesz także uruchomić te polecenia w dwóch oddzielnych terminalach, aby ułatwić debugowanie.

Przy odrobinie szczęścia powinieneś być w stanie odwiedzić http://localhost:3000/blog-post/ (ponownie, nie zapomnij o końcowym ukośniku!), aby zobaczyć przetworzony plik Markdown.

Częściowe nawodnienie za pomocą skrótów

Zróbmy krótkie podsumowanie krótkich kodów. Czas wrócić do tej składni z wcześniejszej wersji:

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

Dla tych, którzy nie znają skrótów: są one mniej więcej takie same jak wywołanie funkcji, w której funkcja zwraca ciąg kodu HTML, który należy wsunąć na stronę. „Anatomia” naszego shortcode to:

  • {% … %}
    Wrapper oznaczający początek i koniec shortcode.
  • react
    Nazwę naszej funkcji shortcode skonfigurujemy za chwilę.
  • '/components/TimesWeMispronouncedVite.jsx'
    Pierwszy (i jedyny) argument naszej funkcji shortcode. Możesz mieć tyle argumentów, ile chcesz.

Podłączmy nasz pierwszy krótki kod! Dodaj plik .eleventy.js do bazy swojego projektu i dodaj ten wpis konfiguracyjny dla naszego krótkiego kodu 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', } } }

Teraz urozmaicmy nasz blog-post.md naszym nowym shortcode. Wklej tę treść do naszego pliku przecen:

 # 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' %}

A jeśli uruchomisz szybki npx eleventy , powinieneś zobaczyć to wyjście w swoim katalogu _site w /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>

Pisanie naszego skrótu do komponentów

Teraz zróbmy coś pożytecznego z tym shortcodem. Pamiętasz ten tag script , który napisaliśmy podczas testowania Vite? Cóż, możemy zrobić to samo w naszym shortcode! Tym razem użyjemy argumentu componentPath do wygenerowania importu, ale resztę zachowaj prawie bez zmian:

 // .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', } } }

Teraz wywołanie naszego shortcode (np. {% react '/components/TimesWeMispronouncedVite.jsx' %} ) powinno dać coś takiego:

 <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>

Odwiedzając nasz serwer deweloperski za pomocą (npx eleventy --watch) & vite _site , powinniśmy znaleźć pięknie klikalny element licznika.

Buzzword Alert — częściowe nawodnienie i architektura wysp

Właśnie zademonstrowaliśmy „architekturę wysp” w najprostszej formie. To jest idea, że ​​nasze interaktywne drzewa komponentów nie muszą pochłaniać całej witryny. Zamiast tego możemy tworzyć mini-drzewa lub „wyspy” w całej naszej aplikacji, w zależności od tego, gdzie faktycznie potrzebujemy tej interaktywności. Masz podstawową stronę docelową z linkami bez żadnego stanu do zarządzania? Świetnie! Nie ma potrzeby stosowania interaktywnych komponentów. Ale czy masz wieloetapowy formularz, który mógłby skorzystać z biblioteki X React? Nie ma problemu. Użyj takich technik, aby react na krótki kod, aby rozkręcić wyspę Form.jsx .

Idzie to w parze z ideą „częściowego nawodnienia”. Prawdopodobnie słyszałeś termin „nawodnienie”, jeśli pracujesz z komponentami SSG, takimi jak NextJS lub Gatsby. Krótko mówiąc, jest to sposób na:

  1. Najpierw renderuj swoje komponenty do statycznego kodu HTML.
    Daje to użytkownikowi coś do wyświetlenia, gdy początkowo odwiedza Twoją witrynę.
  2. „Nawodnij” ten kod HTML z interaktywnością.
    W tym miejscu podłączamy nasze zaczepy stanu i renderery, aby, no cóż, kliknięcia przycisków faktycznie coś wyzwoliły.

To 1-2 uderzenie sprawia, że ​​frameworki oparte na JS są opłacalne dla stron statycznych. Tak długo, jak użytkownik ma coś do wyświetlenia, zanim Twój JavaScript zostanie przetworzony, uzyskasz przyzwoity wynik w tych wskaźnikach latarni.

Cóż, dopóki tego nie zrobisz. „Nawadnianie” całej witryny może być kosztowne, ponieważ będziesz potrzebować pakietu JavaScript gotowego do przetworzenia każdego ostatniego elementu DOM . Ale nasza technika scrappy shortcode nie obejmuje całej strony! Zamiast tego „częściowo” nawilżamy zawartość, która tam jest, wstawiając komponenty tylko tam, gdzie jest to konieczne.

Nie martw się, jest wtyczka do tego wszystkiego: Slinkity

Podsumujmy, co tutaj odkryliśmy:

  1. Vite to niesamowicie wydajny pakiet, który może przetwarzać większość typów plików ( jsx , vue i svelte , żeby wymienić tylko kilka) bez dodatkowej konfiguracji.
  2. Skróty to łatwy sposób na wstawianie fragmentów kodu HTML do naszych szablonów w stylu komponentów.
  3. Możemy użyć skrótów do renderowania dynamicznych, interaktywnych pakietów JS gdziekolwiek chcemy, używając częściowego uwodnienia.

A co ze zoptymalizowanymi kompilacjami produkcyjnymi? Prawidłowo ładujesz style z zakresem? Heck, używasz .jsx do tworzenia całych stron? Cóż, połączyłem to wszystko (i wiele więcej!) w projekt o nazwie Slinkity. Jestem podekscytowany, widząc ciepłe przyjęcie projektu przez społeczność i chciałbym, drogi czytelniku, żebyś sam go zakręcił!

Wypróbuj przewodnik szybkiego startu

Astro też jest świetne

Czytelnicy mający oko na najnowocześniejszą technologię prawdopodobnie myśleli o Astro przynajmniej raz. I nie mogę cię winić! Został zbudowany z dość podobnym celem: zacznij od zwykłego HTML i wstawiaj komponenty stanowe tam, gdzie ich potrzebujesz. Heck, pozwolą Ci nawet zacząć pisać komponenty React w komponentach Vue lub Svelte w plikach szablonów HTML! To jak edycja MDX Xtreme.

Ich podejście wiąże się jednak z jednym poważnym kosztem: musisz napisać swoją aplikację od zera. Oznacza to nowy format szablonu oparty na JSX (z którym możesz nie czuć się komfortowo), zupełnie nowy potok danych, w którym obecnie brakuje kilku drobiazgów, oraz ogólne błędy podczas rozwiązywania problemów.

Ale rozkręcenie koktajlu 11ty + Vite za pomocą narzędzia takiego jak Slinkity? Cóż, jeśli masz już witrynę 11ty, Vite powinien wskoczyć na miejsce bez żadnych przepisywania, a skróty powinny obejmować wiele takich samych przypadków użycia, jak pliki .astro . Przyznam, że w tej chwili jest to dalekie od ideału. Ale hej, jak dotąd było to przydatne i myślę, że jest to całkiem silna alternatywa, jeśli chcesz uniknąć przepisywania całej witryny!

Zawijanie

Ten eksperyment Slinkity do tej pory całkiem dobrze służył moim potrzebom (i kilku z was też!). Możesz swobodnie używać dowolnego stosu dla Twojego JAM. Jestem po prostu podekscytowany, że mogę podzielić się wynikami mojego roku rozpusty w narzędziach do budowania i nie mogę się doczekać, aby zobaczyć, jak możemy zlikwidować wielki podział Jamstack.

Dalsza lektura

Chcesz głębiej zagłębić się w częściowe nawodnienie, ESM lub ogólnie SSG? Sprawdź te:

  • Architektura wysp
    Ten wpis na blogu Jason Format naprawdę zapoczątkował dyskusję na temat „wysp” i „częściowego nawodnienia” w tworzeniu stron internetowych. Jest pełen przydatnych diagramów i filozofii stojącej za pomysłem.
  • Uprość swoją statykę za pomocą niestandardowego generatora stron statycznych
    Kolejny artykuł SmashingMag, który przeprowadzi Cię przez proces tworzenia od podstaw kreatorów stron internetowych opartych na węzłach. To była dla mnie ogromna inspiracja!
  • Jak moduły ES na nowo zdefiniowały tworzenie stron internetowych
    Osobisty post o tym, jak moduły ES zmieniły grę w tworzenie stron internetowych. To zagłębia się nieco dalej w „kiedyś i teraz” składni importu w Internecie.
  • Wprowadzenie do komponentów webowych
    Doskonały przewodnik po tym, czym są komponenty sieciowe, jak działa shadow DOM i gdzie komponenty sieciowe okazują się przydatne. Wykorzystałem ten przewodnik, aby zastosować niestandardowe komponenty we własnym frameworku!