const minutes = (markdown) => Math.max(1, Math.round(markdown.split(/\s+/).length / 220));
export default defineConfig({
hooks: {
// Every page it touches rebuilds, every time
beforeRender({ page }) {
page.frontMatter.readingTime = minutes(page.content);
},
},
});
export default defineConfig({
hooks: {
// Runs before the cache check: unchanged pages stay cached
beforeAll({ pages }) {
for (const page of pages) {
page.frontMatter.readingTime = minutes(page.content);
}
},
},
});
Either way the template reads stati.page.readingTime.
Stati decides whether a page is up to date by hashing its content and front matter. beforeAll runs before that check, so what it adds is part of the hash, and the same on every build. beforeRender runs after the check, only for pages that are being rendered, and the cache entry then stores the hash with your additions in it. The next build hashes the page as it reads it from disk, without them, finds a mismatch and renders it again. And again on the next one.
The order has two more consequences. Pages served from the cache skip beforeRender and afterRender entirely, so neither is the place for work every page needs. And only stati build --force runs them for every page.
In the Stati docs: beforeRender, beforeAll and Hook lifecycle.