Basics Of Webpack Module Bundler - Config, Dev Server, Loaders

Webpack is an amazing tool used by lot of developers. After starting to use webpack, it felt like it was not the regual way scripts would be serverd or how fast the development process was with the various technologies(React, JSX, Coffee, Babel etc) that was being used and how webpack made it really easy to use all those technologies. This is just a simple introduction to the functionalities and features webpack has to offer.

Why webpack ?

Larger the application, more modules are created, leading to more http requests from client. With webpack we can bundle them into single file. This can be done not only to JavaScript but also to CSS and others assets.

Watch this presentation by pete hunt on How Works using webpack.

What does webpack do ?

Using webpack we can,

  • Bundle all the JavaScript and CSS into one file, reducing the number of http requests from clients.
  • Translate JSX, Coffee Script, es6 and others to JavaScript using Loaders.
  • Minify and optimised scripts using Plugins.

webpack uses the module system provided by Node.js to find dependencies between each modules and bundles them into a single file based on those dependencies. If a file exists without any file depending on it, then it must be specified separately to be bundled.


Installing webpack

To install webpack, use the node package manager.

npm  install webpack -g

The -g is to install globally rather than for the project, but it is advised to install it per project as a devDependency.

Getting started - Webpack Command Line

Using the webpack command line commands, we can get started with webpack quickly with the basic functionalities up and running. Let’s create a few module files representing a web application and see what webpack can do.

Modules - login-module.js, signup-module.js and app.js

The directory structure,

Webpack - Directory Structure


console.log('Login module is ready.');


console.log('Signup module is ready, and it will build after i save.');


 * This is the entry point for webpack


console.log('App has been loaded.');

First to determine our entry script, a script that can be processed and our entire modules dependencies are included. app.js requires/includes both the login-module.js and signup-module.js files. So our entry point for building the source would be app.js. We could also have multiple entry points, will look into that later.

Then to determine the location from which the output file(bundled file) with all the modules combined will be served from. We’ll create a dist folder(short for distribution) and we’ll name our output file bundle.js, makes sense right, we are bundling all the modules. You can name it whatever you want it to be, but specify it correctly while linking it to the HTML page to be included in.

Running webpack

webpack ./app.js ./dist/bundle.js —progress —colors —watch

In the above command,

  • ./app.js - The first argument informs webpack what file is going to be the entry point for building the app.
  • ./dist/bundle.js - The second argument tell’s it where it needs to store the bundled output file.

Apart from the arguments we passed, there are few other options too that we can pass to webpack to modify it’s behaviour.

  • —progress - Will tell webpack to show the build progress status.
  • —colors - You know what this means.
  • —watch - Now this here is really useful stuff, this options tells webpack to keep watching the source module files for changes. When there is a change made, it recompiles and generate the output bundle file. You still need to reload the browser to relink the updated bundle file, but we’ll get to automating that later.

Webpack Commandline Execution

Now if you look at the output bundle file, there will be some extra code, that you did not write. It’s what webpack uses to map the modules and load the code that is needed.

So far we have just used the webpack command line, but it’s not good enough to specify the options and configs in the command line every time you need to build using webpack.

Let’s just move all the arguments and options needed for webpack in a separate file, so it’s easier to maintain and there are lot’s more options available in webpack when using a config file.

Note: Webpack is very strict about the configurations, if the configs are not right, it just won’t work.

Webpack Config File

The webpack config file is basically a JavaScript file with all options as a Object key values specifying the options for webpack and added to the Node module exports. For now let’s add the command line options in the config file.

The config file looks as below,

