ellm
2/28/2017 - 2:21 PM

Webpack Notes and Snippets

Webpack Notes and Snippets

Webpack 3.0

Code spliting in webpack to help decrease loaded dependencies on load.

  • UI that gets displayed as a callback from an event can benefit.
  • We can async. load a ES6 import() and code after it is returned using a promise.
// At top of file, assign an `import()` that is returned from a function.
const getBloodhound = () => import('bloodhound-js');

// Add an event that will trigger loading the module.
this.searchTrigger.addEventListener('click', () => {

    // Call the reference to the `import()` and return a promise.
    getBloodhound().then((Bloodhound) => {
        // Do stuff here after the module is loaded and ready.
        // `Bloodhound` is an example of a named export we can access from the module.
    });
});

Webpack Learning

Webpack 2.0

Basic Setup just using package.json

This basic set up in package.json will compile a single JS file.

  • To create a package.json file run npm init.
  • install Webpack npm install webpack --save-dev
{
    "name": "webpack-starter",
    "version": "1.0.0",
    "description": "",
    "main": "index.js",
    "scripts": {
        "build": "webpack src/main.js dist/bundle.js",
        "watch": "webpack src/main.js dist/bundle.js --watch",
    },
    "devDependencies": {
        "webpack": "^2.2.1"
    }
}

Setup using webpack.config.json

  • When running webpack, it's default location is in the root of the project.
  • Specifying a different location is done by using --config flag.
  • path is used to create an absolute path which is usually required.
var webpack = require('webpack');
var path = require('path');

module.exports = {
    entry: './src/main.js',
    output: {
        path: path.resolve(__dirname, './dist'),
        filename: 'bundle.js'
    }
}
  • package.json would be updated to the following:
{
    'scripts': {
        'build': 'webpack',
    },
}

Minification and Environments

  • update package.json to flag production and dev
{
    'scripts': {
        'build': 'webpack',
        'production': 'NODE_ENV=production webpack',
        'watch': 'npm run build -- --watch'
    },
}
  • add variable to webpack.config.json to test when the production flag is set.
var inProduction = (process.env.NODE_ENV === 'production')

Modules

  • allows you to keep pieces of code in other files and import them.
//== ECMAScript 2015 Syntax
// This function in `yap.js` is being exported
export default function (yap) {
    alert(yap);
}

// It can be used in `main.js` using an import statement
import growl from './yap';
growl('Alert');
//== CommonJS Syntax (deprecated)
// This function in `yap.js` is being exported
module.exports = function (yap) {
    alert(yap);
}

// It can be used in `main.js` using an import statement
var growl = require('./yap');
growl('Alert');

Loaders

  • Loaders deal with requiring Sass, compiling with Babel and alike.
  • Example, css-loader installed from npm can be configured in webpack.config.json to load a CSS file. style-loader installed from npm can then inject the <style /> into the <head> of the document
// entry points, etc ...

module: {
    rules: [
        {
            css: /\.css$/,
            // reads right to left
            use: ['style-loader', 'css-loader'],
        }
    ]
}
  • Example Babel loader, also requires additional configuration using a .babelrc file.
// entry points, etc ...

module: {
    rules: [
        {
            test: /\.js$/,
            exclude: /node_modules/,
            loader: 'babel-loader',
            query: {
            presets: ['es2015'],
            },
        },
    ]
}
  • Example, adding sass loader
  • also need to run npm install sass-loader node-sass --save-dev
  • sass-loader handles Webpack process; node-sass handles the compiling
// entry points, etc ...

module: {
    rules: [
        {
            test: /\.scss$/,
            // reads right to left
            use: ['style-loader', 'css-loader', 'sass-loader'],
        },
    ]
}
  • Example, referencing relative image paths.
  • Note, existing absolute paths can be solved w/o loader background: url('/img/test.jpg')
  • use file-loader npm install file-loader --save-dev
// entry points, etc ...

module: {
    rules: [
        {
            test: /\.(png|jpg|gif|svg|eot|ttf|woff|woff2)$/,
            loader: 'file-loader',
            options: 'images/[name].[hash].[ext]',
        },
    ]
}

Plugins

  • plugins extend webpack functionality.
  • Example, minify JS on build for production
if (process.env.NODE_ENV === 'production') {
    module.exports.plugins.push (
        new webpack.optimize.UglifyJsPlugin();
    );
}
  • script can be added to package.json like so:
    //...
    develop: "webpack",
    production: "NODE_ENV=production webpack"
    //...
  • Example, compile SCSS styles to an external file.
  • Use extract-text-webpack-plugin
  • Run npm install extract-text-webpack-plugin
const ExtractTextPlugin = require('extract-text-webpack-plugin');
// ...
module: {
    rules: [
      {
        test: /\.scss$/,
        use: ExtractTextPlugin.extract({
          // reads right to left
          use: ['css-loader', 'sass-loader'],
          fallback: 'style-loader',
        }),
      },
    ],
  },
  plugins: [
    new ExtractTextPlugin('[name].css'),
  ],

Hashing generated files

  • hashing generated files allow for long term caching
  • Webpack has hashing built in
  • Here is some code:
module.exports = {
    entry: {
        app: './src/main.js'
    },

    output: {
        path: path.resolve(__dirname, './dist'),
        // filename: '[name].js',
        // filename: '[name].[hash].js', [hash] adds current hash for build.
        // filename: '[name].[chunkhash].js', [chunkhash] hash for single file.
    }
}
  • [hash] works well if only one file is being cached
  • [chunkhash] is better for multiple file b/c each file gets it's own hash when it has been changed. This allows files that have not changed to keep it's previous hash remain cached.
  • to deal with files being added to the dist/ directory on each run, a plugin can be used to remove and recreate the dist folder on each build. An example plugin to use is called clean-webpack-plugin