jekyll / jekyll

:globe_with_meridians: Jekyll is a blog-aware static site generator in Ruby

Home Page:https://jekyllrb.com

Geek Repo:Geek Repo

Github PK Tool:Github PK Tool

Jekyll creates two instances just to boot, build and watch.

envygeeks opened this issue · comments

While debugging Jekyll Assets on Jekyll 3.1+ to figure out why our Jekyll::Assets::Env#used was constantly reset even though we cache the instance, check for the instance and only reinit on a new Jekyll, I noticed that Jekyll start's itself twice

jordon ~/development/envygeeks/envygeeks.io (master #) → rm -rf .asset-cache
jordon ~/development/envygeeks/envygeeks.io (master #) → rm -rf _site
jordon ~/development/envygeeks/envygeeks.io (master #) →bundle exec jekyll s -w --trace --verbose
  Logging at level: debug
Configuration file: /home/jordon/development/envygeeks/envygeeks.io/_config.yml
The total number of Jekyll instances:  1
Creating a new instance of:  Jekyll::Assets::Env
The old value of Sprockets:  
         Requiring: /home/jordon/development/envygeeks/envygeeks.io/_plugins/filters.rb
         Requiring: kramdown
            Source: /home/jordon/development/envygeeks/envygeeks.io
       Destination: /home/jordon/development/envygeeks/envygeeks.io/_site
 Incremental build: disabled. Enable with --incremental
      Generating... 
The total number of Jekyll instances:  1
       EntryFilter: excluded /vendor/cache
       EntryFilter: excluded /vendor/bundle
         Rendering: index.md
  Pre-Render Hooks: index.md
  Rendering Liquid: index.md
  Rendering Markup: index.md
         Requiring: kramdown
  Rendering Layout: index.md
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/font-awesome/fontawesome-webfont.eot
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/font-awesome/fontawesome-webfont.woff2
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/font-awesome/fontawesome-webfont.woff
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/font-awesome/fontawesome-webfont.ttf
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/font-awesome/fontawesome-webfont.svg
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/roboto-slab.woff2
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/bundle.css
                    done in 3.581 seconds.
         Requiring: jekyll-watch
The total number of Jekyll instances:  2
Creating a new instance of:  Jekyll::Assets::Env
The old value of Sprockets:  
         Requiring: /home/jordon/development/envygeeks/envygeeks.io/_plugins/filters.rb
         Requiring: kramdown
           Watcher: Ignoring (?-mix:_config\.yml)
           Watcher: Ignoring (?-mix:_site)
           Watcher: Ignoring (?-mix:vendor)
           Watcher: Ignoring (?-mix:\.bundle)
           Watcher: Ignoring (?-mix:\.asset\-cache)
 Auto-regeneration: enabled for '/home/jordon/development/envygeeks/envygeeks.io'
  Logging at level: debug
Configuration file: /home/jordon/development/envygeeks/envygeeks.io/_config.yml
[2016-04-29 21:29:14] INFO  WEBrick 1.3.1
[2016-04-29 21:29:14] INFO  ruby 2.3.0 (2015-12-25) [x86_64-linux-gnu]
[2016-04-29 21:29:14] DEBUG WEBrick::HTTPServlet::FileHandler is mounted on /.
[2016-04-29 21:29:14] DEBUG unmount .
[2016-04-29 21:29:14] DEBUG Jekyll::Commands::Serve::Servlet is mounted on .
    Server address: http://127.0.0.1:4000/
[2016-04-29 21:29:14] INFO  WEBrick::HTTPServer#start: pid=25326 port=4000
  Server running... press ctrl-c to stop.
      Regenerating: 1 file(s) changed at 2016-04-29 21:30:51 The total number of Jekyll instances:  2
       EntryFilter: excluded /vendor/cache
       EntryFilter: excluded /vendor/bundle
         Rendering: index.md
  Pre-Render Hooks: index.md
  Rendering Liquid: index.md
  Rendering Markup: index.md
         Requiring: kramdown
  Rendering Layout: index.md
     Jekyll Assets: Writing /home/jordon/development/envygeeks/envygeeks.io/_site/assets/bundle.css
...done in 0.076060421 seconds.

Jekyll Watch should take the current instance of Jekyll, not create it's own instance, this way there is an efficiency in how people can program and cache stuff on Jekyll. Ultimately this doesn't matter to us as we worked around it easily, Jekyll has two instances in memory just to watch and build from the same command.

Why run this before initializing Jekyll?

jordon ~/development/envygeeks/envygeeks.io (master #) → rm -rf .asset-cache
jordon ~/development/envygeeks/envygeeks.io (master #) → rm -rf _site

@jajajames To force a complete site rebuild, ensuring all parts of the Jekyll pipeline activate during the next site build... important for debugging. See jekyll clean for a built-in command.

The problem is that the site instance is not passed to the Jekyll::Watch.watch method. As a result, the Jekyll watch plugin must instantiate a new site.

The silly part is that site instance is in scope at the time Jekyll::Watch.watch is invoked. The instance just isn't passed on. I don't see any reason why the watch plugin should create a new site instance.

The fix involves a change to both Jekyll core and the Jekyll watch plugin. There's a way to do it so that old versions of either simply fallback to the current behavior.

In Jekyll core, lib/jekyll/commands/build.rb:

change:

Jekyll::Watcher.watch(options)

to:

watch = Jekyll::Watcher.method(:watch)
watch.arity == 1 ? watch.call(options) : watch.call(options, _site)

In Jekyll watch, lib/jekyll/watcher.rb:

change:

def watch(options)
  ...
  site = Jekyll::Site.new(options)

to:

def watch(options, site = nil)
  ...
  site ||= Jekyll::Site.new(options)

Once this change is made to both components, the same site instance gets reused.

If you agree, I'd be happy to submit pull requests for these two changes.

@mojavelinux Your help would be greatly appreciated. Part of the motivation for passing the options hash instead of the built site was so that we could reload the configuration file if it were changed during regeneration and instantiate a new Site if it were. This never came to fruition. In the latest version of Jekyll, we have added a method on Site which allows one to pass in new options and to have those new options propagate through the site instance. Perhaps this new method could be used to have the best of both worlds here.

I would gratefully accept PR's which pass the Site object to the Watcher. 😄

PRs sent!