Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Jekyll: Generate an include once and include it to all pages

TL;DR: Can I say somehow to generate the content for a {% include %} once and just stamp it out in multiple places without having to regenerate it in every location?

I'm building a fairly big documentation site with Jekyll which has right now a bit over 50 articles on it. It has a sidebar where all articles are listed. the sidebar is built in a separate sidebar.html and then it is included into every page on the site with {% include sidebar.html %} in default.html.

The problem I have is that every single article runs the generation of sidebar.html separately, so I have over 50 generation passes on that piece of code. Every article I add adds another pass to this and make all the passes a bit slower, as generating the sidebar has to parse every single article in the project.

Build time has gone up from basically zero to over 100 seconds already, and if I remove the {% include sidebar.html %} then it drops down to 5 seconds. When I get all the articles in I'd estimate to have around 100-200 of them. Then I should have versioning in the future for all articles which means that there can easily be 1000+ articles in the long run. At that point I wouldn't be suprised if changing one letter in one file would take something like an hour to regenerate files in jekyll serveand jekyll build.

What I would like to do is to build sidebar.html once in the beginning of the build process and just stamp it out to every page when i generate said pages. Is this possible?

like image 937
Jens Jansson Avatar asked May 29 '15 07:05

Jens Jansson


2 Answers

Fastest way to do this.

Move _includes/sidebar.html to sidebar-template.html

Add this front matter :

---
layout: null
permalink: sidebar-template.html
---

Create a Rakefile

TPL = "_site/sidebar-template.html"
TST = "_includes/sidebar.html"

task :default => :nav

desc "Generates sidebar then copy it to be used as an include"
task :nav do

  if !File.exist?(TST)
    puts "Creating dummy #{TST} file"
    open(TST, 'w') do |f|
      f.puts warning
    end
  end

  puts "Building Jekyll 1st run"
  system "jekyll build --trace"

  # delete target file (TST) if exist
  if File.exist?(TST)
      puts "#{TST} exists deleting it"
      rm TST
  end

  # copy generated file as an include
  cp(TPL, TST)

  puts "Building Jekyll AGAIN"
  system "jekyll build --trace"

  puts "task END"
end

Just run rake and you have your sidebar include generated.

like image 80
David Jacquel Avatar answered Oct 23 '22 23:10

David Jacquel


There is now a better way to do this, thanks to Ben Balter.

instead of: {% include yourtemplate.html %} use: {% include_cached yourtemplate.html %}

When used on larger items that need to be built once, such as a site hierarchy, the item will be cached. For other items that vary across pages, you'll still want to use the include as you always have done.

It is explained well here: https://github.com/benbalter/jekyll-include-cache

Definitely cuts down on site startup time!

like image 39
Jim Kohl Avatar answered Oct 23 '22 22:10

Jim Kohl