Putting together the essential parts of Webpack and be on your way, wiser and calmer.

I decided to stop using create-react-app to bootstrap my projects a while back, and got my hands dirty putting pieces together, in the process, understanding the how and why of Babel and Webpack. This effort will enable me to easily maintain, modify, and optimize their settings as I see fit at my own pace in the future 💪.

But of course, you could eject from your ‘create-react-app’ project and get the loaded config for free, but I found it extremely difficult to maintain their structure and add more settings without breaking the build. Another common approach is to simply copy and paste settings that you can find scattered everywhere on the internet, slowly build up your webpack config. However, you need to be careful that they might be outdated, unnecessary, or worse, you don’t really know what you are doing, ending up with an unmaintainable mess of a config file by the end of it. 😖

I believe a more saner and calmer way to start is to build a solid mental model of how the fundamental pieces work together — which is the goal of this article, and you can then slowly augment it according to your needs, at your own pace, and structure them as it makes most sense to you. 🌞

So let’s do it, friends✊

OK, quickly, why do we even need Webpack — We need Webpack to bundle our import of Javascript, CSS, SVG, JPEG, PNG, fonts files into a single(or more) JS bundle file as well as cleverly insert the <style> and <link> into our index.html accordingly.

What about Babel? — So that we can write latest cool Javascript syntax and still be able to run them in older browsers that we have to support by transpiling our hip code to the appropriate older Javascript syntax. (We will see how Babel works with Webpack in the next post though.)

Here is a good article about how we have come to having to use Babel and Webpack in front-end development:

Alright, enough said, let’s take actions! 🚀

But let’s do some boring stuff first

In you terminal:

mkdir webpackbabel
cd webpackbabel

Now you are in your project folder. Then open in VSCode if you want:

code .

Then create the package.json file:

npm init -y

Now let’s create 3 source files in your root directory to feed Webpack later:

// helloWorld.jsimport "./helloWorld.css";export default "<span>Hey friends, its me, your brother</span>";// helloWorld.cssspan {
color: red;
font-size: 2rem;
}
// index.jsimport helloWorld from "./helloWorld";function testHelloWorld() {
document.body.innerHTML = helloWorld;
}
testHelloWorld();

Setup Webpack for Development mode

Instead of a single webpack.config.js to cater to both development and production mode, a better practice is to separate the config for each of them — webpack.dev.js and webpack.prod.js . So let’s do that with webpack.dev.js first.

Install some npm packages

As our dev dependencies:

npm i -D webpack webpack-cli webpack-dev-server css-loader html-webpack-plugin style-loader

webpack.dev.js

Let’s briefly mention each of the properties:

  • mode — Usually it’s production or development , and webpack will do its thing accordingly.
  • entry — This points to the first file — in our case the index.js — from which webpack will start to build the dependency graph of your app.
  • output — Configures our output folder(the path property) and the files’ name inside(the filenameproperty).
  • devServer — Configures the behaviour of webpack-dev-server . The comments in the gist should explain it or visit the link for more info.
  • devtool — Generates your source maps. Useful for displaying line number when error occurs.
  • plugins — Plugins can do amazing stuff in webpack; here we use one to automatically create the index.html for us! Sick!
  • module — A feature specific to webpack is that it allows you to import any files other than Javascript or JSON as if they were a module. So, like in the helloWorld.js , we import a .css file — import "./helloWorld.css ! When you do that, you are telling webpack’s compiler the following:

“Hey webpack compiler, when you come across a path that resolves to a ‘.css’ file inside of a require()/import statement, use the css-loader and then the style-loaderto transform it before you add it to the bundle.”

And that’s all we need to get development going! 💅

Now we just need to run it. Let’s create a npm script for that.

In your package.json, add the bolded line:

"scripts": {
"start": "webpack --config webpack.dev.js"
}

Now in your terminal run npm start to let webpack do the compiling and bundling work. Once it’s finished, you will see a dist folder created for you. Inside you will find index.html and your main.bundle.js bundle file.

Open the index.html in a browser, and you will see the brotherhood message in red color and the right font size. If you view source, you will see our CSS declarations have been inlined by the style-loader as expected. But as you will see in a bit, we won’t inline but extract our CSS in production mode.

OK, one last thing before we move on: modify our npm script to run our webpack config with webpack-dev-server instead:

"scripts": {
"start": "webpack-dev-server --config webpack.dev.js"
}

npm start again and you will be given a localhost URL for your development! So make changes to your source files and watch it auto reload for you! 🙌

Setup Webpack for Production mode

We have sailed pass the rough sea. This is going to be a lot easier. 🚢

For production, we are gonna do a few things proper now. Specifically:

  1. Instead of inline CSS, we extract them into separate file.
  2. We will fingerprint our JS bundle and CSS files for cache busting purposes.

Install some npm packages

npm i -D mini-css-extract-plugin clean-webpack-plugin

webpack.prod.js

Much of it should be familiar to you. 🙌

To do things proper as promised above, what’s new in this config is that:

  1. We added the [hash] in Line-10. hash is one of the possible values as documented here.
  2. We replaced style-loader with a loader from a plugin called ‘mini-css-extract-plugin’ that extracts our CSS into a .css file!

Plus there is a bonus plugin in there called ‘clean-webpack-plugin’ which deletes the existing ‘dist’ folder for us whenever we trigger a build! 🎊

And that’s it! Now let’s create another npm script for triggering a build 🚀

"scripts": {
"start": "webpack-dev-server --config webpack.dev.js",
"build": "webpack --config webpack.prod.js"
}

Notice that we have to just use ‘webpack’. Then we run npm run build .

As before, we see a ‘dist’ folder. Open it and you will see a bunch of finger-printed JS and CSS files. Open the index.html and there it is, all of them, in their right place and format. 😺

(Here is the obligatory repo)

Advanced stuff

Remember I mentioned about the possibility of augmentation? Here are 2 possible starting points:

  1. Make Webpack do more works for you; Add more loaders and plugins; Handle different kind of files; Implement critical CSS; optimize your bundle, and more. Here is good reference.
  2. Structure your webpack config to make it maintainable as you add more functionalities. If you need inspiration, this article separates into files, each for:
  • paths —the entry, output paths etc.
  • module.rules
  • webpack.common.js
  • webpack.dev.js
  • webpack.prod.js

And it glues them all together in the good ol’ webpack.config.js file. 😃

But always remember the YAGNI principle: Enhance and refactor in ways that make most sense to you and team only when it’s absolutely necessary.

ok bai bai~ 🎈

“Sky” by Kheoh Yee Wei

Get the Medium app

A button that says 'Download on the App Store', and if clicked it will lead you to the iOS App store
A button that says 'Get it on, Google Play', and if clicked it will lead you to the Google Play store