Basics of Webpack – module bundler

Webpack is a module bundler. It takes you code transforms and bundles it, then returns a new compiled version. If you want to write ES6 Javascript code or React then I think Webpack is the better option.

what-is-webpack

webpack – Module Bundler

Webpack is a very complex tool. I have been using it for 6 months and still haven’t used it to its full potential. I’m going to cover the very basics but will get you up and running with a little project.

So let’s start

There are three key parts to a basic Webpack configuration.

  1. entry – the starting point of your application
  2. loaders –  the transformations which you want to make on your code
  3. output – where you want your compiled code to go

Let’s move to configuration

Let’s start by creating a package.json file in the root of your project by running npm init, keep pressing enter and fill out the information asked if you want, otherwise just keep pressing enter till it’s done. Look in the root of your project and you will see a package.json file has been created with the information you gave.

Now let’s install Webpack as a dev dependency in this project:

npm install webpack --save-dev

Take another look at your package.json file and you’ll see a new devDependencies property has been added.

Next create a webpack.config.js file in the root of your project, this will contain all of our Webpack configurations. You can use different webpack configuration files for production and for development, but for this we’ll only be working with one file.

At the top of your file let’s write :

module.exports = {
  entry: [
    './app/index.js'
  ]
}

Here we have given our object a property of entry and a value which is an array, with a string that points to the index.js file in our app directory. This could just be a string instead of an array like I’ve done, but Webpack does allow you to have several entry points so I always default to an array just in case I add another.

Now that we have told Webpack where to start we need to tell it which transforms to make on the code. We add a module property to the object we’re exporting, then that module property will have another property of loaders which is an array. Now your webpack.config.js file should look like this.

module.exports = {
  entry: [
    './app/index.js'
  ],
  module: {
    loaders: []
  }
}

Let’s say we want to install the babel-loader module into our project so that the browser can understand the latest and most awesome ES6 JavaScript we are writing. You run:

npm install babel-loader babel-core babel-preset-es2015 --save-dev

I’m not going to go into too much details about what to write here as this can vary between projects plus the purpose of this tutorials is to show you what you’ll need in your webpack.config.js file. And these settings can vary between projects. For this loader we’ll do the following:

module.exports = {
  entry: [
    './app/index.js'
  ],
  module: {
    loaders: [
      {
        test: /\.js$/, 
        include:  __dirname + '/app',
        loader: 'babel?presets[]=es2015'
      }
    ]
  }
}

Let’s step through what we’ve done. The first part is test, it may look a little scary if you’ve not seen a regular expression before but all this is doing is telling Webpack to only run this loader on files with the .js extension. Next is include, this tells Webpack to only run the loader on files in the ./app directory. We only want to transform code we have written not code from other npm modules added to the project. The last part is loader, this tells Webpack which transformation to run on all paths that match test and are in the include.

You can find the recommended loaders config in the README of the project you want to install.

Now the third and final part to Webpack, the part where we want our transformed code to go. We add another property called output, with a filename and path. Like so:

module.exports = {
  entry: [
    './app/index.js'
  ],
  module: {
    loaders: [
      {
        test: /\.js$/, 
        include:  __dirname + '/app',
        loader: 'babel?presets[]=es2015'
      }
    ]
  },
  output: {
    filename: 'index_bundle.js',
    path: __dirname + '/dist'
  }
}

Here we can see filename is the name of the file that Webpack is going to create which contains our new transformed code. And path is the specific directory where the new filename is going to be placed.

So now when Webpack runs, our code will be transformed and will be referenced at dist/index_bundle.js. Well that’s ok, but we need our HTML to reference this specific file too.

Let’s jump into little more!!

Now we need to come up with a plan to get our HTML to reference the compiled file. At the moment the code we’re developing with is in the app directory and our transformed code is in the dist directory. We want to only ever edit the index.html located in the app folder.

There are several ways of doing this in Webpack. We could copy and paste the file into the dist folder but you would need to do this every time you made a change which is not an effective workflow.

So the next part of the tutorial is not essential for Webpack as it can be done in several ways, this way is just one way simple way for a static structure like we have in this tutorial.

We are going to use a Webpack tool that will essentially do the copy and pasting for us, called HTML Webpack Plugin. Let’s install this npm module to our project in our Terminal with the command:

npm install html-webpack-plugin --save-dev

Now we need to tell Webpack what we want to do with it. Firstly, we need to import this plugin at the top of your webpack.config.js file, then create a new instance of HTMLWebpackPlugin and specify two things.

var HtmlWebpackPlugin = require('html-webpack-plugin');
var HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/index.html',
  filename: 'index.html'
});

The template is the app/index.html file that you will be editing. filename is what we want the name of the new compiled file to be. In this example we are going to keep the the name index.html.

Lastly we need to add the HTMLWebpackPluginConfig variable we created as an item in the array of plugins in our webpack config file. Your file should now look like this:

var HtmlWebpackPlugin = require('html-webpack-plugin');
var HTMLWebpackPluginConfig = new HtmlWebpackPlugin({
  template: __dirname + '/app/index.html',
  filename: 'index.html'
});
module.exports = {
  entry: [
    './app/index.js'
  ],
  module: {
    loaders: [
      {
        test: /\.js$/, 
        include:  __dirname + '/app', 
        loader: 'babel?presets[]=es2015'
      }
    ]
  },
  output: {
    filename: 'index_bundle.js',
    path: __dirname + '/dist'
  },
  plugins: [HTMLWebpackPluginConfig]
};

Now that we’ve configured Webpack you’ll want to run it. The package.json has a section called scripts where we can put commands we want to run. Let’s add “start”: “webpack –watch”, under the scripts property. This finds Webpack in the node modules directory and runs it with the watch flag which automatically recompiles your files every time you make a change. Now your scripts property should look like this:

"scripts": {
  "start": "webpack --watch",
  "test": "echo \"Error: no test specified\" && exit 1"
},

Now open your terminal and run the command npm start.

Wooo hooo!! your code is now compiling. Let’s test this out by writing some ES6 JavaScript in our index.js file to see if Babel compiles it. I added the following but you may want to add something else.

const appDiv = document.getElementById('app');
const name = 'John';
appDiv.innerHTML = `Hello ${name}, welcome to webpack starter tutorial!`;

Save and open the compiled dist/index.html file in your browser and you should see some text. Let’s take a look at the bottom of your dist/index_bundle.js file, you should see the browser compatible JavaScript that you wrote.

And there you have it, a very basic project set up using Webpack. 🙂

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s