Конфигурация
На этой странице
Параметры плагина и необязательные настройки Vite складывайте в sitelo.config.js. Отдельный vite.config.js не нужен.
export default {
site: 'https://example.com',
rss: {
site: 'https://example.com',
title: 'Мой блог',
description: 'Последние записи',
routePrefix: '/blog',
},
vite: {
publicDir: 'static',
build: {
emptyOutDir: true,
outDir: 'public',
},
server: {
port: 8888,
},
},
}Параметры плагина
pagesDir— по умолчанию'src'pageExtensions— какие суффиксы считаются страницамиcleanUrls— по умолчаниюtrue(/about/index.html)site— базовый URL; включаетsitemap.xmlrss— настройки RSS-лентыpagefind—trueили объект параметров; индексирует сайт через Pagefind послеsitelo build(требуетnpm install -D pagefind)images—trueили объект параметров; оптимизирует изображения в разработке и послеsitelo build(требуетnpm install -D sharp)missingAssets—'error'или'warn'linkCheck— битые внутренние ссылки (см. Проверку ссылок)lighthouse— аудит сборки через Lighthouse (см. Аудит Lighthouse)generatedTypesDir— по умолчанию'.sitelo/types'renderConcurrency/renderBatchSize— параллелизм сборкиbuildReport— по умолчаниюtrue; сводка после сборки: страницы, размер вывода, крупнейшие файлы и время по этапам.falseотключает её,{ top }меняет число перечисляемых крупных файловdebug— подробное логированиеdevToolbar— по умолчаниюtrue; поставьтеfalse, чтобы скрыть панель разработчика (исходный файл, параметры, число островов, переключатель viewport)devToolbarDocsUrl— ссылка на документацию в панели (по умолчаниюhttps://sitelo.dev/docs)
Панель разработчика
Пока работает sitelo (dev), небольшая полоса внизу каждой страницы показывает файл страницы, её параметры и количество серверных островов на ней. Кнопка viewport переключает предпросмотр Desktop / Tablet / Mobile (через iframe, чтобы медиазапросы совпадали), а Copy выдаёт отладочный блок для обращений в трекер. В выводе sitelo build она не появляется никогда.
// sitelo.config.js
export default {
devToolbar: false, // скрыть для всех в этом проекте
}Параметры Vite
Всё, что находится под ключом vite, подмешивается в конфигурацию Vite. Флаги CLI (например, --port) важнее обоих.
Если vite.config.js уже есть
Он по-прежнему поддерживается — либо только параметры Vite, либо полный контроль над плагином:
// Только параметры Vite; sitelo всё равно подключит плагин
export default {
publicDir: 'static',
server: { port: 8888 },
}// Подключить плагин самостоятельно
import htmlPages from 'sitelo'
export default {
plugins: [htmlPages({
site: 'https://example.com',
})],
}Если плагин уже подключён в вашей конфигурации Vite, задавайте параметры плагина там — и не дублируйте их как параметры плагина в sitelo.config.js (sitelo выдаст ошибку).
Sitemap и RSS
Задайте site, чтобы создавался dist/sitemap.xml.
RSS:
export default {
rss: {
site: 'https://example.com',
title: 'Мой блог',
description: 'Последние записи',
routePrefix: '/blog',
},
}Создаёт dist/rss.xml с элементом для каждой страницы внутри routePrefix.
Проверка ссылок
Битые <script src> и href таблиц стилей уже прерывают сборку (см. missingAssets). linkCheck закрывает вторую половину: внутренние ссылки <a href>, ведущие на несуществующую страницу.
export default {
linkCheck: true, // 'warn' (по умолчанию), 'error' или объект параметров
}После sitelo build каждая внутренняя ссылка в выводе разрешается, и всё, за чем не стоит страницы, попадает в отчёт, сгруппированный по странице, где встретилось:
[sitelo] 3 битых внутренних ссылок
index.html
../escape -> выходит за пределы каталога сборки
/abuot -> такой страницы нет
/blog/missing-post -> такой страницы нетКак разрешаются ссылки
Проверка идёт по собранному сайту, а не по таблице маршрутов, поэтому учитывает cleanUrls, группы маршрутов, mapOutputPath, файлы, скопированные из public/, и страницы, созданные динамическими маршрутами. Она выполняется после оптимизации изображений и Pagefind, так что видит ровно то, что публикуется. Ссылка верна, когда на неё отвечает настоящий файл, и порядок проверки такой же, как у статического хостинга:
/about→about, затемabout/index.html, затемabout.html/blog/→blog/index.html(завершающая косая черта всегда означает только индекс каталога)/→index.html
Относительные ссылки (../about) разрешаются относительно страницы, где находятся, и те, что выходят за пределы каталога сборки, попадают в отчёт. Строки запроса при разрешении игнорируются: /about?utm=x проверяет /about.
Внешние ссылки никогда не запрашиваются. https://, протокол-относительные //cdn.example.com, mailto:, tel: и прочие схемы пропускаются полностью.
Параметры
| Параметр | По умолчанию | Описание |
|---|---|---|
mode | 'warn' | 'warn' пишет в лог и продолжает; 'error' прерывает сборку — полезно в CI |
exclude | [] | Glob-шаблоны или регулярные выражения href, которые надо пропустить |
checkFragments | false | Дополнительно проверяет, что цели #fragment есть на связанной странице |
export default {
linkCheck: {
mode: 'error', // прервать сборку при битой ссылке
checkFragments: true, // проверять также цели #fragment
exclude: ['/api/**', /^\/legacy\//],
},
}checkFragments выключен по умолчанию, потому что идентификаторы, добавляемые клиентским JavaScript, отсутствуют в собранном HTML и попадали бы в отчёт как отсутствующие. Целями фрагментов считаются и id, и устаревший атрибут якоря name.
Сайты на базовом пути
Если сайт развёрнут по base (скажем, проектный сайт GitHub Pages), любая корневая ссылка без этого базового пути попадёт в отчёт. Ссылка /about на сайте, отдаваемом из /repo/, уводит браузер в корень хоста, а не внутрь вашего сайта — разрешив её по выводу, мы скрыли бы ровно ту ошибку, которую и стоит ловить. Если это сделано намеренно, используйте exclude.
Аудит Lighthouse
sitelo lighthouse проверяет готовую сборку с помощью Lighthouse. Это необязательная peer-зависимость:
npm install -D lighthousesitelo отдаёт dist/ так же, как sitelo preview, направляет headless-Chrome на каждую страницу и печатает оценки:
[sitelo] lighthouse mobile - 3 pages
page perf a11y best seo
/ 98 100 100 100
/docs 95 100 100 100
/docs/routing 97 100 100 100
[sitelo] lighthouse audited 3 pages in 31.4sКаждая страница проверяется по тому URL, который сайт указывает в ссылках, — /docs, а не dist/docs.html, — поэтому cleanUrls, группы маршрутов и base учтены. Задайте пороги, и отчёт станет проверкой: всё, что ниже порога, завершает команду с ошибкой.
export default {
lighthouse: {
exclude: ['404.html'], // страницу 404 проверять обычно незачем
thresholds: {
performance: 90,
accessibility: 100,
'best-practices': 95,
seo: 100,
},
},
}Оценки записываются так, как их показывает Lighthouse (0–100); его собственные доли от 0 до 1 тоже работают. С mode: 'warn' будет только запись в лог.
include/exclude— какие страницы проверять (globs или регулярные выражения)sample— проверять столько случайных страниц на каждый шаблонinclude, а не всеcategories—performance,accessibility,best-practices,seothresholds— минимальная оценка по категорииmode—'error'(по умолчанию) или'warn'formFactor—'mobile'(по умолчанию),'desktop'или обаruns— повторить аудит и взять медианную оценкуoutput/formats— сохранить полный отчёт Lighthouse по каждой страницеflags/config— передаются в Lighthouse как есть, поэтому доступно всё, что понимает его CLIonBuild— проверять и в концеsitelo build
export default {
lighthouse: {
formFactor: 'desktop', // десктопный пресет Lighthouse
runs: 3, // три прогона на страницу, медианная оценка
output: true, // полные отчёты в .sitelo/lighthouse/
onBuild: true, // проверять и в конце sitelo build
flags: { throttlingMethod: 'provided' },
},
}Lighthouse управляет настоящим Chrome: установите его там, где идёт аудит, или укажите путь в CHROME_PATH. Оценки производительности колеблются между прогонами, поэтому перед порогом на них поставьте runs: 3.
Поиск Pagefind
Необязательный статический поиск на Pagefind — это опциональная peer-зависимость. Установите её, когда нужен поиск, затем включите индексацию, разметьте содержимое, подключите интерфейс и запустите sitelo build.
npm install -D pagefind1. Включите индексацию
Поставьте pagefind: true. После sitelo build появится dist/pagefind/ и, по умолчанию, копия в public/pagefind/, чтобы следующий sitelo (dev) или sitelo preview могли отдавать /pagefind/ без пересборки.
export default {
pagefind: true,
}2. Разметьте содержимое и добавьте точку монтирования
Поставьте data-pagefind-body на основное содержимое, чтобы навигация и подвал не индексировались. Оставьте пустой элемент под интерфейс поиска:
export default () => `
<html lang="ru">
<head>
<title>Мой сайт</title>
<link rel="stylesheet" href="/styles.css">
<script type="module" src="/main.js"></script>
</head>
<body>
<header>
<a href="/">Главная</a>
<div id="search"></div>
</header>
<main data-pagefind-body>
<h1>Привет</h1>
<p>Индексируется только эта область.</p>
</main>
</body>
</html>
`import {
html, head, title, link, script, body, header, a, div, main, h1, p,
} from 'javascript-to-html'
export default () =>
html({ lang: 'ru' },
head(
title('Мой сайт'),
link({ rel: 'stylesheet', href: '/styles.css' }),
script({ type: 'module', src: '/main.js' }),
),
body(
header(
a({ href: '/' }, 'Главная'),
div({ id: 'search' }),
),
main({ 'data-pagefind-body': '' },
h1('Привет'),
p('Индексируется только эта область.'),
),
),
)export default function Home() {
return (
<html lang="ru">
<head>
<title>Мой сайт</title>
<link rel="stylesheet" href="/styles.css" />
<script type="module" src="/main.js" />
</head>
<body>
<header>
<a href="/">Главная</a>
<div id="search" />
</header>
<main data-pagefind-body="">
<h1>Привет</h1>
<p>Индексируется только эта область.</p>
</main>
</body>
</html>
)
}3. Подключите интерфейс Pagefind
Загрузите /pagefind/pagefind-ui.js и pagefind-ui.css из своего клиентского скрипта (только после того, как сборка создала индекс):
async function initSearch() {
const mount = document.querySelector('#search')
if (!mount) return
// Индекс появляется только после `sitelo build` (по умолчанию синхронизируется в public/pagefind)
try {
const probe = await fetch('/pagefind/pagefind-ui.js', { method: 'HEAD' })
if (!probe.ok) return
} catch {
return
}
const style = document.createElement('link')
style.rel = 'stylesheet'
style.href = '/pagefind/pagefind-ui.css'
document.head.appendChild(style)
await new Promise((resolve, reject) => {
const script = document.createElement('script')
script.src = '/pagefind/pagefind-ui.js'
script.onload = resolve
script.onerror = reject
document.body.appendChild(script)
})
new window.PagefindUI({
element: '#search',
showImages: false,
})
}
initSearch()4. Соберите и исключите синхронизированную копию из Git
sitelo build
# затем: sitelo preview — или sitelo (dev) с public/pagefindpublic/pagefind/Расширенные параметры (syncPublic, glob, язык, селекторы, …) задаются объектом: pagefind: { syncPublic: false, glob: '**/*.html' }. Все параметры интерфейса: pagefind.app.
404
Создайте src/404.ht.js, чтобы получить dist/404.html. Иначе будет создана аккуратная страница по умолчанию.