Skip to content

Commit

Permalink
Faster rendering by less split
Browse files Browse the repository at this point in the history
  • Loading branch information
ppwwyyxx committed Sep 18, 2022
1 parent 49ae957 commit 68f7b94
Showing 1 changed file with 30 additions and 8 deletions.
38 changes: 30 additions & 8 deletions lib/hexo/post.js
Original file line number Diff line number Diff line change
Expand Up @@ -418,15 +418,37 @@ class Post {
toString: true
}, options);
}).then(content => {
// This function restores swig tags in `content` and render them.
if (disableNunjucks) {
// If rendering is disabled, do nothing.
return cacheObj.restoreAllSwigTags(content);
}
// We'd like to render tags concurrently, so we split `content`
// by top-level HTML nodes that have swig tags into `split_content` array
// (nodes that don't have swig tags don't need to be split).
// Then we render items in `split_content` asynchronously.
const doc = parse5.parseFragment(content);
// Indepedently render the tags in each top-level node
// asynchronously. This can significantly speed up rendering of slow tags
const results = doc.childNodes.map(async node => {
// Replace cache data with real contents
const content = cacheObj.restoreAllSwigTags(parse5.serializeOuter(node));
// If disabled, return content after replacing the placeholders
if (disableNunjucks) return content;
// Render with Nunjucks
const split_content = [];
let current = []; // Current list of nodes to be added to split_content.
doc.childNodes.forEach(node => {
const html = parse5.serializeOuter(node);
const restored = cacheObj.restoreAllSwigTags(html);
current.push(restored);
if (html !== restored) {
// Once we encouner a node that has swig tags, merge
// all content we've seen so far and add to `split_content`.
// We don't simply add every node to `split_content`, because
// most nodes don't have swig tags and calling `tag.render` for
// all of them has significant overhead.
split_content.push(current.join(''));
current = [];
}
});
if (current.length) {
split_content.push(current.join(''));
}
// Render the tags in each top-level node asynchronously.
const results = split_content.map(async content => {
return await tag.render(content, data);
});
return Promise.all(results).then(x => x.join(''));
Expand Down

0 comments on commit 68f7b94

Please sign in to comment.