Skip to content

perf(nunjucks): reuse compiled view templates - #5810

Merged
stevenjoezhang merged 2 commits into
masterfrom
fix/nunjucks-compile-cache
Aug 9, 2026
Merged

perf(nunjucks): reuse compiled view templates#5810
stevenjoezhang merged 2 commits into
masterfrom
fix/nunjucks-compile-cache

Conversation

@stevenjoezhang

Copy link
Copy Markdown
Member

What does it do?

Reuses the compiled top-level Nunjucks template for each Hexo View instead of creating a new Nunjucks environment and recompiling the same source on every render.

Background

The current behavior dates back to #4356, which introduced the dedicated Nunjucks renderer in 2020.

Although the compile() hook returns a closure with a comment saying that the closure keeps the compiled template, njkCompile(data) is invoked inside that closure. Consequently, every render creates another Nunjucks environment and recompiles the current View.

Simply moving the compilation outside the closure would make {% extends %}, {% include %}, and {% import %} dependencies stale during hexo server, because Nunjucks caches loader-resolved templates.

This PR therefore:

  • Compiles and retains the current View once.
  • Calls Environment#invalidateCache() before every render.
  • Reloads templates referenced through extends, include, and import.
  • Keeps the top-level compiled View because it is not stored in the loader cache.
  • Preserves hexo server hot-reload behavior.

This optimization was identified while profiling #5705. It does not remove the Buffer.from() encoding cost reported by that issue; it addresses a larger Nunjucks rendering hot path found during the same profiling work.

Performance

Measured with an isolated snapshot of a real-world Hexo blog. Baseline and patched runs used the same site state and were executed in alternating order.

Metric Before After Change
Warm hexo generate median 4.84 s 3.60 s -25.6%
First generation 7.16 s 6.21 s -13.2%
Top-level compile calls 2,873 79 -97.3%
Nunjucks environments created 2,875 81 -97.2%
Total template compilations 5,763 2,918 -49.4%
Template compilation time 1,517 ms 647 ms -57.3%
Loader dependency reads 2,890 2,890 unchanged

The unchanged dependency-read count is intentional: loader-resolved dependencies are still reloaded on each render to preserve server-side hot updates.

Tests

Added coverage to verify that:

  • The current View is compiled only once.
  • Updated include templates are reloaded.
  • Updated extends templates are reloaded.
  • Updated import templates are reloaded.

A real hexo server integration check was also performed by changing an included theme partial and confirming that the updated content appeared in the next HTTP response.

Validation completed:

  • Nunjucks renderer tests: 23 passing
  • TypeScript build: passed
  • ESLint: passed

Related to #5705.

Screenshots

N/A

Pull request tasks

  • Add test cases for the changes.
  • Passed the CI test.

@github-actions

github-actions Bot commented Aug 8, 2026

Copy link
Copy Markdown

How to test

git clone -b fix/nunjucks-compile-cache https://github.com/hexojs/hexo.git
cd hexo
npm install
npm test

@SukkaW
SukkaW requested a review from a team August 8, 2026 17:24
@stevenjoezhang
stevenjoezhang force-pushed the fix/nunjucks-compile-cache branch from e7d7f76 to 0548582 Compare August 9, 2026 11:53
@stevenjoezhang
stevenjoezhang merged commit 059cb17 into master Aug 9, 2026
25 checks passed
@stevenjoezhang
stevenjoezhang deleted the fix/nunjucks-compile-cache branch August 9, 2026 11:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants