Webpack From Zero to Hero

May 06, 2019 0 Comments

Webpack From Zero to Hero

 

 

Picture Under Creative Commons License (Source: Flickr)

This article is part of the Webpack from Zero to Hero series, for more background or for the index, check the “Chapter 0: History”.

Previous - Chapter 1: Getting Started with the Basics

Next - Chapter 3: Everything is a Module

Last chapter we saw the need for BabelJS to transpile our code, and the way to make Webpack pass files to other parsers like BabelJS, which is through loaders. But until now, we were running Webpack with no configuration file. In this chapter we’re going to create our very first Webpack configuration, learn how to use a loader and set up our local development server. Let’s start!

Chotto matte kudasai Marie Sensei, let’s keep our Webpack configuration clean from the start!

First we need to install the dependencies:

yarn add @babel/core @babel/preset-env babel-loader --dev
  • Babel Core: it has all logic necessary for transformations and also some polyfills;
  • Babel Preset Env: it is able to choose the right transformations/polyfills depending on the target browser list;
  • Babel Loader: it will beresponsible for receiving the input file from Webpack and passing it through BabelJS.

First let’s setup the Babel to use the preset-env. Create a file called .babelrc with this content:

And set a browser list range on package.json:

Note: I’m creating a pretty generic query here. For production apps, always check analytics to properly choose your target browsers!

Let’s see how many browsers will be targeted with this query:

npx browserslist

As we don’t want to install browserslist just for a single run, we will directly use it through npx. The output will be (from the time of this article publication):

So one of the baselines for transpiling/polyfilling will probably be Internet Explorer 11 (and its mobile version). As I said before, don’t go for queries which are too generic, instead build the list based on usage data from your target audience.

Now we just need to “tell Webpack” that all JS files should pass through Babel. Let’s create a webpack.config.js file on the project root directory and add this code:

Webpack config is just a NodeJS module, exporting the configuration object.

😖- “Hey, I don’t understand regular expressions, can you explain that?”

Right behind ya⚡️! The expression above should just match all files ending with .js:

  • We need to escape the “.” from .js, because in regex lingo it is used as a mask for “any character” and we don’t want it, we want the actual period char;
  • Then we set the “$”, stating that the matching should end right after .js, so we don’t mismatch things like .json.
  • Be happy, you’re a regex master now 💪 !

Some will say to put all babel and browserslist configuration inside the Webpack configuration, but in my point of view, both Babel and browserslist configuration tend to stay the same (size-wise), while Webpack config tends to grow, so the key to keep it organized is to make it as modular as possible. Like with any normal source code (remember that the Webpack configuration is a Node.js file!), if you see it’s growing, assuming too many responsibilities and repeating the code, you should break it up!

For any app/site development, we need to create a dev environment, where we can test and see the updates right away. And since we haven’t seen our actual code running in the browser yet, I think is time already, let’s go and do it!

As you may know or have heard about, Webpack has a pretty nice tool called webpack-dev-server, where you can simulate an HTTP server on your machine integrated with a hot module reloading feature. It is pretty nice as the browser reloads every time a compilation is triggered, and you don’t need to be reloading the page manually every time you do a change to your code.

We will install both the webpack dev server and the plugin to generate an index.html for us:

yarn add webpack-dev-server html-webpack-plugin --dev

On the webpack config we add the plugin to the “plugins” section:

Tip of the day: If you don’t want to output an index.html on the production builds, we can skip it by checking the webpack argv.mode:

Some explanation for the code above:

  • Webpack accepts both an Object or a Function as configuration. When you provide it as a function, it will inject the env and the argv as parameters:
  • env: everything the client (webpack-cli) receives under the env param comes as an env object property, e.g.:
--env.test or --env.customValue="Hello there!"
  • argv: all the arguments given to webpack config that are part of the configuration schema, e.g.:
--mode=production

As we’re starting simple there’s no need yet to create two configuration files, one for development and another for production, so let’s stick to simplicity.

Now is time to run the server, which accepts the same arguments that the webpack client does (plus some additional ones). Let’s remove the “build:dev” in package.json and change to:

Let’s test it!

yarn start:dev

And you’re going to see something like this:

Now open the page at http://localhost:8080/, open the dev tools on the console tab, and you’ll see this:

Hello OLX Dev!!

If you click on the link right after the console.log result on the dev tools console tab, you’re going to be forwarded to the sources panel, and you’re going to see something interesting:

This is the transpiled code by Babel. But how can I check my actual code? Enter the source maps! ⚡️

Source maps are something that will map your actual source to the final bundled source, letting you use breakpoints and see the actual code lines on stack traces in case of exceptions. To enable them, just add this to webpack.config.js:

devtool: "source-map",

Stop and run the dev server again and check the source on the console tab link, and this time you’re going to see the actual source code!

Now that we have everything up and running on our development server, we have paved a way to add more loaders and parse all kinds of files. But let’s read about that in the next chapter - see you there!


Tag cloud