How I learnt webpack 3 and created a Jekyll and webpack boilerplate

#5 — Fifth month of my challenge: 12 topics to learn in 12 months

It’s webpack not Jetpack … but the idea is the same, to give boost!

After learning how to steal like an artist, I decided to go back to some more technical knowledge again for my fifth month of the Learning lab challenge.

This month the challenge will be to learn about webpack 3. You may ask yourself, what is this? It’s a module bundler for web development. Isn’t that clear? If not I invite you to keep reading this article to understand better what the h*** is this and why is so important😎!

The reasons why I want to learn webpack 3 are various. 
First, as you could read in the previous articles, I am a frontend developer and a designer, so I need to be up to date with the latest technologies. 
Second, frontend development is evolving very fast, every day new technologies appear and webpack 3 is the brand new version of webpack. Moreover, people are now using webpack to replace other tools that used to be part of their development toolkit.

My knowledge of webpack is not very extensive, I used it in my project Kanbanote merely knowing what it does but without knowing how it worked, or how to change the settings. I was just playing with black boxes and that’s something very bad to do for a developer.

So enough with the talking, let’s do it! I started this topic on the 25th of July 😀. This article may be a bit technical, feel free to scroll it to the results if you are not a technical person 😬. Don’t worry next one will be different!

Preparation

  1. Finding a mentor
    For this learning I didn’t have any mentor. Yeah… I know, this is one of the bases of my methodology. I contacted an employee of my previous company who was a mentor to teach me some JavaScript features but he never answered… 😪
  2. Defining the scope of the topic
    The scope of this topic will be to understand what is webpack exactly, what can it do, how to set it up in a project, and how to take full advantage of it.
  3. Choosing a learning resource
    In order to learn webpack, I just went through the documentation and followed it. There is nothing better for learning about a tool or library than reading the documentation.
  4. Defining a project
    I will build a boilerplate of Jekyll with webpack. Jekyll is a static website generator that I often use for my projects. It has a lot of plugins that are great but still lacking some of the modern development features and optimisations that I will add with webpack. This boilerplate will be open source and on MIT license.
Learning without mentor is indeed less fun!

The documentation

In order to start with webpack, I went to the official website to checked out the concept pages and the guide.

What is webpack?

The following image is a good summary of what webpack does.

Résultat de recherche d'images pour "webpack3"

Webpack turns all your module dependencies such as npm libraries, images, fonts or JavaScript files into assets.

webpack is a module bundler for modern JavaScript applications. When webpack processes your application, it recursively builds a dependency graph that includes every module your application needs, then packages all of those modules into a small number of bundles — often only one — to be loaded by the browser.”

So instead of having to load your different libraries you will just load the bundles generated by webpack. You can see the official definition above. webpack will do it in a smart way. For example if you use only a few classes of a library it will load only them and not the full library.

Moreover by adding a few plugins you can automate tasks such as transpiling another language (ES6, TypeScript, Coffescript), minifying your CSS files, and optimizing your images.

Finally it gives you a development server that watches your changes and reloads automatically the page that it will serve.

How is it different from Gulp, Grunt?
The first time I heard about webpack, I was asking myself this question.
Gulp and Grunt are JavaScript task runners, basically they create and execute scripts. This is very different from what webpack does but Gulp and Grunt are often used to apply transformations on top of your project, such as minifying files, optimizing images and running a development server. So you can replace this kind of use with webpack along with npm scripts. Npm scripts will run commands including running webpack, and webpack will handle the transformations and the bundling.

Nevertheless webpack has other alternatives such as Browserify or SystemJS.

How did I practice?

Learning Webpack through its official documentation was quite interesting because every time I was seeing a new concept I was directly applying it to the boilerplate I was building, in that way I could apply and put into practise directly what I just read, which is the best thing ever for learning.

Because of that I could go really fast in both the learning, and the boilerplate creation. Once the reading of the documentation was finished I just focused fully on the creation of the boilerplate and I only checked the documentation when I was facing issues.

Webpack concept

Webpack configuration is made in a JavaScript configuration file and it looks like this.