module.exports = {
  // The entry point for the application
  entry: ["./app.js"],
  output: {
    // Where to put the output source.
    path: "./dist/",
    // Name of the output source file.
    filename: "bundle.js"
  // Tells webpack to keep watching for changes and recompile if changes are found.
  watch: true,

The entry script is given in the entry key, the value can be an array, since webpack can have multiple entry scripts. This is identical to the first argument in the command line.

The output key is an object that specifies two options for now. filename which is the output file name(eg. bundle.js) and path is where the output file is to be stored. This is identical to the second argument in the command line.

Finally the watch option informs webpack to keep watching the files for changes and is identical to the command line —watch option.

Now just run the webpack in the command line and you will see the output file in the dist directory.


Webpack Commandline with Watch

With the config file, there is a lot’s of options we can use to configure webpack to use it’s full capabilities.

Webpack Dev Server for Automation

webpack-dev-server is another one of the cool NPM package for webpack which is used to speed up the development process by automating the build and run process. It watches for changes in files just like the watch option we used, but webpack-dev-server refreshes the browser web page automatically, making it easier to view the changes into effect immediately instead of us refreshing the browser manually.

Note: webpack-dev-server is nothing but a node.js Express server, which uses webpack-dev-middleware and to serve and reload in realtime.

To use the webpack-dev-server, we need to install the package first.

npm install webpack-dev-server -g

Again we specify the -g flag to install it globally.

Once it is installed, in the root directory of the project, i.e where our webpack config file is, just run webpack-dev-sever command. You can also place the webpack config file in a separate directory and specify the config file using the —config [path/to/webpack.config.js] option. Here the config file is stored inside of the config directory.


To configure the webpack-dev-server to serve the files, you need to specify the base folder relative path from which webpack will serve the build using the publicPath key of the output object in the webpack config.

module.exports = {
  // The entry point for the application
  entry: ["./app.js"],
  output: {
    // Where to put the output source.
    path: "./dist/",
    // Name of the output source file.
    filename: "bundle.js",
    // Required for webpack-dev-server, provide the path from which
    // the file will be served to front end.
    publicPath: '/dist/'

Running webpack-dev-server

As you can see in the output above, webpack instead of the process being ended, it is watching for changes in files to recompile. It now shows bundle is now VALID

The webpack-dev-server does not actually write the output to the bundle.js file, instead it serves the file from memory. So you won’t actually see the output in the bundle.js. Since webpack-dev-server serves the files from memory, you need to specify this in the HTML file which needs the output bundle.

For example, if the file is served from dist directory


    <title>Webpack Basics - Command Line / Config file</title>
  <h3>Welcome to webpack</h3>
  <p><b>Open the console to view the modules messages.</b></p>
  <script type="text/javascript" src="dist/bundle.js"></script>


webpack-dev-server has two modes of behaviour,

  • Iframe Mode - Runs you app inside a iframe and a status bar showing the build status at the top
  • Inline Mode - You app is auto reloaded when changes are made, no status bar is shown.

Iframe Mode

Once you have configures webpack and started the webpack dev server, it builds the source files is ready to server. Open the browser and visit,


When the page is loaded, you see a App status bar at the top of the browser. Basically your app is embedded in an iframe and is auto refreshed when changes are made.

webpack-dev-server iframe mode

webpack-dev-server app status bar

Once the command is run, webpack builds and bundles the source files and serves the output file.

Inline Mode

In the browser there is a App status bar shown which specifies the status of the build and refreshes the browser every time a change is made. If you don’t want to get that in your way of development, you can use the —inline option in webpack. Once specified, the dev-server will do a auto refresh of the application and you won’t see the App status bar this time, but you get the autorefresh feature out of the box.

webpack-dev-server —config config/webpack.config.js —inline

webpack-dev-server inline mode

Once the —inline is specified you don’t see the status bar anymore and you are good to go.

read more on webpack-dev-server.

Loader and Pre Loaders

Loaders are one of the important features of webpack. Apart from just combining modules and producing an output, with loaders you can process and transform js source code. They are just functions that takes in as input the source file and return the processed/transformed new source.

For example you can convert JSX to JavaScript, CoffeeScript to JS, Process LESS and SASS into CSS etc using loaders. You can find the list of loaders here

PreLoaders and Loaders

Here are some of the loaders features described in the official webpack documentation,

  • Loaders can be chained. They are applied in a pipeline to the resource. The final loader is expected to return JavaScript; each other loader can return source in arbitrary format, which is passed to the next loader.
  • Loaders run in Node.js and can do everything that’s possible there.
  • Loaders accept query parameters. This can be used to pass configuration to the loader.
  • Loaders can be bound to extensions / RegExps in the configuration.
  • Loaders can access the configuration.
  • Plugins can give loaders more features.


Loaders have a general naming convention of XXX-loader, where XXX can be the loader name. For example babel-loader. It can be referenced either with just the loader name(babel) or using the full name(babel-loader).

Loaders are just another npm package. They can be used by configuring in the webpack config file. There are two ways loaders can be used, as a

  • PreLoader - Runs before the loaders works on the source files. Things like listing and other checks can be done on the source code.
  • Loaders - Runs after all the PreLoaders have worked on the source file.


First install the loader package that we are going to be using by using the npm command.

npm install jshint jshint-loader —save-dev

Here the jshint and its loader jshint-loader is installed.

To configure webpack to run this preLoader(there can be many preLoaders) modify the webpack config file as shown below.

  module: {
    preLoaders: [
        test: /\.js$/, // will process all the js files
        exclude: /node_modules/,
        loader: "jshint-loader"

Add a preLoaders array of loader objects in the module object of the webpack config. Each loader object has some configs options that tells which files the loader should process and which loader to parse it with.

  • test - Regular Expression to match the file’s that should to be processed with this loader.

  • exclude - Regular Expression to exclude the folders and files that should not be processed with the loader.

  • loader - The loader which must be used must be specified in this options. e.g. jshint-loader

In addition to the above configurations, you can also pass a query object, which contains options specific to the loader, that will be sent as a config to the loader to modify it’s behaviour.

Once the config has been added, run the webpack command. Once you run it, you will see the following output.

PreLoader Output

In the output above, jshint is reporting that there is a semicolon missing in the login-module.js and in the signup-module.js the document.write can be a form of eval and that there is a semicolon missing there too. We can go ahead and fix those.

Once fixed, those warning do not appear.


Loaders and preLoaders are the same. Only difference is that preLoaders run before the loaders are executed. Now let’s install babel-loader which can process and transform React JSX and ES6 code to JavaScript.

npm install react react-dom babel-preset-react babel-loader babel-core babel-preset-es2015 —save-dev

Note: In the above installation babel-preset-es2015 and babel-preset-react are loader specific packages to compile and process es6 and JSX.

Let’s include a sample react application from the react website with JSX syntax. Let's name it timer.jsx and put it in the root folder.


var React = require('react');
var ReactDOM = require('react-dom');

// Sampel Timer app from -
var Timer = React.createClass({
  getInitialState: function() {
    return {secondsElapsed: 0};
  tick: function() {
    this.setState({secondsElapsed: this.state.secondsElapsed + 1});
  componentDidMount: function() {
    this.interval = setInterval(this.tick, 1000);
  componentWillUnmount: function() {
  render: function() {
    return (
Seconds Elapsed: {this.state.secondsElapsed}
); } }); ReactDOM.render(, document.getElementById('timer'));


  module: {
    preLoaders: [
        test: /\.js$/, // will process all the js files
        exclude: /node_modules/,
        loader: "jshint-loader"

    loaders: [
        test: /\.jsx$/, // Will process all the jsx files
        exclude: /node_modules/,
        loader: "babel",
        query: {
          presets: ['react']

Run the webpack command now.

Timer React Output

The above output shows that React JSX has been successfully compiled and the output rendered properly.

Note: You can also compile and process es6 code into javascript by using the preset as es2015 in the query object of bable-loader.

Source Maps

Source map is built into webpack. It allows us to view the source of the file that we have written directly instead of the code webpack has bundled all together. This helps us identify the code for debugging purpose and make changes easily.

To enable source map, use the -d flag while running webpack or webpack-dev-server.

Let's add a debugger statement inside the render method and see what happens without sourmap enabled.

webpack-dev-server --config config/webpack.config.js --inline -d

Before Source Map

Once the source map is enabled, the debugger will point to the exact source script where the debugger statement is

After Source Map

Once you understand the basic of webpack, you can do lot more things using plugin and other set of amazing features webpack offers.

To learn more head to the webpack documentation.