Konfiguracja
Na tej stronie
Opcje wtyczki i ewentualne ustawienia Vite wpisz do sitelo.config.js. Żaden vite.config.js nie jest potrzebny.
export default {
site: 'https://example.com',
rss: {
site: 'https://example.com',
title: 'Mój blog',
description: 'Najnowsze wpisy',
routePrefix: '/blog',
},
vite: {
publicDir: 'static',
build: {
emptyOutDir: true,
outDir: 'public',
},
server: {
port: 8888,
},
},
}Opcje wtyczki
pagesDir— domyślnie'src'pageExtensions— które końcówki liczą się jako stronycleanUrls— domyślnietrue(/about/index.html)site— bazowy URL; włączasitemap.xmlrss— konfiguracja kanału RSSpagefind—truealbo obiekt opcji; indeksuje witrynę przez Pagefind positelo build(wymaganpm install -D pagefind)images—truealbo obiekt opcji; optymalizuje obrazy w dev i positelo build(wymaganpm install -D sharp)missingAssets—'error'albo'warn'linkCheck— martwe odnośniki wewnętrzne (zobacz Sprawdzanie odnośników)lighthouse— audyty Lighthouse buildu (zobacz Audyty Lighthouse)generatedTypesDir— domyślnie'.sitelo/types'renderConcurrency/renderBatchSize— równoległość buildubuildReport— domyślnietrue; podsumowanie po buildzie: strony, rozmiar wyniku, największe pliki i czasy faz.falsewyłącza, a{ top }zmienia, ile dużych plików jest wypisanychpruneCss— domyślniefalse;truealbo{ keep }zapisuje arkusz stylów sitelo/ui z samymi regułami, które zbudowane strony potrafią dopasowaćdebug— gadatliwe logowaniedevToolbar— domyślnietrue; ustawfalse, by ukryć pasek widoczny tylko w dev (plik źródłowy, parametry, liczba wysp, przełącznik widoku)devToolbarDocsUrl— odnośnik do dokumentacji na pasku (domyślniehttps://sitelo.dev/docs)
Pasek deweloperski
Gdy sitelo (dev) działa, mały pasek na dole każdej strony pokazuje plik strony, parametry i to, ile wysp serwerowych jest na stronie. Przyciskiem widoku przełączysz podgląd Desktop / Tablet / Mobile (w iframie, więc zapytania medialne się zgadzają), a Copy skopiuje porcję informacji diagnostycznych do zgłoszenia. Na wyniku sitelo build nigdy się nie pojawia.
// sitelo.config.js
export default {
devToolbar: false, // ukryj dla wszystkich w tym projekcie
}Opcje Vite
Wszystko pod kluczem vite jest scalane z konfiguracją Vite. Flagi CLI (na przykład --port) mają pierwszeństwo przed jednym i drugim.
Buildy sitelo ustawiają build.rollupOptions.checks.pluginTimings: false. Inaczej Rolldown zgłasza, że haki wtyczek dominują build, co na witrynie sitelo jest zawsze prawdą — generowanie stron jest buildem — więc wskazywałby tę samą wtyczkę przy każdym uruchomieniu. Ustaw na true pod kluczem vite, gdy profilujesz własne wtyczki.
Istniejący vite.config.js
Nadal wspierany — albo same opcje Vite, albo pełna kontrola nad wtyczką:
// Tylko opcje Vite; sitelo i tak wstrzykuje wtyczkę
export default {
publicDir: 'static',
server: { port: 8888 },
}// Zarejestruj wtyczkę samodzielnie
import htmlPages from 'sitelo'
export default {
plugins: [htmlPages({
site: 'https://example.com',
})],
}Jeśli wtyczka jest już w Twojej konfiguracji Vite, umieść opcje wtyczki tam — a nie dodatkowo jako opcje wtyczki w sitelo.config.js (sitelo zgłosi błąd).
Sitemapa i RSS
Ustaw site, żeby powstała dist/sitemap.xml.
RSS:
export default {
rss: {
site: 'https://example.com',
title: 'Mój blog',
description: 'Najnowsze wpisy',
routePrefix: '/blog',
},
}Tworzy dist/rss.xml z jednym elementem na każdą stronę pod routePrefix.
Sprawdzanie odnośników
Zepsute <script src> i adresy arkuszy stylów już przerywają build (zobacz missingAssets). linkCheck pokrywa drugą połowę: wewnętrzne odnośniki <a href> wskazujące na stronę, która nie istnieje.
export default {
linkCheck: true, // 'warn' (domyślnie), 'error' albo obiekt opcji
}Po sitelo build każdy wewnętrzny odnośnik w wyniku jest rozwiązywany, a wszystko, za czym nie stoi strona, zostaje zgłoszone i pogrupowane według strony, na której się pojawia:
[sitelo] 3 martwe odnośniki wewnętrzne
index.html
../escape -> wychodzi poza katalog wyjściowy
/abuot -> nie ma takiej strony
/blog/missing-post -> nie ma takiej stronyJak rozwiązywane są odnośniki
Sprawdzenie działa na wypuszczonej witrynie, a nie na tabeli tras — więc uwzględnia cleanUrls, grupy tras, mapOutputPath, pliki skopiowane z public/ i strony powstałe z tras dynamicznych. Działa też po optymalizacji obrazów i po Pagefind, więc widzi dokładnie to, co trafia do sieci. Odnośnik jest poprawny, gdy odpowiada mu prawdziwy plik, próbowany w kolejności, w jakiej zrobiłby to hosting statyczny:
/about→about, potemabout/index.html, potemabout.html/blog/→blog/index.html(końcowy ukośnik zawsze oznacza indeks katalogu)/→index.html
Odnośniki względne (../about) rozwiązują się względem strony, która je zawiera, a taki, który wychodzi poza katalog wyjściowy, zostaje zgłoszony. Query stringi są przy rozwiązywaniu ignorowane — /about?utm=x sprawdza /about.
Odnośniki zewnętrzne nigdy nie są pobierane. https://, względne wobec protokołu //cdn.example.com, mailto:, tel: i inne schematy są pomijane w całości.
Opcje
| Opcja | Domyślnie | Opis |
|---|---|---|
mode | 'warn' | 'warn' zapisuje i kontynuuje; 'error' przerywa build — przydatne w CI |
exclude | [] | Globy albo wyrażenia regularne adresów do pominięcia |
checkFragments | false | Sprawdzaj też, czy cele #fragmentów istnieją na podlinkowanej stronie |
export default {
linkCheck: {
mode: 'error', // przerwij build przy martwym odnośniku
checkFragments: true, // sprawdzaj też cele #fragmentów
exclude: ['/api/**', /^\/legacy\//],
},
}checkFragments jest domyślnie wyłączone, bo identyfikatory dodawane przez JavaScript po stronie klienta nie ma ich w zbudowanym HTML-u i zostałyby zgłoszone jako brakujące. Jako cele fragmentów liczą się zarówno atrybuty id, jak i dawne name kotwic.
Witryny serwowane spod bazy
Jeśli Twoja witryna jest wdrożona pod base (powiedzmy jako witryna projektu na GitHub Pages), odnośnik względem katalogu głównego bez tej bazy zostaje zgłoszony. /about na witrynie serwowanej spod /repo/ wysyła przeglądarkę do korzenia hosta, a nie w głąb Twojej witryny — rozwiązywanie go mimo to względem wyniku ukryłoby dokładnie ten błąd, który warto wyłapać. Gdy jest to zamierzone, użyj exclude.
Audyty Lighthouse
sitelo lighthouse audytuje gotowy build przez Lighthouse. To opcjonalna peer dependency:
npm install -D lighthousesitelo serwuje dist/ tak samo jak sitelo preview, kieruje bezgłowego Chrome’a na każdą stronę i wypisuje wyniki:
[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.4sKażda strona jest audytowana pod adresem, którym linkuje ją witryna — /docs, nigdy dist/docs.html — więc cleanUrls, grupy tras i base są uwzględnione. Dodaj progi, a raport stanie się sprawdzeniem: każdy wynik poniżej swojego progu przerywa polecenie.
export default {
lighthouse: {
exclude: ['404.html'], // strona 404 rzadko warta jest audytu
thresholds: {
performance: 90,
accessibility: 100,
'best-practices': 95,
seo: 100,
},
},
}Wyniki zapisuje się tak, jak pokazuje je Lighthouse (0–100); działają też jego własne ułamki 0–1. Użyj mode: 'warn', by tylko zapisywać zamiast przerywać.
include/exclude— które strony są audytowane (globy albo wyrażenia regularne)sample— audytuj tyle losowych stron na każdy wzorzecincludezamiast wszystkichcategories—performance,accessibility,best-practices,seothresholds— minimalny wynik na kategorięmode—'error'(domyślnie) albo'warn'formFactor—'mobile'(domyślnie),'desktop'albo obaruns— powtórz audyt i podaj wynik medianyoutput/formats— zapisz pełny raport Lighthouse dla każdej stronyflags/config— przekazywane wprost do Lighthouse, więc działa wszystko, co przyjmuje jego CLIonBuild— audytuj także na końcusitelo build
export default {
lighthouse: {
formFactor: 'desktop', // presetu desktopowego Lighthouse
runs: 3, // trzy przebiegi na stronę, wynik mediany
output: true, // pełne raporty w .sitelo/lighthouse/
onBuild: true, // audytuj też na końcu sitelo build
flags: { throttlingMethod: 'provided' },
},
}Lighthouse steruje prawdziwym Chrome’em: zainstaluj go tam, gdzie działa audyt, albo wskaż plik wykonywalny przez CHROME_PATH. Wyniki wydajności wahają się między uruchomieniami, więc zanim oprzesz na nich próg, użyj runs: 3.
Wyszukiwanie Pagefind
Opcjonalne wyszukiwanie statyczne napędzane przez Pagefind, opcjonalną peer dependency. Zainstaluj ją, gdy chcesz wyszukiwania, potem włącz indeksowanie, oznacz treść, zamontuj interfejs i uruchom sitelo build.
npm install -D pagefind1. Włącz indeksowanie
Ustaw pagefind: true. Po sitelo build dostaniesz dist/pagefind/, a domyślnie też kopię w public/pagefind/, żeby kolejne sitelo (dev) albo sitelo preview mogło serwować /pagefind/ bez przebudowywania.
export default {
pagefind: true,
}2. Oznacz treść i dodaj miejsce montowania
Umieść data-pagefind-body na treści głównej, żeby nawigacja i stopka nie były indeksowane. Zostaw pusty element na interfejs wyszukiwania:
export default () => `
<html lang="pl">
<head>
<title>Moja strona</title>
<link rel="stylesheet" href="/styles.css">
<script type="module" src="/main.js"></script>
</head>
<body>
<header>
<a href="/">Start</a>
<div id="search"></div>
</header>
<main data-pagefind-body>
<h1>Cześć</h1>
<p>Indeksowany jest tylko ten obszar.</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: 'pl' },
head(
title('Moja strona'),
link({ rel: 'stylesheet', href: '/styles.css' }),
script({ type: 'module', src: '/main.js' }),
),
body(
header(
a({ href: '/' }, 'Start'),
div({ id: 'search' }),
),
main({ 'data-pagefind-body': '' },
h1('Cześć'),
p('Indeksowany jest tylko ten obszar.'),
),
),
)export default function Home() {
return (
<html lang="pl">
<head>
<title>Moja strona</title>
<link rel="stylesheet" href="/styles.css" />
<script type="module" src="/main.js" />
</head>
<body>
<header>
<a href="/">Start</a>
<div id="search" />
</header>
<main data-pagefind-body="">
<h1>Cześć</h1>
<p>Indeksowany jest tylko ten obszar.</p>
</main>
</body>
</html>
)
}3. Zamontuj interfejs Pagefind
Załaduj /pagefind/pagefind-ui.js i pagefind-ui.css ze swojego skryptu klienckiego (dopiero po tym, jak build wytworzy indeks):
async function initSearch() {
const mount = document.querySelector('#search')
if (!mount) return
// Indeks powstaje dopiero po `sitelo build` (domyślnie kopiowany do 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. Zbuduj i zignoruj zsynchronizowaną paczkę
sitelo build
# potem: sitelo preview — albo sitelo (dev) korzystające z public/pagefindpublic/pagefind/Opcje zaawansowane (syncPublic, glob, język, selektory, …) trafiają do obiektu: pagefind: { syncPublic: false, glob: '**/*.html' }. Pełne opcje interfejsu: pagefind.app.
404
Utwórz src/404.ht.js, żeby powstał dist/404.html. W przeciwnym razie powstanie schludny domyślny.