A straightforward asset bundling plugin for Jekyll, utilizing externalminification tool of your choice. It provides asset concatenation forbundling and asset fingerprinting with MD5 digest for cache busting.
There are no runtime dependencies, except for the minification tool usedfor bundling (fingerprinting has no dependencies).
The plugin requires Jekyll version 3 or 4. It is tested with Ruby MRI2.5 and later.
The plugin works with Jekyll's watch mode (auto-regeneration, Jekylloption --watch
), but not with incremental feature enabled (Jekylloption --incremental
).
There are two features: fingerprinting with MD5 digest over thecontents of the asset file (any type of file will do), and assetbundling combined with the first feature.
Asset bundling consists of concatenation and minification. The pluginimplements concatenation and leaves choosing the minification tool up toyou. UglifyJS is a good and fast minifier, for example. Theplugin connects to the minifier with standard unix pipe, feeding assetfile contents to it in desired order via standard input, and reads theresult from standard output.
Why is this good? A fingerprint in asset's path is the recommendedway to handle caching of static resources,because you can allow browsers and intermediate proxies to cache theasset for a very long time. Calculating MD5 digest over the contents ofthe file is fast and the resulting digest is reasonably unique to begenerated automatically.
Asset bundling is good for reducing the number of requests to thebackend upon page load. The minification of stylesheets and JavaScriptsources makes asset sizes smaller and thus faster to load over network.
The plugin ships as a RubyGem. To install:
Add the following line to the Gemfile of your site:
gem 'jekyll-minibundle'
Run bundle install
.
Instruct Jekyll to load the gem by adding this line to theconfiguration file of your site (_config.yml
):
plugins:
- jekyll/minibundle
(Use the gems
key instead of plugins
for Jekyll older than v3.5.0.)
An alternative to using the plugins
configuration option is to add the_plugins/minibundle.rb
file to your site project with this line:
require 'jekyll/minibundle'
You must allow Jekyll to use custom plugins. That is, do not enableJekyll's safe
configuration option.
If you just want to have an MD5 fingerprint in your asset's path, usethe ministamp
Liquid tag in a Liquid template file. For example,fingerprinting CSS styles:
<link rel="stylesheet" href="{{ site.baseurl }}/{% ministamp _assets/site.css assets/site.css %}" media="screen, projection">
When it's time to render the ministamp
tag, the plugin copies thesource file (_assets/site.css
, the first tag argument) to thespecified destination path (assets/site.css
, the second tag argument)in Jekyll's site destination directory. The filename will contain afingerprint.
The tag outputs the asset destination path, encoded for HTML, intoLiquid's template rendering outcome. For example, when site.baseurl
isempty:
<link rel="stylesheet" href="/assets/site-390be921ee0eff063817bb5ef2954300.css" media="screen, projection">
Another example, this time fingerprinting an image and using theabsolute_url Liquid filter of Jekyll to renderthe absolute URL of the image in the src
attribute:
<img src="{{ "/" | absolute_url }}{% ministamp _assets/dog.jpg assets/dog.jpg %}" alt="My dog smiling to the camera" title="A photo of my dog" width="195" height="258" />
This feature can be combined with asset generation tools external toJekyll. For example, you can configure Sass to take input files from_assets/styles/*.scss
and to produce output to _tmp/site.css
. Then,you use the ministamp
tag to copy the file with a fingerprint toJekyll's site destination directory:
<link rel="stylesheet" href="{{ site.baseurl }}/{% ministamp _tmp/site.css assets/site.css %}">
ministamp
call syntaxThe argument for the ministamp
tag must be in YAML syntax, andparsing the argument as YAML must result either in a String or aHash. What you saw previously was the argument being parsed as a String;it's effectively a shorthand version of passing the argument as a Hashwith certain keys. That is, in the following call:
{% ministamp _tmp/site.css assets/site.css %}
the argument is a String: "_tmp/site.css assets/site.css"
. The call isequivalent to the following call with a Hash argument:
{% ministamp { source_path: _tmp/site.css, destination_path: assets/site.css } %}
The Hash argument allows expressing more options and quotingsource_path
and destination_path
values, if needed.
The supported keys for the Hash argument are:
Key | Required? | Value type | Value example | Default value | Description |
---|---|---|---|---|---|
source_path |
yes | string | '_tmp/site.css' |
- | The source path of the asset file, relative to the site directory. |
destination_path |
yes | string | 'assets/site.css' |
- | The destination path of the asset file, relative to Jekyll's site destination directory. If the value begins with / and render_basename_only is false , ministamp 's output will begin with / . |
render_basename_only |
no | boolean | true |
false |
If true , ministamp 's rendered URL will be the basename of the asset destination path. See Separating asset destination path from generated URL for more. |
With a Hash argument, the plugin processes source_path
anddestination_path
values through a tiny template engine. This allowsyou to use Liquid's variables as input to ministamp
tag. An examplewith Liquid's assign
tag:
{% assign asset_dir = 'assets' %}
<link rel="stylesheet" href="{% ministamp { source_path: _tmp/site.css, destination_path: '{{ asset_dir }}/site.css' } %}">
The above would use assets/site.css
as the destination path.
Note that you must quote destination_path
's value, otherwise YAML doesnot recognize it as a proper string.
To refer to Jekyll's configuration options (_config.yml
)in the template, prefix the variable name with site.
. For example, torefer to baseurl
option, use syntax {{ site.baseurl }}
in thetemplate.
See Variable templating for details about thetemplate syntax.
This is a straightforward way to bundle assets with any minificationtool that supports reading input from stdin and writing the output tostdout. You write the configuration for input sources directly into thecontent file where you want the markup tag for the bundle file toappear. The markup tag contains the path to the bundle file, and theJekyll's site destination directory will have the bundle file at thatpath. The path will contain an MD5 fingerprint.
Place the minibundle
Liquid block into the Liquid template filewhere you want the block's generated markup to appear. Write bundlingconfiguration inside the block in YAML syntax. For example, to bundlea set of JavaScript sources:
{% minibundle js %}
source_dir: _assets/scripts
destination_path: assets/site
baseurl: '{{ site.baseurl }}/'
assets:
- dependency
- app
attributes:
id: my-scripts
async:
{% endminibundle %}
Then, specify the command for launching your favorite minifier in_config.yml
:
baseurl: ''
minibundle:
minifier_commands:
js: node_modules/.bin/uglifyjs
When it's time to render the minibundle
block, the plugin launches theminifier and connects to it with a Unix pipe. The plugin feeds thecontents of the asset files in source_dir
directory as input to theminifier (stdin). The feeding order is the order of the files in theassets
key in the block configuration. The plugin expects the minifierto produce output (stdout) and writes it to the file atdestination_path
in Jekyll's site destination directory. The filenamewill contain a fingerprint.
The block outputs <link>
(for css
type) or <script>
(for js
type) HTML element into Liquid's template rendering outcome. Continuingthe example above, the block's output will be:
<script src="/assets/site-8e764372a0dbd296033cb2a416f064b5.js" type="text/javascript" id="my-scripts" async></script>
You can pass custom attributes, like id="my-scripts"
and async
above, to the generated markup with attributes
map inside theminibundle
block.
As shown above for the baseurl
key, you can use Liquid template syntaxinside the contents of the block. Liquid renders block contents beforethe minibundle
block gets the turn to render itself. Just ensure thatblock contents will result in valid YAML.
For bundling CSS assets, use css
as the argument to the minibundle
block:
{% minibundle css %}
source_dir: _assets/styles
destination_path: assets/site
baseurl: '{{ site.baseurl }}/'
assets:
- reset
- common
attributes:
media: screen
{% endminibundle %}
And then specify the minifier command in _config.yml
:
minibundle:
minifier_commands:
css: _bin/remove_whitespace
js: node_modules/.bin/uglifyjs
minibundle
call syntaxUse css
or js
as the argument to the opening tag, for example {% minibundle css %}
.
The block contents must be in YAML syntax. The supported keys are:
Key | Value type | Value example | Default value | Description |
---|---|---|---|---|
source_dir |
string | - | '_assets' |
The source directory of assets , relative to the site directory. You can use period (. ) to select the site directory itself. |
assets |
array of strings | ['deps/one', 'deps/two', 'app'] |
[] |
Array of assets relative to source_dir directory, without type extension. These are the asset files to be bundled, in order, into one bundle destination file. |
destination_path |
string | - | 'assets/site' |
The destination path of the bundle file, without type extension, relative to Jekyll's site destination directory. If the value begins with / and baseurl is empty, baseurl will be set to '/' implicitly. |
baseurl |
string | '{{ site.baseurl }}/' |
'' |
If nonempty, the bundle destination URL inside minibundle 's rendered HTML element will be this value prepended to the destination path of the bundle file. Ignored if destination_baseurl is nonempty. |
destination_baseurl |
string | '{{ site.cdn_baseurl }}/' |
'' |
If nonempty, the bundle destination URL inside minibundle 's rendered HTML element will be this value prepended to the basename of the bundle destination path. See Separating asset destination path from generated URL for more. |
attributes |
map of keys to string values | {id: my-link, media: screen} |
{} |
Custom HTML element attributes to be added to minibundle 's rendered HTML element. |
minifier_cmd |
string | 'node_modules/.bin/uglifyjs' |
- | Minifier command specific to this bundle. See Minifier command specification for more. |
You can specify minifier commands in three places:
In _config.yml
(as shown earlier):
minibundle:
minifier_commands:
css: _bin/remove_whitespace
js: node_modules/.bin/uglifyjs
As environment variables:
export JEKYLL_MINIBUNDLE_CMD_CSS=_bin/remove_whitespace
export JEKYLL_MINIBUNDLE_CMD_JS="node_modules/.bin/uglifyjs"
Inside the minibundle
block with minifier_cmd
option, allowingblocks to have different commands from each other:
{% minibundle js %}
source_dir: _assets/scripts
destination_path: assets/site
minifier_cmd: node_modules/.bin/uglifyjs
assets:
- dependency
- app
attributes:
id: my-scripts
{% endminibundle %}
These ways of specification are listed in increasing order ofspecificity. Should multiple commands apply to a block, the mostspecific one wins. For example, the minifier_cmd
option inside the {% minibundle js }%
block overrides the setting in the$JEKYLL_MINIBUNDLE_CMD_JS
environment variable.
It's recommended that you exclude the files you use as asset sourcesfrom Jekyll itself. Otherwise, you end up with duplicate files in thesite destination directory.
For example, in the following snippet we're using assets/src.css
asasset source to ministamp
tag:
<!-- BAD: unless assets dir is excluded, both src.css and dest.css will be copied to site destination directory -->
<link rel="stylesheet" href="{{ site.baseurl }}/{% ministamp assets/src.css assets/dest.css %}" media="screen, projection">
By default, Jekyll includes this file to the site destinationdirectory. As a result, there will be both src.css
anddest-<md5>.css
files in _site/assets/
directory, which you probablydo not want.
In order to avoid this, exclude the asset source file from Jekyll.Because Jekyll's site generation excludes underscore directories (thatis, directories whose name begins with underscore character), considerusing the following directory layout:
_assets/
for JavaScript and CSS assets handled by the plugin thatare in version control_tmp/
for temporary JavaScript and CSS assets handled by the pluginthat are not in version control (for example, Sass output files)assets/
for images and other assets handled by Jekyll directlyHowever, Jekyll's watch mode (auto-regeneration) does monitor filesinside underscore directories. If such a file is modified, the watchmode triggers site generation. For Minibundle's functionality, this isbeneficial: it allows the plugin to check if assets need to be updatedto the site destination directory.
The exclude
Jekyll configuration option affects Jekyll'swatch mode. Given the recommended directory layout above, if you set thefollowing in _config.yml
:
exclude:
- _assets
- _tmp
Then Jekyll won't see if files inside those directories have changed andthe plugin won't get the chance to update assets to the site destinationdirectory. So, don't explicitly exclude the _assets
and _tmp
directories.
See Jekyll configuration for more about excluding filesand directories.
If you set the $JEKYLL_MINIBUNDLE_MODE
environment variable todevelopment
, then the plugin will copy asset files as is to Jekyll'ssite destination directory and omit fingerprinting.
The development mode changes minibundle
block's destination_path
option to be the base directory for files mentioned in the assets
option. This is useful in development workflow, where you need thefilenames and line numbers of the original asset sources.
$ JEKYLL_MINIBUNDLE_MODE=development jekyll serve --watch
Alternatively, you can enable development mode from _config.yml
:
minibundle:
mode: development
Should both be defined, the setting from the environment variable wins.
The template engine used by ministamp
tag's Hash argument has syntaxresembling the ones of Liquid and Mustache, with {{
and }}
tagssurrounding the variable to be substituted into the output string. Forexample, given Liquid variable var = 'foo'
, the template begin{{ var }}end
results in beginfooend
.
The engine supports variable substitution only. It does not supportother expressions. If you need to, you can write complex expressions inLiquid, store the result to a variable, and use the variable in thetemplate.
If you need literal {
or }
characters in the template, you canescape them with backslash. For example, \{
results in {
in theoutput. To output backslash character itself, write it twice: \\
results in \
in the output.
Inside variable subsitution (between {{
and }}
), anything before theclosing }}
tag is interpreted as part of the variable name, exceptthat the engine removes any leading and trailing whitespace from thename. For example, in the template {{ var } }}
, var }
is treated asthe name of the variable.
A reference to undefined variable results in empty string. For example,begin{{ nosuch }}end
will output beginend
if there's no variablenamed nosuch
.
Use the render_basename_only: true
option of the ministamp
tag andthe destination_baseurl
option of the minibundle
block to separatethe destination path of the asset file from the generated URL of theasset. This allows you to serve the asset from a separate domain, forexample.
Example usage, with the following content in _config.yml
:
cdn_baseurl: 'https://cdn.example.com'
For the ministamp
tag:
<link rel="stylesheet" href="{{ site.cdn_baseurl }}/css/{% ministamp { source_path: '_tmp/site.css', destination_path: assets/site.css, render_basename_only: true } %}">
The asset file will be in Jekyll's site destination directory with pathassets/site-ff9c63f843b11f9c3666fe46caaddea8.css
, and Liquid'srendering will result in:
<link rel="stylesheet" href="https://cdn.example.com/css/site-ff9c63f843b11f9c3666fe46caaddea8.css">
For the minibundle
block:
{% minibundle js %}
source_dir: _assets/scripts
destination_path: assets/site
destination_baseurl: '{{ site.cdn_baseurl }}/js/'
assets:
- dependency
- app
{% endminibundle %}
The bundle file will be in Jekyll's site destination directory with pathassets/site-4782a1f67803038d4f8351051e67deb8.js
, and Liquid'srendering will result in:
<script type="text/javascript" src="https://cdn.example.com/js/site-4782a1f67803038d4f8351051e67deb8.js"></script>
Use Liquid's capture
block to store outputrendered inside the block to a variable, as a string. Then you canprocess the string as you like.
For example:
{% capture site_css %}{% ministamp _assets/site.css assets/site.css %}{% endcapture %}
<link rel="stylesheet" href="{{ site_css | remove_first: "assets/" }}">
Liquid's rendering outcome:
<link rel="stylesheet" href="site-390be921ee0eff063817bb5ef2954300.css">
See the sources of an example site.
The plugin does not work with Jekyll's incremental rebuild feature(Jekyll option --incremental
).
MIT. See LICENSE.txt.
Jekyll 是一个简单的免费的Blog生成工具,类似WordPress。但是和WordPress又有很大的不同,原因是jekyll只是一个生成静态网页的工具,不需要数据库支持。但是可以配合第三方服务,例如discuz。最关键的是jekyll可以免费部署在Github上,而且可以绑定自己的域名。 快速安装指令: gem install jekylljekyll new my-awesome-sit
中文网站 jekyllcn 快速开始 ~ $ gem install jekyll bundler ~ $ jekyll new my-awesome-site ~ $ cd my-awesome-site ~/my-awesome-site $ bundle install ~/my-awesome-site $ bundle exec jekyll serve # => 打开浏览器 http
jekyll-admin 是一个 jekyll 插件,为用户提供了传统 CMS(内容管理系统)风格的图形化界面来创作内容和管理 jekyll 网站。 该项目分为两部分。基于 Ruby 的 HTTP API 处理 jekyll 和文件系统的操作部分,以及在这个 API 基础上的基于 JavaScript 的前端部分。 安装: 就像安装其他插件一样,请参阅 jekyll 文档的插件安装部分安装 jek
Jekyll的增强版,使用Markdown来写日志。 Jekyll采用静态文件方式管理,不需要数据库即可支持一个独立博客站点,在github-pages平台上被普遍采用。Jekyll-Bootstrap在Jekyll基础上,集成了twitter-bootstrap界面风格和一些实用的插件,并且易于扩展。
Jekyll Docker Jekyll Docker is a software image that has Jekyll and many of its dependencies ready to use for you in an encapsulated format. It includes a default set of gems, different image types wi
jekyll-katex This is a Jekyll plugin for performing compile-time math rendering via the KaTeX library.KaTeX is a library for rending math on the web using LaTeX, similar to MathJax. KaTeX differs from
�� Jekyll Spaceship �� Jekyll plugin for Astronauts. Install | Config | Usage | Credits | License Built with ❤︎ by jeffreytse and contributors Spaceship is a minimalistic, powerful and extremely custo
reveal-jekyll Transforms Markdown files into presentation slides using reveal.js and Jekyll. The theme is based on Solarized Colors (by Ethan Schoonover) containing a light and a dark theme. reveal-je