In my post from 2015 on build process of my own jekyll-based blog, I'd implemented blog deploy script with Gulp. It featured with html/css/js checking and minifications. It was very usable for final deploying of blog to hosting, but not much convenient when I wrote the posts.
Here is an explanation how I'd integrated browser-sync
into my process.
When I wrote the posts I used Sublime Text with following plugins:
- MarkdownEditing for syntax highlighting
- Markdown Preview for preview results in browser
Later I discovered Atom which supports markdown editing and preview out of the box.
This editors is convenient when you write posts but they are cannot show post inside my blog's markup. Also, markup editing with selected process was painful. I needed to rebuild blog on each post or style change manually with gulp build
command.
I tolerate this process for two years and now I'd like to improve this experience. I bet on jekyll build --watch --incremental
command in conjunction with browser-sync
web-server and browser synchronization library.
jekyll build --watch
When you run jekyll build
command, jekyll will delete all the contents of _site
folder and will generate all site content again. There is --watch
command line modifier which stands for "watch for changes and rebuild".
The challenge was to copy external bower components to _site/vendor
folder. Jekyll deleted this folder each time I executed jekyll build
or jekyll build --watch
.
The solution is to tell jekyll which of folders he should not delete. It is possible with keep_files configuration option. It stands for "when clobbering the _site
destination, keep the selected files". It is useful for files that are not generated by jekyll. The paths are relative to the _site
destination.
I'd added following line to my _config.yml
:
keep_files: [ "vendor" ]
Now jekyll will delete all content of _site
except vendor
folder.
browser-sync
I discovered browser-sync JavaScript library. It has built-in web server which includes into served HTML <body>
tag a custom <script>
with synchronization implementation. The idea of using this library is to watch changes with gulp and execute browserSync.reload()
when files in _site
changes (when jekyll rewrites changed posts or styles).
gulp integration
Here I specified four gulp tasks:
jekyll-watch
task runs jekyll in incremental watch modecopy_bower_components
task was not changed since my post in 2015 and intended to copy external bower components intovendor
folder of_site
webserver
task- Runs browserSync webserver on port=4000
- Watch all the changes in jekyll output (
_site
). When change event is fired, browserSync will reload changed pages usingbrowserSync.reload()
. - Note
reloadThrottle
andreloadDebounce
settings which defines time window to minimize reloading of pages when multiple changes occured almost simultaneously - Note
setTimeout
to defer watching of changes. I need this becausejekyll-watch
andwebserver
tasks working in parallel and jekyll needs some time to generate the site content.
serve
task intended to run from command line and combines all necessary tasks to support build site, watching changes and reload pages in browser.
var gulp = require('gulp');
var browserSync = require('browser-sync').create();
var shell = require('gulp-shell');
gulp.task('jekyll-watch', shell.task(['jekyll build --watch --incremental']));
gulp.task('copy_bower_components', function() {
gulp.src([
'bower_components/bootstrap/dist/css/bootstrap.min.css',
'bower_components/bootstrap/dist/css/bootstrap-theme.min.css',
'bower_components/fontawesome/css/font-awesome.min.css',
'bower_components/normalize.css/normalize.css'
]).pipe(gulp.dest('./_site/vendor/css/'));
gulp.src([
'bower_components/bootstrap/dist/fonts/*',
'bower_components/fontawesome/fonts/*',
]).pipe(gulp.dest('./_site/vendor/fonts/'));
gulp.src([
'bower_components/bootstrap/dist/js/bootstrap.min.js',
'bower_components/jquery/dist/jquery.min.js',
]).pipe(gulp.dest('./_site/vendor/js/'));
gulp.src([
'bower_components/modernizr/modernizr.js',
]).pipe(uglify())
.pipe(gulp.dest('./_site/vendor/js/'));
});
gulp.task('webserver', function () {
browserSync.init({
port: 4000,
open: true,
reloadThrottle: 500,
reloadDebounce: 500,
server: {
baseDir: '_site/'
}
});
setTimeout(function () {
gulp.watch('_site/**/*.*').on('change', browserSync.reload);
}, 5000);
})
gulp.task('serve', ['jekyll-watch', 'copy_bower_components', 'webserver'], function () {});
Yes, html/js/css is not minified with this gulp serve
command. But it is not necessary for writing-time. I haven't changed my deploy script for production. See my previous post for details.
Conclusion
browser-sync
changed the way I can write posts and modify markup and styles for my blog. Manual work is minimized and I can preview my blog posts almost interactively. Solution is so simple that I can't imagine how I lived before without this stuff :).
Happy blogging!
Comments