const config = {
entry: './path/to/my/entry/file.js',
output: {
// ...
},
module: {
rules: [
// ...
]
},
plugins: [
// ...
]
};

module.exports = config;

As you can see there are 4 categories linked to 4 concepts: the entry point, the output, the loaders that you put in modules.rules and the plugins.

Actually the minimum configuration needed is the entry and the output.

Input

Put here the entry point, or entry points (if you have many) of your JavaScript modules.

Output

Here you will put the path where you will export the bundles and also the name of your bundle.

Loaders

What webpack is doing is checking in your entry points what are the modules loaded through the import instruction.

import defaultMember from "module-name";
import { member } from "module-name";
import "module-name";
import "style.css";
import myLogo from 'images/logo.png';

So webpack will check here and compare the loading rules. Depending on what the rules are it will decide whether to put these files in the bundle.

You can import any kind of files, JavaScript, css, images and of course you need a loader for each.

module.exports = {
module: {
rules: [
{ test: /\.css$/, use: 'css-loader' },
{
test: /\.js$/,
exclude: /(node_modules|bower_components)/,
use: {
loader: 'babel-loader',
options: {
presets: ['env']
}
}
},
]
}
};

The previous code will load the CSS file using the css-loader, and the js files and using the babel loader which is going to translate ES6 to ES5.

Plugins

The plugins will perform actions on the files that are loaded. You have a lot of plugins available and you can also build them (maybe this will be another learning month! 😬).

There are many examples of plugins such as HtmlWebpackPlugin that performs actions to your html templates, it can for example add the JavaScript code there; UglifyJS which uglifies your code, or Imagemin plugin that compresses your images.

What else did I learn?

Through this documentation I learnt a lot of things:

  • How to setup the configuration file.
  • How to separate environments to have a development configuration file and a production configuration file.
  • How to use the HtmlWebpackPlugin in order to inject the loading of the JavaScript bundles.
  • How to set up the webpack dev server.
  • How to activate the source map for a better debugging of the development files.
  • How smart webpack loads the functions and the modules, only the ones that are being used.
  • Code splitting, and putting common libraries in common chunk.
  • How to automatically put hashes in the assets filenames for a better cache management

If you want to also implement webpack in a project I really recommend you to read the official documentation instead of just reading tutorials. This document is quite short and very complete and easy to understand.

Let’s see now how I created this Jekyll webpack boilerplate 😉.

The creation of the Jekyll wepack boilerplate

The reason why I am creating a Jekyll webpack boilerplate is because I often use Jekyll and every time I use it I have to repeat the same preparation tasks and also because I miss the assets optimisations in my process. Even though there are a lot of Jekyll plugins to do these optimisations I thought it would be a good opportunity to try to implement webpack. Moreover some of these optimisations are nonexistent for Jekyll.

What is Jekyll

For your information, Jekyll is a static generator website.

“Instead of using databases, Jekyll takes the content, renders Markdown or Textile and Liquid templates, and produces a complete, static website ready to be served by Apache HTTP Server, Nginx or another web server. Jekyll is the engine behind GitHub Pages, a GitHub feature that allows users to host websites based on their GitHub repositories.” — Wikipedia

Static websites are really useful since we can easily edit and host them for free in many hosting providers or even CDN (Content Delivery Network) like:

You can of course also use your static pages to serve your Single Pages Applications instead of using a PHP, Ruby or Java server.

While doing my project I looked for some good boilerplates of Jekyll with webpack but none of them were fulfilling my requirements. Most of them were just compiling ES6 to JavaScript.

The requirements of the boilerplate

I made this list of requirements based on the projects I usually do. I completed this list based on this Web Launch Checklist to have the best optimisations I could bring. I ended up looking for the best plugins for webpack and Jekyll to see if they would be useful for the boilerplate, and added the ones that were good.

