Skip to content

perf(search): load Pagefind lazily on first open; build the index in dev and build#3340

Open
Vidminas wants to merge 2 commits into
HugoBlox:mainfrom
Vidminas:perf/lazy-load-pagefind
Open

perf(search): load Pagefind lazily on first open; build the index in dev and build#3340
Vidminas wants to merge 2 commits into
HugoBlox:mainfrom
Vidminas:perf/lazy-load-pagefind

Conversation

@Vidminas

Copy link
Copy Markdown

πŸš€ What type of change is this?

  • πŸ› Bug fix (A non-breaking change that fixes an issue)
  • ✨ New feature (A non-breaking change that adds functionality)
  • πŸ’… Style change (A change that only affects formatting, visuals, or styling)
  • πŸ“š Documentation update (Changes to documentation only)
  • 🧹 Refactor or chore (A code change that neither fixes a bug nor adds a feature)
  • πŸ’₯ Breaking change (A fix or feature that would cause existing functionality to not work as expected)

🎯 What is the purpose of this change?

The search modal imported Pagefind eagerly in init(), so pagefind.js and the index were
fetched on every page view, even for visitors who never open search. (The current try/catch +
assetPaths already make a missing index degrade gracefully β€” this is the remaining perf/ergonomics
refinement.)

Changes:

  1. Lazy load (engine). Move the import into an idempotent ensurePagefind() that runs the first
    time the search modal opens (via the existing $store.search.open watcher), and is awaited by
    search() so typing before the load finishes still works. Net: the index is fetched on first
    search-open, not on page load.

  2. Build the index in dev and build (all starters). Inline the Pagefind call in every
    starter's dev and build scripts, replacing the pnpm run pagefind indirection so each script
    is explicit and self-contained:

    • dev: hugo && pagefind --site public --output-subdir ../static/pagefind && hugo server …
      β€” builds the index into the already-gitignored static/pagefind/ so hugo server serves it,
      making search work under pnpm dev (mirrors the monorepo dev harness in view-starter-dev.sh).
    • build: hugo --minify && pagefind --site public β€” writes the index straight into the
      deployed public/pagefind (the standard location; unchanged behaviour, just inlined).

    The standalone pagefind script is kept because each starter's netlify.toml still calls
    pnpm run pagefind. The starter base template wraps its 2>/dev/null || true fault-guard in a subshell β€”
    hugo && (pagefind … || true) && hugo server β€” so it tolerates only a Pagefind failure. Inlined
    bare, sh's equal &&/|| precedence would let || true also swallow a failed Hugo build and
    start the server on broken output.

Verified: the built search script has exactly one await import(...) (inside ensurePagefind),
init() no longer imports eagerly, the open-watcher calls ensurePagefind(), and the emitted JS
passes node --check. All nine starters' package.json remain valid JSON, and Pagefind's output
locations are confirmed empirically β€” --output-subdir ../static/pagefind writes to
static/pagefind/ (dev, served by hugo server) and the default --site public writes to
public/pagefind/ (build, the deployed output).


πŸ“Έ Screenshots or Screencast (if applicable)

n/a


ℹ️ Documentation Check

  • No, this change does not require a documentation update.
  • Yes, I have updated the documentation accordingly (or will in a follow-up PR).

πŸ“œ Contributor Agreement

Thank you for your contribution!

Vidminas and others added 2 commits July 9, 2026 22:46
Pagefind was imported eagerly in the search modal's init(), so its index loaded
on every page view even when search was never opened. Move the import into an
idempotent ensurePagefind() that runs when the modal first opens (and is awaited
by search() to cover a user typing before that load finishes).

Also build the Pagefind index in the academic-cv starter's `dev` script so
search works under `pnpm dev` (mirrors the monorepo dev harness; output goes to
the already-gitignored static/pagefind).

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Extend the dev-time index build (previously only academic-cv) to every starter,
and inline the Pagefind call in both `dev` and `build` instead of the
`pnpm run pagefind` indirection:

  dev:   hugo && pagefind --site public --output-subdir ../static/pagefind && hugo server ...
  build: hugo --minify && pagefind --site public

`dev` writes the index into static/ so `hugo server` serves it; `build` writes it
straight into the deployed public/pagefind. The `pagefind` script is kept because
each starter's netlify.toml still calls `pnpm run pagefind`. The `starter` base
template keeps its `|| true` fault-guard, scoped in a subshell so it can't mask a
Hugo failure.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Vidminas
Vidminas requested a review from gcushen as a code owner July 12, 2026 09:27
@netlify

netlify Bot commented Jul 12, 2026

Copy link
Copy Markdown

❌ Deploy Preview for academic-demo failed. Why did it fail? β†’

Name Link
πŸ”¨ Latest commit d04d53a
πŸ” Latest deploy log https://app.netlify.com/projects/academic-demo/deploys/6a535e1744e8130008fa89d0

@Vidminas

Copy link
Copy Markdown
Author

Builds fail due to Hugo 0.162.0 incompatibility, which is addressed in #3329

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant