Webpack 3 - Simple Configuration Workflow (with RxJS and Babel)

MD
R
Markdown

I've brought up a simple but epic flow using Webpack 3. Please feel free to use it as a basis for your fresh project.

Webpack 3.0 Simple Configuration

## 1. Create a plain project with a package.json npm ini -y

2. Install Webpack and WebPackDevServer

npm install --save-dev webpack@latest webpack-dev-server@latest

3. Bundle mappings overview

Source Files: /src/**/*.js Entry point: /src/app.js Output: dist/app.bundle.js

4. The webpack.config

The simplest config file looks like this:

const webpack = require('webpack');
const config = {
    context: __dirname + '/src',
    entry: {
        app: './entry.js',
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].bundle.js',
    },
    devServer: {
        open: true, // to open the local server in browser
        contentBase: __dirname + '/src',
    }
};
module.exports = config;

5. Add some NPM scripts (dev (with watch), production(uglify, minify))

File: package.json

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --progress --open --colors --watch --hot",
    "production": "NODE_ENV=production webpack -p --progress --colors"
  },

6. Create an index.html & some js files in /src/

File: src/index.html

<!DOCTYPE html>
<html>
<head>
    <title>Webpack 3 Basic App</title>
</head>
<body>
    <h1> Hello World </h1>
    <script src="/assets/app.bundle.js"></script>
</body>
</html>

File: src/entry.js

const _ = require('lodash');
import { Subject } from 'rxjs/Rx';

class EventEmitter {
    constructor(){
        this.subject = new Subject({});
        console.info('event emitter shared observable attached')
    }
}
const singleton = new EventEmitter();
export default singleton;

7. Webpack Loaders

Think of the loaders as middleware pipes that you can add to your bundling process (after the automatic bundling from webpack)

7.1 ES6 Transpilling via Babel (core + es6 presets) *you won't need it for modern browsers for most of the ES6 features as they are now part of the latest versions of the most common browsers

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

Add a new entry on the webpack.config.js literal object

module: {
    rules: [
        {
            test: /\.js$/, //Check for all js files
            loader: 'babel-loader',
            query: {
                presets: ["babel-preset-es2015"].map(require.resolve)
            }
        }
    ]
}

7.2 SASS and CSS Loaders

npm install --save-dev css-loader style-loader sass-loader node-sass New entry to webpack.config.js literal object

module: {
  rules: [
        {
            test: /\.(sass|scss)$/,
            use: [
            'style-loader',
            'css-loader',
            'sass-loader',
            ]
        }
    ]
}

8. Set sourcemaps (development only)

Let's add some keys to the webpack.config.js literal object

devtool: "eval-source-map"

And just before exporting the config.

// Check if build is running in production mode, then change the sourcemap type
if (process.env.NODE_ENV === "production") {
  config.devtool = "";
  // More Pipes and Stuff (separate build outputs, versioning, etc)
}

9. Done!

npm run dev npm run production

The files

The JS entry file /src/entry.js.

'use strict';
import { Subject } from 'rxjs/Rx';
import Styles from './styles/index.scss';

class EventEmitter {
    constructor(){
        this.subject = new Subject({});
        console.info('event emitter shared observable attached')
    }
}
const singleton = new EventEmitter();
export default singleton;

The Webpack.config.js

const webpack = require('webpack');
const config = {
    context: __dirname + '/src',
    entry: {
        app: './entry.js',
    },
    output: {
        path: __dirname + '/dist',
        filename: '[name].bundle.js',
        publicPath: "/dist",
    },
    devServer: {
        contentBase: __dirname + '/src',
    },
    module: {
        rules: [
            {
                test: /\.js$/,
                loader: 'babel-loader',
                query: {
                    presets: ["babel-preset-es2015"].map(require.resolve)
                }
            },
            {
                test: /\.(sass|scss)$/,
                use: [
                    'style-loader',
                    'css-loader',
                    'sass-loader'
                ]
            },
            {
                test: /\.json$/,
                loader: "json-loader"
            }
        ]
    },
    devtool: "eval-source-map",
    plugins: []
};

if (process.env.NODE_ENV === "production") {
  // More Production Stuff (separate build outputs, versioning, etc)
}
module.exports = config;

The HTML File /src/index.html

<!DOCTYPE html>
<html>
<head>
    <title>Webpack 3 Basic App</title>
</head>
<body>
    <h1> Hello World </h1>
    <script src="/assets/app.bundle.js"></script>
</body>
</html>

The package.json

{
  "name": "webpack-basic",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "dev": "webpack-dev-server --progress --open --colors --watch --hot",
    "production": "NODE_ENV=production webpack -p --progress --colors"
  },
  "keywords": [],
  "author": "",
  "license": "ISC",
  "devDependencies": {
    "babel-core": "^6.25.0",
    "babel-loader": "^7.1.0",
    "babel-preset-es2015": "^6.24.1",
    "css-loader": "^0.28.4",
    "lodash": "^4.17.4",
    "node-sass": "^4.5.3",
    "rxjs": "^5.4.1",
    "sass-loader": "^6.0.6",
    "style-loader": "^0.18.2",
    "webpack": "^3.0.0",
    "webpack-dev-server": "^2.5.0"
  }
}

Created on 6/26/2017