Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
galaxyproject
GitHub Repository: galaxyproject/training-material
Path: blob/main/_plugins/jekyll-bundler.rb
1677 views
1
require 'digest'
2
3
# While reading in all of the files for the site
4
# load the bundles and find out their last modified time
5
# so we can use that as a cache buster
6
Jekyll::Hooks.register :site, :post_read do |site|
7
site.config['javascript_bundles'].each do |name, resources|
8
if Jekyll.env == 'production'
9
# Get the maximum last file modified time to use as the bundle timestamp
10
bundle_timestamp = resources['resources'].map { |f| File.mtime(f).to_i }.max
11
site.config['javascript_bundles'][name]['timestamp'] = bundle_timestamp
12
13
# This is inefficient since we read twice but it's also not that expensive.
14
bundle = resources['resources'].map { |f| File.read(f) }.join("\n")
15
hash = Digest::MD5.hexdigest(bundle)[0..7]
16
site.config['javascript_bundles'][name]['hash'] = hash
17
site.config['javascript_bundles'][name]['path'] = "/assets/js/bundle.#{name}.#{hash}.js"
18
19
Jekyll.logger.info "[GTN/Bundler] Analysing JS Bundle #{name} => #{bundle_timestamp} / #{hash}"
20
else
21
Jekyll.logger.info '[GTN/Bundler] Serving plain JS'
22
end
23
end
24
end
25
26
# When writing the site, build the bundles
27
# It's basically "cat *.js > bundle.js"
28
# We don't need no fancy JS minification
29
# gzip probably does enough, everything else is pre-minified.
30
Jekyll::Hooks.register :site, :post_write do |site|
31
site.config['javascript_bundles'].each do |name, resources|
32
if Jekyll.env == 'production'
33
bundle_path = "#{site.dest}#{resources['path']}"
34
Jekyll.logger.info "[GTN/Bundler] Building JS bundle #{name} => #{bundle_path}"
35
36
# Just concatenate them all together
37
bundle = resources['resources'].map { |f| File.read(f) }.join("\n")
38
39
# Write the bundle to the output directory
40
File.write(bundle_path, bundle)
41
end
42
end
43
end
44
45
module Jekyll
46
module Filters
47
48
# Our (very simple) JS Bundler
49
module JsBundle
50
##
51
# Setup the local cache via +Jekyll::Cache+
52
def cache
53
@@cache ||= Jekyll::Cache.new('GtnJsBundle')
54
end
55
56
# Return the preloads for the bundles, when in production
57
# +test+:: ignore this
58
# Returns the HTML to load the bundle
59
#
60
# Example:
61
# {{ 'load' | bundle_preloads }}
62
def bundle_preloads(_test)
63
if Jekyll.env == 'production'
64
bundle_preloads_prod
65
else
66
''
67
end
68
end
69
70
# (Internal) Return the production preloads for the bundles
71
def bundle_preloads_prod
72
bundles = @context.registers[:site].config['javascript_bundles']
73
baseurl = @context.registers[:site].config['baseurl']
74
75
# Select the ones wishing to be preloaded
76
bundles = bundles.select do |_name, bundle|
77
bundle['preload'] == true
78
end
79
80
bundles.map do |_name, bundle|
81
bundle_path = "#{baseurl}#{bundle['path']}"
82
"<link rel='preload' href='#{bundle_path}' as='script'>"
83
end.join("\n")
84
end
85
86
# Load a specific bundle, in liquid
87
# +name+:: the name of the bundle to load
88
# Returns the HTML to load the bundle
89
#
90
# Example:
91
# {{ 'main' | load_bundle }}
92
def load_bundle(name)
93
cache.getset("#{Jekyll.env}-#{name}") do
94
if Jekyll.env == 'production'
95
load_bundle_production(name)
96
else
97
load_bundle_dev(name)
98
end
99
end
100
end
101
102
##
103
# Dev version of the bundle loader, just direct script links
104
def load_bundle_dev(name)
105
bundle = @context.registers[:site].config['javascript_bundles'][name]
106
raise "Bundle #{name} not found in site config" if bundle.nil?
107
108
Jekyll.logger.debug "[GTN/Bundler] Bundle #{bundle}"
109
110
baseurl = @context.registers[:site].config['baseurl']
111
112
bundle['resources'].map do |f|
113
"<script src='#{baseurl}/#{f}'></script>"
114
end.join("\n")
115
end
116
117
##
118
# Production version of the bundle loader, with cache busting
119
def load_bundle_production(name)
120
bundle = @context.registers[:site].config['javascript_bundles'][name]
121
raise "Bundle #{name} not found in site config" if bundle.nil?
122
123
baseurl = @context.registers[:site].config['baseurl']
124
attrs = ''
125
attrs += ' async' if bundle['async']
126
attrs += ' defer' if bundle['defer']
127
bundle_path = "#{baseurl}#{bundle['path']}"
128
"<script #{attrs} src='#{bundle_path}'></script>"
129
end
130
end
131
end
132
end
133
134
Liquid::Template.register_filter(Jekyll::Filters::JsBundle)
135
136