Skip to main content
Settings
Search
Appearance
Theme Mode
About
Jekyll v3.10.0
Environment Production
Last Build
2026-05-19 04:06 UTC
Current Environment Production
Build Time May 19, 04:06
Jekyll v3.10.0
Build env (JEKYLL_ENV) production
Page Location
Page Info
Layout default
Collection docs
Path _docs/obsidian/performance.md
URL /docs/obsidian/performance/
Date 2026-05-19
Theme Skin
SVG Backgrounds
Layer Opacity
0.6
0.04
0.08

Obsidian Resolver — Performance & Caching

The zer0-mistakes Obsidian integration resolves [[Wiki-links]] on every page at build time (Ruby plugin path) or at page-load time (JavaScript path). Both paths include caching to keep build and load times fast even on large vaults with hundreds of cross-links.

Two Resolution Paths

graph LR
    A[Markdown source] --> B{Deployment type}
    B -- "Self-build (vanilla Jekyll)" --> C["Ruby plugin<br/>_plugins/obsidian_links.rb"]
    B -- "GitHub Pages (remote_theme)" --> D["JS resolver<br/>obsidian-wiki-links.js"]
    C --> E[Server-side HTML]
    D --> F[Client-side rewrite on load]

Ruby Plugin Path (Self-Build)

_plugins/obsidian_links.rb runs as a Jekyll :pre_render hook and transforms [[Wiki-links]] before kramdown processes the Markdown.

Page-URL Index

The plugin builds a title → permalink index (site.obsidian.index) once per build and reuses it for every page. The index is also written to:

assets/data/wiki-index.json

This JSON file is consumed by the JavaScript client-side resolver (see below).

Avoiding Redundant Work

The :pre_render hook skips pages that contain no Obsidian syntax (no [[, ![[, > [!, or #tag patterns). This short-circuit check avoids string-scanning files that don’t need transformation.

JavaScript Path (GitHub Pages)

assets/js/obsidian-wiki-links.js fetches wiki-index.json and rewrites [[Wiki-links]] that were left as-is in the HTML (because the Ruby plugin did not run on GitHub Pages).

Fetch Cache

The fetch uses cache: 'force-cache' so the browser reuses a cached copy of wiki-index.json on subsequent page loads:

fetch(CONFIG.indexUrl, { credentials: 'same-origin', cache: 'force-cache' })

This means the index is only downloaded once per browser session for most users.

In-Memory Resolution Cache

After the index is loaded, the resolver caches resolved URLs in a Map for the duration of the page session. Repeated lookups for the same target (common in docs with many cross-references) hit the in-memory map rather than re-scanning the index array.

Build-Time Impact

On a vault with ~200 pages and ~500 cross-links:

Before caching After caching
Index rebuilt per page Index built once
Every page scanned unconditionally Pages without Obsidian syntax skipped
~15 % longer build Baseline build time

Actual numbers vary by content; run bundle exec jekyll build --profile to measure your site.

Configuration

# _config.yml
obsidian:
  enabled: true              # set false to disable the plugin entirely
  attachments_path: /assets/images/notes
  tag_base_url: /tags/

Setting enabled: false disables both the Ruby plugin and the JS resolver initialization.

Monitoring Build Performance

Use Jekyll’s built-in profiler:

bundle exec jekyll build --profile

Look for the obsidian_links.rb hook in the :pre_render section of the output. If it accounts for a large share of build time, consider reducing the number of cross-links or splitting large pages into smaller ones.

See also

  • [[Obsidian]]
  • [[Performance]]
  • [[Development]]