Here are my requirements:

  • Jekyll
  • Webpack
  • Live reload — To reload every time the code is updated
  • Autoprefixer for CSS — To have automatically the CSS prefix for each browser
  • Sass
  • ES6 babel JS — To write the JavaScript following ES6 specification and also be compiled in ES5
  • Image optimization — To reduce the sizes of images
  • CSS minification
  • JavaScript minification
  • Critical CSS Path — To inline in the html page a part of the CSS for a better rendering of the page
  • Favicon generated automatically
  • Progressive Web App — Check my previous article if you don’t know what is a PWA
  • Colored navbar
  • Google Analytics
  • Doorbell
  • Cookie consent
  • Internationalization plugin — To have a multi language website
  • JavaScript linter — For a better code style
  • Having a default simple template
  • Accelerated mobile pages for posts — The new Google AMP protocol for faster pages in mobile
  • Easy to deploy (with Netlify)

That’s a big list!

The implementation

As described above I did the implementation along with the reading of webpack’s documentation. That is why it went quite fast.

Nevertheless I faced a few difficulties and had to take some decisions 😶.

First, regarding the live reload, webpack is reloading only the files that are being loaded by the loaders. This is why it doesn’t reload when you are editing the Jekyll files. In order to fix that I decided to use browser sync webpack plugin, which makes it work by specifying the “_site” folder, where is served and where webpack is updating the files. It is a bit slow though but good enough. Note that for some files Jekyll is not updating the build (for example the config file) so you will have to start and relaunch the development server.

Second, I wanted to have a look at PostCSS the future of CSS development, I wanted to use it to compile Sass, I read that the performances were better than using the original Sass compiler. For some reason it didn’t work so I kept using the original one.

Regarding the offline mode, I used to have a service worker generated, but now I had to choose between Jekyll offline and Webpack offline. I tried both and the Jekyll offline (which was caching all the pages well) wasn’t building a good service worker as it was using the most basic template. webpack offline, however, was only caching the assets generated by webpack and I needed all the Jekyll pages. So I ended up with Sw-precache that works directly in command line.

Talking about command lines, as I describe below, I decided to use npm scripts. All my serving building scripts are in package.json and I can run them with yarn start for example or npm run start .

Finally, I wanted to have a hash in my assets, the hash is a generated key that is in the filename app-775af5b1861d453bb7b.bundle.js . By changing this hash at every build the browser will not load the previous one from the cache. It helps you handle your cache. I made this for the JavaScript assets but couldn’t make it for the CSS files because the same CSS file was used to generate the critical path. I needed to specify the path and the name of this CSS file to generate the critical path.

Writing documentation

Once the boilerplate was done I created the documentation to understand how to use it since my plan was to release it open source so it can be used by anyone.

Creating a logo

In order to create the logo I tried to find an intersection between Jekyll logo (the tube test) and webpack (a cube inside a cube) and I came up with a cristalin structure (like you can see in the atomium) because it’s part of chemistry (Jekyll) and it’s cubic like webpack. Moreover you can see the atoms that are linked together. Jekyll are the atoms, and webpack the links between each other. Yes I know it’s very poetic.

Here is the beautiful and simple logo!

The final performance test

In order to test performance I decided to implement and test the boilerplate with a project that I made with Jekyll. So I quickly moved the assets, templates and translations files, I deleted a few useless files, and changed the config ones. To finish the implementation I had to change a bit the JavaScript, to load the libraries as dependencies and to import them in the main JS entry point. It went really fast and worked well.

I then tested the performance with Google Lighthouse and look at the differences. They are very good. Do you think it can be improved? Please let me know in the comments or make a Pull Request to the Github repository 😀.

SConférenciers made with Jekyll
SConférenciers made with Jekyll webpack boilerplate (with PWA generated)

The final result

The boilerplate is here and ready. Feel free to use it, clone it, fork it, improve it or contribute to it: https://github.com/sandoche/Jekyll-webpack-boilerplate

Feedback from this learning month

What went well

  • The time scope: I finished on the day of 12th of August
  • The learning & practicing in parallel
  • The implementation of the boilerplate
  • The result of performance
  • The use of previous knowledge

What to improve

  • Having a mentor would have been better
  • Building a webpack plugin would make me understand how the plugin works inside
  • I didn’t fully understand how PostCSS works and how to make it compile Sass

If you liked this post, please click the clap 👏button below a few times to show your support! Also, feel free to comment and give any kind of feedback. Don’t forget to follow me!