Konfiguracja

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

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 strony

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

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

OpcjaDomyślnieOpis
mode'warn''warn' zapisuje i kontynuuje; 'error' przerywa build — przydatne w CI
exclude[]Globy albo wyrażenia regularne adresów do pominięcia
checkFragmentsfalseSprawdzaj 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 lighthouse

sitelo 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.4s

Każ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ć.

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 pagefind

1. 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:

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.'),
      ),
    ),
  )

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/pagefind
public/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.