Skip to content

Commit 68f7b94

Browse files
committed
Faster rendering by less split
1 parent 49ae957 commit 68f7b94

File tree

1 file changed

+30
-8
lines changed

1 file changed

+30
-8
lines changed

lib/hexo/post.js

Lines changed: 30 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -418,15 +418,37 @@ class Post {
418418
toString: true
419419
}, options);
420420
}).then(content => {
421+
// This function restores swig tags in `content` and render them.
422+
if (disableNunjucks) {
423+
// If rendering is disabled, do nothing.
424+
return cacheObj.restoreAllSwigTags(content);
425+
}
426+
// We'd like to render tags concurrently, so we split `content`
427+
// by top-level HTML nodes that have swig tags into `split_content` array
428+
// (nodes that don't have swig tags don't need to be split).
429+
// Then we render items in `split_content` asynchronously.
421430
const doc = parse5.parseFragment(content);
422-
// Indepedently render the tags in each top-level node
423-
// asynchronously. This can significantly speed up rendering of slow tags
424-
const results = doc.childNodes.map(async node => {
425-
// Replace cache data with real contents
426-
const content = cacheObj.restoreAllSwigTags(parse5.serializeOuter(node));
427-
// If disabled, return content after replacing the placeholders
428-
if (disableNunjucks) return content;
429-
// Render with Nunjucks
431+
const split_content = [];
432+
let current = []; // Current list of nodes to be added to split_content.
433+
doc.childNodes.forEach(node => {
434+
const html = parse5.serializeOuter(node);
435+
const restored = cacheObj.restoreAllSwigTags(html);
436+
current.push(restored);
437+
if (html !== restored) {
438+
// Once we encouner a node that has swig tags, merge
439+
// all content we've seen so far and add to `split_content`.
440+
// We don't simply add every node to `split_content`, because
441+
// most nodes don't have swig tags and calling `tag.render` for
442+
// all of them has significant overhead.
443+
split_content.push(current.join(''));
444+
current = [];
445+
}
446+
});
447+
if (current.length) {
448+
split_content.push(current.join(''));
449+
}
450+
// Render the tags in each top-level node asynchronously.
451+
const results = split_content.map(async content => {
430452
return await tag.render(content, data);
431453
});
432454
return Promise.all(results).then(x => x.join(''));

0 commit comments

Comments
 (0)