Optimize rendering Liquid templates (#7136)

Merge pull request 7136
This commit is contained in:
Ashwin Maroli 2018-10-03 20:59:45 +05:30 committed by jekyllbot
parent 440374aa4d
commit a2d61f976f
5 changed files with 40 additions and 14 deletions

View File

@ -19,9 +19,32 @@ If you're using Ruby >= 2.3.0, go ahead and fetch the latest version of Jekyll:
gem update jekyll gem update jekyll
``` ```
---
*Insert sections here* ### Template rendering
We've slightly altered the way Jekyll parses and renders your various templates to improve
the overall build times. Jekyll now parses a template once, caches it internally and then
renders the parsed template multiple times as required by your pages and documents.
The downside to this is that some of the community-authored plugins may not work as they
previously used to.
#### For Plugin-authors
* If your plugin depends on the following code: `site.liquid_renderer.file(path).parse(content)`,
note that the return value (`template`, an instance of *`Liquid::Template`*), from that line will
always be the **same object** for a given `path`. <br/>
The *`template`* instance is then rendered as previously, with respect to the `payload` passed to it.
You'll therefore have to ensure that *`payload`* is not memoized or cached in your plugin instance.
* If its a requirement that `template` you get from the above step *be different* at all times,
you can invoke *`Liquid::Template`* directly:
```diff
- template = site.liquid_renderer.file(path).parse(content)
+ template = Liquid::Template.parse(content)
```
--- ---

View File

@ -18,6 +18,7 @@ module Jekyll
def reset def reset
@stats = {} @stats = {}
@cache = {}
end end
def file(filename) def file(filename)
@ -50,10 +51,18 @@ module Jekyll
"#{error.message} in #{path}" "#{error.message} in #{path}"
end end
# A persistent cache to store and retrieve parsed templates based on the filename
# via `LiquidRenderer::File#parse`
#
# It is emptied when `self.reset` is called.
def cache
@cache ||= {}
end
private private
def filename_regex def filename_regex
@filename_regex ||= %r!\A(#{source_dir}/|#{theme_dir}/|\W*)(.*)!i @filename_regex ||= %r!\A(#{source_dir}/|#{theme_dir}/|/*)(.*)!i
end end
def new_profile_hash def new_profile_hash

View File

@ -10,8 +10,9 @@ module Jekyll
def parse(content) def parse(content)
measure_time do measure_time do
@template = Liquid::Template.parse(content, :line_numbers => true) @renderer.cache[@filename] ||= Liquid::Template.parse(content, :line_numbers => true)
end end
@template = @renderer.cache[@filename]
self self
end end
@ -24,6 +25,7 @@ module Jekyll
end end
end end
# This method simply 'rethrows any error' before attempting to render the template.
def render!(*args) def render!(*args)
measure_time do measure_time do
measure_bytes do measure_bytes do

View File

@ -90,13 +90,7 @@ module Jekyll
# Render the variable if required # Render the variable if required
def render_variable(context) def render_variable(context)
if @file =~ VARIABLE_SYNTAX Liquid::Template.parse(@file).render(context) if @file =~ VARIABLE_SYNTAX
partial = context.registers[:site]
.liquid_renderer
.file("(variable)")
.parse(@file)
partial.render!(context)
end
end end
def tag_includes_dirs(context) def tag_includes_dirs(context)

View File

@ -17,9 +17,7 @@ module Jekyll
def render(context) def render(context)
site = context.registers[:site] site = context.registers[:site]
relative_path = Liquid::Template.parse(@relative_path).render(context)
liquid = site.liquid_renderer.file("(jekyll:link)")
relative_path = liquid.parse(@relative_path).render(context)
site.each_site_file do |item| site.each_site_file do |item|
return item.url if item.relative_path == relative_path return item.url if item.relative_path == relative_path