Webpack

These are the notes from my Kochi Twitter developer meet talk.

  • import files
  // app.js
  import bar from './bar';
  bar();


  // bar.js
  export default function bar() {
    return "hello from bar.js";
  }

Getting Started

  • npm init

  • npm install --save-dev webpack

  • create src/index.js

  • create public/index.html

  • npm install --save lodash

  • import _ from 'lodash';

  • remove _ from html

  • add bundle.js

  • ./node_modules/.bin/webpack src/index.js dist/bundle.js

  • --display-modules to show all modules

Modules

  • import and export statements have been standardized in es2015, webpack support them out of the box.
  • webpack won't support other es2015 features.

Configuration

  • create webpack.config.js
  • const path = require('path');
  module.exports = {
    entry: './src/index.js',
    output: {
      filename: 'bundle.js',
      path: path.resolve(__dirname, 'dist')
    }
  };
  • ./node_modules/.bind/webpack
  • add webpack to package.json scripts

Loading CSS

  • npm install --save-dev style-loader css-loader
   module: {
     rules: [
       {
         test: /\.css$/,
         use: [
           'style-loader',
           'css-loader'
         ]
       }
     ]
   }
  • style loader
  • css loader - interprets import css from 'file.css';

Loading Images

  • npm install --save-dev file-loader
      {
        test: /\.(png|svg|jpg|gif)$/,
        use: [
          'file-loader'
        ]
      }
  • import Logo from './logo.png';
  • a = new Image(); a.src=Logo;
  • background: url('./logo.png');
  • fonts will also work with file loader.

Output Management

  • multiple output files
  entry: {
    app: './src/index.js',
    home: './src/home.js'
  },
  output: {
    filename: '[name].bundle.js',
    path: path.resolve(__dirname, 'dist')
  },
  • HtmlWebpackPlugin
  • npm install --save-dev html-webpack-plugin
  const HtmlWebpackPlugin = require('html-webpack-plugin');
  plugins: [
    new HtmlWebpackPlugin({
      title: 'Output Management'
    })
  ],

Development

  • error debug - devtool: "inline-source-map"
  • webpack --watch

live reload

  • npm install --save-dev webpack-dev-server
     devServer: {
       contentBase: './dist'
     },

Deadcode elimination / Tree Shaking

  • npm i --save-dev uglifyjs-webpack-plugin
  const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
  plugins: [
    new UglifyJSPlugin();
  ]

Production

  • npm install --save-dev webpack-merge

  • webpack.common.js, webpack.dev.js, webpack.prod.js

  // webpack.dev.js
  const merge = require('webpack-merge');
  const common = require('./webpack.common.js');
 
  module.exports = merge(common, {
    devtool: 'inline-source-map',
    devServer: {
      contentBase: './dist'
    }
  });
  // webpack.prod.js
  const merge = require('webpack-merge');
  const UglifyJSPlugin = require('uglifyjs-webpack-plugin');
  const common = require('./webpack.common.js');
 
  module.exports = merge(common, {
    plugins: [
      new UglifyJSPlugin()
    ]
  });
  • npm scripts
  • start: webpack-dev-server --open --config webpack.dev.js
  • build: webpack --config webpack.prod.js

Code splitting

  • CommonsChunkPlugin
  const webpack = require('webpack');
  new webpack.optimize.CommonsChunkPlugin({
    name: 'common'
  })
  • moving out third-party libraries
  plugins: [
     new webpack.optimize.CommonsChunkPlugin({
       name: 'vendor'
     }),
  ]
  entry: {
    app: './src/index.js',
    vendor: [
      'lodash'
    ]
  },
  • ExtractTextWebpackPlugin
  • npm install --save-dev extract-text-webpack-plugin
  const ExtractTextPlugin = require("extract-text-webpack-plugin");

  plugins: [
    new ExtractTextPlugin("styles.css"),
  ]

  rules: [
     {
       test: /\.css$/,
       use: ExtractTextPlugin.extract({
         fallback: "style-loader",
         use: "css-loader"
       })
     },

Caching

  • [chunkhash] in filename

Babel

  • npm install --save-dev babel-loader babel-core babel-preset-env
  module: {
    rules: [
      {
        test: /\.js$/,
        exclude: /(node_modules|bower_components)/,
        use: {
          loader: 'babel-loader',
          options: {
            presets: ['env']
          }
        }
      }
    ]
  }