hexo
hexo copied to clipboard
Concurrent rendering of nunjucks tags within a post
Check List
Please check followings before submitting a new feature request.
- [x] I have already read Docs page
- [x] I have already searched existing issues
Feature Request
Currently, if we use async rendering in custom tag plugins, rendering of tags can run concurrently between posts. However, tags within the same post are still rendered sequentially.
This is because when rendering a post, hexo makes a single render
call to nunjucks to render the entire post. Inside nunjucks, it renders all the tags sequentially.
I have a custom tag plugin that needs to make expensive async calls, so it could benefit a lot from within-post async rendering of tags.
Others
I have made a draft implementation of this feature at https://github.com/ppwwyyxx/hexo/commit/17565f7b1af33a8b71faab5ccb5b185125b4df32 . Instead of making one render
call per-post, it finds each nunjucks tag in the post and call render
on each of them.
This diff has improved my whole-site generation speed by 10x.
I would like to hear:
- Whether the feature makes sense to add
- If the above is yes, whether my implementation is in the right direction. If so I could start a PR.
The feature sounds awesome! You can draft a PR first as a PoC. And we will see if any changes/adoptions are required.
UPDATE: I managed to fix the issue.
I ran into a test failure that I'm not sure how to address. The problem is that for an input like this:
<p><code>{{ 1 + 1 }}</code> {{ 1 + 1 }}</p>
When the entire input is given, nunjucks is smart enough to know that the first {{ 1+1 }}
should not be rendered.
However, if we (i) find all tags and then (ii) render each tag independently using nunjucks, nunjucks lost the context and will therefore render both tags in the input.
- It seems difficult to implement this correctly without touching nunjucks. One potential approach:
-
When registering tags to nunjucks, register a cheap function that replaces tag content with some placeholder such as
<hexoTag>a unique id string<hexoTag>
. Save the mapping from "a unique id string" to the actual(fn, args)
that should be called to render the tag. -
Still use nunjucks to render the entire post in one
render()
call. The cheap function that we register will be called here. -
After rendering with nunjucks, find all
<hexoTag>
and asynchronously call the corresponding(fn, args)
to render the real content in the custom tag.This seems too complicated that I probably won't be able to work on it any time soon.
Please comment if you have other ideas.
- Alternatively, would it make sense to add the new feature (independent & async rendering of tags) as a per-post option? This way users can enable it for posts that don't have the abovementioned problem.