Dev Notes

Software Development Resources by David Egan.

Webpack Configuration for JavaScript, CSS and Babel


Front End, JavaScript, Webpack
David Egan

Notes on configuring and using Webpack 2.x for JavaScript and CSS. This article includes a description of the use of Babel, so that next generation JavaScript can be used whilst maintaining browser compatibility.

These are personal notes that I’m making these as I learn Webpack. I favour Yarn over NPM, and the notes reflect this. You could always use NPM to manage dependencies.

Why Webpack?

Webpack is a tool that bundles modules (files) for your application. It can use loaders to transform non JS resources (like CSS) into JavaScript. Webpack has a rich plugin system. Webpack facilitates code-splitting, which aids in project organisation. In short, it is a very versatile build tool for all your front-end assets.

There are four core concepts that underpin webpack:

  1. Entry: Once an entry point is defined, webpack can work out dependencies and what to bundle.
  2. Output: Define the name and location of the bundle to be emitted.
  3. Loaders: In webpack, files are treated as modules - but webpack only understands JavaScript. Loaders transform resource files so that webpack can use them.
  4. Plugins: Extensible functionality by means of a powerful & customizable plugin system.

Install Webpack in Project

This command installs webpack as a project dev dependency.

cd /path/my-project
# If necessary, initialise a package
yarn init

# Install Webpack
yarn add webpack --dev

You should now see webpack listed in the devDependencies section of your package.json.

Run From CLI

To see Webpack in basic operation, create a file src/main.js in your project root. Run:

webpack src/main.js dist/bundle.js

Webpack will compile src/main.js down to dist/bundle.js, which then can be referenced in your HTML.

Define Script in package.json

For convenience, you could define a webpack command in the scripts section of package.json:

{
  "scripts": {
    "build": "webpack src/main.js dist/bundle.js"
  }
}

Running yarn build will now trigger the webpack task.

Reference Extra Files

In Node.js, there are two module systems that you can choose to import/export functionality between files:

  1. Import modules using require and export using module.exports
  2. Import using ES6 import and export using ES6 export

If you add additional JavaScript files, you can reference them in the entry-point JS file like this (CommonJS):

// src/main.js
alert(require("./additional.js"));

// src/additional.js
module.exports = "This is additional.js"

Or like this (ES6):

// src/main.js
import extra from './additional.js';
alert(extra);

// src/additional.js
export default "This is additional.js"

Loaders

To add CSS to the application, webpack needs to load the stylesheet in the entry JavaScript file. Because webpack can only handle JavaScript, a “Loader” is needed to process CSS. In this case, the required loader is css-loader.

To apply the stylesheet, processing the CSS isn’t enough - the resultant style rules need to be injected inline. This is achieved with the style-loader Loader.

To install both loaders in the project using Yarn:

yarn add css-loader style-loader --dev

Using Loaders

You can call loaders “inline” when requiring modules in the entry point JavaScript file:

require("!style-loader!css-loader!./main.css");

This shows the syntax for applying loaders within the require statement. As we’ll see, it’s easier to define loaders in a config file.

Be careful that you’re not looking at the docs for webpack 1.x: the old syntax does not require the -loader suffix.

Note that the loaders are applied in a right-to-left order - and the order is important. In this case, the processed CSS must be piped to the style loader.

Apparently you can use loaders through the webpack CLI - but I wasn’t able to get this working on Ubuntu 16.04.

Webpack Config

Webpack configuration can be defined in a configuration file. This drastically simplifies the entry-point JavaScript and makes code more concise and maintainable.

The webpack config file is a JS file that exports an object. The object is processed by webpack based on the defined properties. The config file is a standard Node.js CommonJS module.

The module.rulesproperty of webpack.config.js allows you to specify loaders for particular file types:

// webpack.config.js
// Configure CSS processing & injection
var webpack = require('webpack');
var path = require('path');

module.exports = {
    entry: './src/main.js',
    output: {
        // Webpack prefers an absolute path:
        path: path.resolve(__dirname, './dist'),
        filename: 'bundle.js'
    },
    module: {
        rules: [
            {
                // Uses regex to test for a file type - in this case, ends with `.css`
                test: /\.css$/,
                // Apply these loaders if test returns true
                use: ['style-loader', 'css-loader']
            }
        ]
    }
}

Note that the order in which loaders is applied is important - the right-most loader is applied first.

Write ES2015/ES6 - For All Browsers

Use next gen JavaScript today - using Babel

First, pull in the Babel node module:

yarn add babel-loader babel-core --dev

You also need to configure Babel - you do this by means of a preset plugin and a .babelrc config. Install the ES2015 plugin:

yarn add babel-preset-es2015 --dev

…then create .babelrc in the project root, with the following content:

{
  "presets": ["es2015"]
}

Finally, amend the webpack.config.js - tell webpack to apply the configured Babel loader to all JavaScript files, excluding those in node_modules:

module: {
        rules: [
            {
                test: /\.css$/,
                use: ['style-loader', 'css-loader']
            },
            {
                test: /\.js$/,
                exclude: /node_modules/,
                loader: 'babel-loader'
            }
        ]
    }

References


comments powered by Disqus