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!