Создание SSG, о котором я всегда мечтал: 11ty, Vite и JAM Sandwich
Опубликовано: 2022-03-10Не знаю, как вы, но я был ошеломлен всеми инструментами веб-разработки, которые у нас есть в наши дни. Любите ли вы Markdown, простой HTML, React, Vue, Svelte, шаблоны Pug, Handlebars, Vibranium — вы, вероятно, можете смешать их с некоторыми данными CMS и получить хороший коктейль статического сайта.
Я не собираюсь говорить вам, какие инструменты разработки пользовательского интерфейса использовать, потому что все они великолепны — в зависимости от потребностей вашего проекта. Этот пост посвящен поиску идеального генератора статических сайтов для любого случая; что-то, что позволяет нам использовать шаблоны без JS, такие как уценка, для начала и добавлять «островки» интерактивности, управляемой компонентами, по мере необходимости.
Я собираю знания за год в один пост. Мы не только поговорим о коде (т.е. склеиваем вместе 11ty и Vite), но также собираемся выяснить, почему этот подход настолько универсален для задач Jamstackian. Мы коснемся:
- Два подхода к созданию статических сайтов и почему мы должны восполнить пробел;
- Где языки шаблонов, такие как Pug и Nunjucks, все еще оказываются полезными;
- Когда в игру должны вступить фреймворки компонентов, такие как React или Svelte;
- Как новый мир Vite с горячей перезагрузкой помогает нам привнести интерактивность JS в наш HTML практически без конфигураций;
- Как это дополняет каскад данных 11ty, перенося данные CMS в любую компонентную структуру или HTML-шаблон, который вы можете захотеть.
Итак, без лишних слов, вот мой рассказ об ужасных сценариях сборки, прорывах в сборщиках и изоленте спагетти-кода, которые (в конечном итоге) дали мне SSG, о котором я всегда мечтал: сэндвич 11ty, Vite и Jam под названием Slinkity!
Большой разрыв в создании статических сайтов
Прежде чем углубиться, я хочу обсудить то, что я назову двумя «лагерями» в создании статических сайтов.
В первом лагере у нас есть «простой» генератор статических сайтов. Эти инструменты не содержат пакетов JavaScript, одностраничных приложений и любых других модных словечек, которые мы привыкли ожидать. Они просто придерживаются основ Jamstack: извлекают данные из любого JSON-объекта CMS, который вы предпочитаете, и помещают эти данные в простые HTML-шаблоны + CSS. Такие инструменты, как Jekyll, Hugo и 11ty, доминируют в этом лагере, позволяя превратить каталог уцененных и ликвидных файлов в полнофункциональный веб-сайт. Ключевые преимущества:
- Неглубокая кривая обучения
Если вы знаете HTML, вы готовы к работе! - Быстрое время сборки
Мы не обрабатываем ничего сложного, поэтому каждый маршрут строится в мгновение ока. - Мгновенное время для интерактивного
На клиенте нет (или очень мало) JavaScript для анализа.
Теперь во втором лагере у нас есть «динамический» генератор статических сайтов. В них представлены фреймворки компонентов, такие как React, Vue и Svelte, чтобы сделать ваш Jamstack интерактивным. Они выполняют то же основное обещание объединения данных CMS с маршрутами вашего сайта во время сборки. Ключевые преимущества:
- Создан для интерактивности
Нужна карусель с анимированными изображениями? Многоступенчатая форма? Просто добавьте компонентный самородок HTML, CSS и JS. - Государственное управление
Что-то вроде React Context в магазинах Svelte позволяет беспрепятственно обмениваться данными между маршрутами. Например, корзина на вашем сайте электронной коммерции.
У любого подхода есть явные плюсы. Но что, если вы выберете SSG из первого лагеря, такого как Jekyll, только для того, чтобы через шесть месяцев вашего проекта понять, что вам нужна некоторая компонентная интерактивность? Или вы выбираете что-то вроде NextJS для этих мощных компонентов только для того, чтобы бороться с кривой обучения React или ненужными килобайтами JavaScript в статичном посте в блоге?
По моему мнению, немногие проекты полностью вписываются в тот или иной лагерь. Они существуют в широком спектре, постоянно отдавая предпочтение новым наборам функций по мере развития потребностей проекта. Так как же нам найти решение, которое позволит нам начать с простых инструментов из первого лагеря и постепенно добавлять функции из второго, когда они нам понадобятся?
Что ж, давайте немного пройдемся по моему учебному путешествию.
Примечание. Если вы уже продали статические шаблоны с 11ty для создания своих статических сайтов, не стесняйтесь переходить к сочному пошаговому руководству по коду.
Переход от компонентов к шаблонам и веб-API
Еще в январе 2020 года я решил сделать то, что почти каждый веб-разработчик делает каждый год: перестроить свой личный сайт. Но на этот раз все должно было быть иначе. Я поставил перед собой задачу создать сайт со связанными за спиной руками, без фреймворков и пайплайнов сборки!
Это была непростая задача для приверженца React. Но с высоко поднятой головой я решил построить свой собственный конвейер сборки с нуля. Есть много плохо написанного кода, которым я мог бы поделиться из версии 1 моего личного сайта… но я позволю вам щелкнуть этот README, если вы настолько смелы. Вместо этого я хочу сосредоточиться на выводах более высокого уровня, которые я усвоил, изголодав себя от своих JS-удовольствий.
Шаблоны идут намного дальше, чем вы думаете
Я пришел на этот проект выздоравливающим наркоманом JavaScript. Есть несколько потребностей, связанных со статическими сайтами, которые мне нравились с помощью фреймворков на основе компонентов:
- Мы хотим разбить мой сайт на повторно используемые компоненты пользовательского интерфейса , которые могут принимать объекты JS в качестве параметров (так называемые «реквизиты»).
- Нам нужно получить некоторую информацию во время сборки , чтобы попасть на рабочий сайт.
- Нам нужно сгенерировать кучу URL-маршрутов либо из каталога файлов, либо из толстого объекта содержимого JSON.
Список взят из этого поста в моем личном блоге.
Но вы, возможно, заметили… ни одному из них на самом деле не нужен клиентский JavaScript. Фреймворки компонентов, такие как React, в основном созданы для решения проблем управления состоянием, например, веб-приложение Facebook, в первую очередь вдохновляющее React. Если вы просто разбиваете свой сайт на небольшие компоненты или элементы системы дизайна, такие шаблоны, как Pug, тоже подойдут!
Возьмем, к примеру, эту панель навигации. В Pug мы можем определить «миксин», который получает данные в качестве реквизита:
// nav-mixins.pug mixin NavBar(links) // pug's version of a for loop each link in links a(href=link.href) link.text
Затем мы можем применить этот миксин в любом месте нашего сайта.
// index.pug // kinda like an ESM "import" include nav-mixins.pug html body +NavBar(navLinksPassedByJS) main h1 Welcome to my pug playground
Если мы «рендерим» этот файл с некоторыми данными, мы получим красивый index.html
для обслуживания наших пользователей.
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)
Конечно, это не дает таких тонкостей, как CSS с ограниченной областью действия для ваших миксинов или JavaScript с отслеживанием состояния, где вы этого хотите. Но у него есть очень важные преимущества перед чем-то вроде React:
- Нам не нужны причудливые упаковщики, которых мы не понимаем.
Мы только что написали этот вызовpug.render
вручную, и у нас уже есть первый маршрут сайта, готовый к развертыванию. - Мы не отправляем JavaScript конечному пользователю.
Использование React часто означает отправку большой среды выполнения ole для запуска браузеров людей. Вызывая такую функцию, какpug.render
, во время сборки, мы сохраняем весь JS на своей стороне, а в конце отправляем чистый.html
-файл.
Вот почему я считаю шаблоны отличной «базой» для статических сайтов. Тем не менее, было бы неплохо иметь возможность использовать фреймворки компонентов там, где мы действительно извлекаем из них пользу. Подробнее об этом позже.
Рекомендуемая литература : Как создавать лучшие шаблоны Angular с помощью Pug от Zara Cooper
Вам не нужен фреймворк для создания одностраничных приложений
Пока я этим занимался, я также хотел несколько сексуальных переходов страниц на своем сайте. Но как сделать что-то подобное без фреймворка?
Что ж, мы не можем этого сделать, если каждая страница представляет собой отдельный файл .html
. Весь браузер обновляется, когда мы переходим от одного HTML-файла к другому, поэтому у нас не может быть такого приятного эффекта плавного перехода (поскольку мы ненадолго покажем обе страницы друг над другом).
Нам нужен способ «извлекать» HTML и CSS для того места, куда мы переходим, и анимировать их для просмотра с помощью JavaScript. Это звучит как работа для одностраничных приложений! Для этого я использовал простую смесь API браузера:
- Перехватывайте все клики по ссылкам с помощью прослушивателя событий.
- fetch API : извлеките все ресурсы для любой страницы, которую вы хотите посетить, и захватите часть, которую я хочу анимировать, в поле зрения: содержимое за пределами панели навигации (которое я хочу оставаться неподвижным во время анимации).
- API веб-анимации : анимируйте новый контент в виде ключевого кадра.
- API истории : измените маршрут, отображаемый в адресной строке вашего браузера, с помощью
window.history.pushState({}, 'new-route')
. В противном случае создается впечатление, что вы никогда не покидали предыдущую страницу!
Для ясности вот наглядная иллюстрация концепции этого одностраничного приложения с использованием простого поиска и замены ( исходная статья ):
Примечание . Вы также можете посетить исходный код с моего личного сайта.
Конечно, некоторое сочетание React и др. и выбранной вами библиотеки анимации может сделать это. Но для такого простого варианта использования, как плавный переход… веб-API чертовски эффективны сами по себе. А если вам нужны более надежные переходы страниц в статических шаблонах, таких как Pug или простой HTML, вам пригодятся такие библиотеки, как Swup.
Что 11ty принес к столу
В этот момент я чувствовал себя довольно хорошо по поводу своего маленького SSG. Конечно, он не мог получить какие-либо данные CMS во время сборки, не поддерживал разные макеты по страницам или каталогам, не оптимизировал мои изображения и не имел инкрементных сборок.
Хорошо, мне может понадобиться помощь.
Учитывая все, что я узнал из v1, я думал, что заслужил право отказаться от правила «запрет сторонних конвейеров сборки» и использовать существующие инструменты. Оказывается, у 11ty есть кладезь функций, которые мне нужны!
- Извлечение данных во время сборки с использованием файлов
.11ydata.js
; - Глобальные данные доступны для всех моих шаблонов из папки
_data
; - Горячая перезагрузка во время разработки с помощью browsersync;
- Поддержка причудливых преобразований HTML;
- …и множество других вкусностей.
Если вы пробовали простые SSG, такие как Jekyll или Hugo, у вас должно быть довольно хорошее представление о том, как работает 11ty. Только разница? 11ty полностью использует JavaScript.
11ty поддерживает практически все существующие библиотеки шаблонов, поэтому он был рад отобразить все мои страницы Pug в маршрутах .html
. Эта опция цепочки макетов помогла и с моей настройкой фальшивого одностраничного приложения. Мне просто нужен был один 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?
Пока этот main.js
выполняет все те перехваты ссылок, которые мы исследовали, у нас есть переходы между страницами!
О, и каскад данных
Итак, 11ty помог очистить весь мой спагетти-код от v1. Но это принесло еще одну важную деталь: чистый API для загрузки данных в мои макеты. Это хлеб с маслом подхода Jamstack. Вместо того, чтобы получать данные в браузере с помощью JavaScript + DOM, вы можете:
- Извлекать данные во время сборки с помощью Node.
Это может быть вызов какого-либо внешнего API, локальный импорт JSON или YAML или даже содержимое других маршрутов на вашем сайте (представьте, что оглавление обновляется всякий раз, когда добавляются новые маршруты). - Вставьте эти данные в свои маршруты. Вспомните функцию
.render
, которую мы написали ранее:
const html = pug.render('/index.pug', { navLinksPassedByJS: [ { href: '/', text: 'Home' }, { href: '/adopt', text: 'Adopt a Pug' } ] })
…но вместо того, чтобы каждый раз вызывать pug.render
с нашими данными, мы позволяем 11ty делать это за кулисами.
Конечно, у меня не было много данных для моего личного сайта. Но было здорово создать файл .yaml
для всех моих личных проектов:
# _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 ...
И получить доступ к этим данным в любом шаблоне:
// home.pug .project-carousel each work in works h3 #{title} p #{timeframe} each tag in tags ...
Исходя из мира «рендеринга на стороне клиента» с приложением create-react-app, это было довольно большим открытием. Больше не нужно отправлять ключи API или большие двоичные объекты JSON в браузер.
Я также добавил некоторые улучшения для получения JavaScript и улучшения анимации по сравнению с версией 1 моего сайта. Если вам интересно, вот где стоял мой README на данный момент.
Я был счастлив в этот момент, но чего-то не хватало
Я зашел на удивление далеко, отказавшись от компонентов на основе JS и приняв шаблоны (с анимированными переходами между страницами). Но я знаю, что это не будет удовлетворять мои потребности навсегда. Помнишь ту большую пропасть, с которой я столкнул нас? Ну, очевидно, что между моей настройкой сборки (устойчиво в лагере №1) и убежищем JS-ориентированной интерактивности (Next, SvelteKit и многое другое из лагеря №2) все еще есть овраг. Скажем, я хочу добавить:
- всплывающее окно с переключателем открытия/закрытия,
- система дизайна на основе компонентов, такая как Material UI, в комплекте со стилем области действия,
- сложная многошаговая форма, возможно управляемая конечным автоматом.
Если вы приверженец простого JS, у вас, вероятно, есть ответы на все эти варианты использования без фреймворка. Но есть причина, по которой JQuery больше не является нормой! Есть что-то привлекательное в создании отдельных, легко читаемых компонентов HTML, стилей с ограниченной областью действия и фрагментов переменных «состояния» JavaScript. React, Vue, Svelte и т. д. предлагают так много тонкостей для отладки и тестирования, что прямое манипулирование DOM не может полностью соответствовать.
Итак, вот мой вопрос на миллион долларов:
Можем ли мы начать с простых HTML-шаблонов и постепенно добавлять компоненты React/Vue/Svelte там, где мы хотим?
Ответ - да . Давай попробуем.
11ty + Vite: матч, заключенный на небесах ️
Вот сон, который я воображаю здесь. Везде, где я хочу вставить что-то интерактивное, я хочу оставить в своем шаблоне небольшой флажок, чтобы «поместить здесь компонент X React». Это может быть синтаксис шорткода, который поддерживает 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' %}
Но помните, цельный 11ty (намеренно) избегается: способ связать весь ваш JavaScript. Выйдя из гильдии бандлинга OG, ваш мозг, вероятно, перейдет к созданию процессов Webpack, Rollup или Babel. Создайте большой файл точки входа ole и выведите красивый оптимизированный код, верно?
Ну да, но это может быть довольно сложно. Например, если мы используем компоненты React, нам, вероятно, понадобятся некоторые загрузчики для JSX, причудливый процесс Babel для преобразования всего, интерпретатор для импорта модулей SASS и CSS, что-то, что поможет с перезагрузкой в реальном времени, и так далее.
Если бы только существовал инструмент, который мог бы просто видеть наши файлы .jsx
и точно знать, что с ними делать.
Введите: Вите
Вите в последнее время стал притчей во языцех. Это должен быть универсальный инструмент для создания практически всего на JavaScript. Вот пример для вас, чтобы попробовать дома. Давайте создадим пустой каталог где-нибудь на нашей машине и установим некоторые зависимости:
npm init -y # Make a new package.json with defaults set npm i vite react react-dom # Grab Vite + some dependencies to use React
Теперь мы можем создать файл index.html
, который будет служить «точкой входа» нашего приложения. Мы будем держать это довольно просто:
<!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>
Единственный интересный момент — это div id="root"
посередине. Через мгновение это будет корнем нашего компонента React!
Если вы хотите, вы можете запустить сервер Vite, чтобы увидеть наш обычный HTML-файл в своем браузере. Просто запустите vite
(или npx vite
, если команда не настроена в вашем терминале), и вы увидите следующий полезный вывод:
vite vX.XX dev server running at: > Local: http://localhost:3000/ > Network: use `--host` to expose ready in Xms.
Подобно Browsersync или другим популярным серверам разработки, имя каждого файла .html
соответствует маршруту на нашем сервере. Поэтому, если бы мы переименовали index.html
в about.html
, мы бы посетили http://localhost:3000/about/
(да, вам понадобится косая черта!)
Теперь займемся чем-нибудь интересным. Наряду с этим файлом index.html
добавьте какой-нибудь базовый компонент React. Здесь мы будем использовать useState
React для демонстрации интерактивности:
// 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> ) }
Теперь давайте загрузим этот компонент на нашу страницу. Это все, что нам нужно добавить в наш 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>
Да, это оно. Нет необходимости самостоятельно преобразовывать наш файл .jsx
в готовый для браузера файл .js
! Везде, где Vite видит импорт .jsx
, он автоматически преобразует этот файл во что-то, что браузеры могут понять. При разработке нет даже папки dist
или build
; Vite обрабатывает все на лету — в комплекте с горячей перезагрузкой модуля каждый раз, когда мы сохраняем наши изменения.
Итак, у нас есть невероятно мощный инструмент для сборки. Как мы можем перенести это в наши 110 шаблонов?
Запуск Vite вместе с 11ty
Прежде чем мы перейдем к хорошим вещам, давайте обсудим работу 11ty и Vite бок о бок. Продолжайте и установите 11ty в качестве зависимости разработчика в тот же каталог проекта, что и в предыдущем разделе:
npm i -D @11ty/eleventy # yes, it really is 11ty twice
Теперь давайте проверим перед полетом, работает ли 11ty. Чтобы не было путаницы, я предлагаю вам:
- Удалите этот файл
index.html
из более раннего; - Переместите этот
TimesWeMispronouncedVite.jsx
в новый каталог. Скажем,components/
; - Создайте папку
src
для нашего веб-сайта; - Добавьте шаблон в этот каталог
src
для обработки 11ty.
Например, файл blog-post.md
со следующим содержимым:
# Hello world! It's markdown here
Структура вашего проекта должна выглядеть примерно так:
src/ blog-post.md components/ TimesWeMispronouncedVite.jsx
Теперь запустите 11ty с вашего терминала следующим образом:
npx eleventy --input=src
Если все пойдет хорошо, вы должны увидеть вывод сборки, подобный этому:
_site/ blog-post/ index.html
Где _site
— наш выходной каталог по умолчанию, а blog-post/index.html
— наш файл уценки, красиво преобразованный для просмотра.
Обычно мы запускаем npx eleventy --serve
, чтобы запустить сервер разработки и посетить страницу /blog-post
. Но сейчас мы используем Vite для нашего сервера разработки! Цель здесь состоит в том, чтобы:
- Пусть одиннадцать создадут наши markdown, Pug, nunjucks и многое другое в каталоге
_site
. - Укажите Vite в том же каталоге
_site
, чтобы он мог обрабатывать компоненты React, импорт причудливых стилей и другие вещи, которые 11ty не уловил.
Итак, двухэтапный процесс сборки, когда 11ty передают Vite. Вот команда CLI, которая вам понадобится для одновременного запуска 11ty и Vite в режиме «просмотра»:
(npx eleventy --input=src --watch) & npx vite _site
Вы также можете запускать эти команды в двух отдельных терминалах для упрощения отладки.
Если повезет, вы сможете посетить http://localhost:3000/blog-post/
(опять же, не забудьте косую черту в конце!), чтобы увидеть обработанный файл Markdown.
Частичная гидратация с помощью шорткодов
Давайте сделаем краткое изложение шорткодов. Пришло время вернуться к предыдущему синтаксису:
{% react '/components/TimesWeMispronouncedVite.jsx' %}
Для тех, кто не знаком с шорткодами: они примерно такие же, как и вызов функции, когда функция возвращает строку HTML для перехода на вашу страницу. «Анатомия» нашего шорткода такова:
-
{% … %}
Обертка, обозначающая начало и конец шорткода. -
react
Имя нашей функции шорткода мы настроим через мгновение. -
'/components/TimesWeMispronouncedVite.jsx'
Первый (и единственный) аргумент нашей функции шорткода. Вы можете иметь столько аргументов, сколько захотите.
Давайте подключим наш первый шорткод! Добавьте файл .eleventy.js
в базу вашего проекта и добавьте эту запись конфигурации для нашего шорткода 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', } } }
Теперь давайте оживим наш blog-post.md
нашим новым шорткодом. Вставьте этот контент в наш файл уценки:
# 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' %}
И если вы запустите быстрый npx eleventy
, вы должны увидеть этот вывод в вашем каталоге _site
в /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>
Пишем шорткод нашего компонента
Теперь давайте сделаем что-нибудь полезное с этим шорткодом. Помните тот тег script
, который мы написали, когда пробовали Vite? Ну, мы можем сделать то же самое в нашем шорткоде! На этот раз мы будем использовать аргумент componentPath
для генерации импорта, но оставим все остальное почти таким же:
// .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', } } }
Теперь вызов нашего шорткода (например, {% react '/components/TimesWeMispronouncedVite.jsx' %}
) должен вывести что-то вроде этого:
<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>
Посетив наш сервер разработки с помощью (npx eleventy --watch) & vite _site
, мы должны найти красиво кликабельный элемент счетчика.
Предупреждение о модном слове — частичная гидратация и островная архитектура
Мы только что продемонстрировали «островную архитектуру» в ее простейшей форме. Это идея о том, что наши деревья интерактивных компонентов не должны занимать весь веб-сайт. Вместо этого мы можем раскручивать мини-деревья или «острова» в нашем приложении в зависимости от того, где нам действительно нужна эта интерактивность. У вас есть базовая целевая страница со ссылками без какого-либо состояния для управления? Здорово! Нет необходимости в интерактивных компонентах. Но есть ли у вас многошаговая форма, которая могла бы извлечь выгоду из библиотеки X React? Без проблем. Используйте методы, подобные этому, чтобы Form.jsx
react
Это идет рука об руку с идеей «частичной гидратации». Вы, вероятно, слышали термин «гидратация», если вы работаете с компонентными SSG, такими как NextJS или Gatsby. Короче говоря, это способ:
- Сначала визуализируйте свои компоненты в статический HTML.
Это дает пользователю что-то для просмотра, когда он впервые посещает ваш сайт. - «Наполните» этот HTML интерактивностью.
Здесь мы подключаем наши обработчики состояний и рендереры, чтобы заставить нажатия кнопок действительно запускать что-то.
Этот 1-2 шаг делает JS-фреймворки жизнеспособными для статических сайтов. Пока у пользователя есть что просмотреть до того, как ваш JavaScript будет разобран, вы получите приличный балл по этим метрикам-маякам.
Ну, пока не сделаешь. «Гидратация» всего веб-сайта может быть дорогостоящей, поскольку вам понадобится пакет JavaScript, готовый к обработке каждого элемента DOM до последнего . Но наша техника обрывочного шорткода не покрывает всю страницу! Вместо этого мы «частично» увлажняем содержимое, вставляя компоненты только там, где это необходимо.
Не волнуйтесь, для всего этого есть плагин: Slinkity
Давайте резюмируем, что мы здесь обнаружили:
- Vite — невероятно мощный упаковщик, который может обрабатывать большинство типов файлов (
jsx
,vue
иsvelte
, и это лишь некоторые из них) без дополнительной настройки. - Шорткоды — это простой способ вставки фрагментов HTML в наши шаблоны в стиле компонентов.
- Мы можем использовать шорткоды для рендеринга динамических интерактивных пакетов JS везде, где захотим, используя частичную гидратацию.
А как насчет оптимизированных производственных сборок? Правильно загружаете стили с областью видимости? Черт возьми, использовать .jsx
для создания целых страниц? Что ж, я объединил все это (и многое другое!) в проект под названием Slinkity. Я рад видеть, что сообщество тепло восприняло проект, и я хотел бы, чтобы вы, дорогой читатель, попробовали его сами!
Попробуйте краткое руководство
Astro тоже хорош
Читатели, интересующиеся передовыми технологиями , вероятно , уже хотя бы раз думали об Astro. И я не могу винить тебя! Он создан с довольно похожей целью: начать с простого HTML и вставлять компоненты с отслеживанием состояния везде, где они вам нужны. Черт возьми, они даже позволят вам начать писать компоненты React внутри компонентов Vue или Svelte внутри файлов шаблонов HTML! Это как издание MDX Xtreme.
Однако у их подхода есть одна довольно большая цена: вам нужно переписать свое приложение с нуля. Это означает новый формат шаблона, основанный на JSX (который вам может быть неудобен), совершенно новый конвейер данных, в котором прямо сейчас отсутствует пара тонкостей, и общие ошибки, когда они работают с перегибами.
Но раскрутить коктейль 11ty + Vite с помощью такого инструмента, как Slinkity? Что ж, если у вас уже есть 110 сайтов, Vite должен встать на место без каких-либо переделок, а шорткоды должны охватывать многие из тех же вариантов использования, что и файлы .astro
. Я признаю, что сейчас он далек от совершенства. Но эй, до сих пор это было полезно, и я думаю, что это довольно сильная альтернатива, если вы хотите избежать переписывания всего сайта!
Подведение итогов
Этот эксперимент со Slinkity до сих пор довольно хорошо удовлетворял мои потребности (и некоторых из вас тоже!). Не стесняйтесь использовать любой стек, который подходит для вашего JAM. Я просто рад поделиться результатами моего года разврата с инструментами сборки, и я так взволнован, чтобы увидеть, как мы можем преодолеть великий разрыв Jamstack.
Дальнейшее чтение
Хотите глубже погрузиться в частичную гидратацию, или ESM, или SSG в целом? Проверьте это:
- Архитектура островов
Этот пост в блоге от Джейсона Формата действительно положил начало обсуждению «островов» и «частичной гидратации» в веб-разработке. Он полон полезных диаграмм и философии, лежащей в основе этой идеи. - Упростите свои статические сайты с помощью специального генератора статических сайтов.
Еще одна статья SmashingMag, которая проведет вас через создание конструкторов веб-сайтов на основе Node с нуля. Это было огромным вдохновением для меня! - Как модули ES изменили определение веб-разработки
Личный пост о том, как модули ES изменили игру веб-разработки. Это погружает немного глубже в «тогда и сейчас» синтаксис импорта в Интернете. - Введение в веб-компоненты
Отличное пошаговое руководство о том, что такое веб-компоненты, как работает теневая модель DOM и где веб-компоненты могут оказаться полезными. Использовал это руководство, чтобы применить пользовательские компоненты к моей собственной структуре!