Webpack

A module bundler

@TehranJS

The old way









            <script src="js/jquery.js"></script>
            <script src="js/react.js"></script>
            <script src="js/react-router.js"></script>
            <script src="js/app.js"></script>

Script includes

  • Have to know "correct" order (inter-dependencies)
  • Have to make sure correct dependencies are added
    (on each page)
  • Inefficient fetching (HTTP 1.1 concurrency limit)
  • No package management, meaning you have to copy/paste in prebuilt vendor code
  • No way of using new JavaScript features that requires transpiling (ES6-7)

Concatenation








            grunt.initConfig({
              concat: {
                files: {
                  home: [
                    'js/jquery.js',
                    'js/jquery-ui.js',
                    'js/react.js',
                    'js/react-router.js',
                    'js/home.js',
                    ]
                }
              }
            });
  • Still means you have to know the ordering of dependencies
     
  • What happens when you add a new page?
grunt.initConfig({
  concat: {
    files: {
      home: [
        'js/jquery.js',
        'js/jquery-ui.js',
        'js/react.js',
        'js/react-router.js',
        'js/app.js',
      ],
      dashboard: [
        'js/jquery.js',
        'js/some-other-jquery-plugin.js',
        'js/react.js',
        'js/react-router.js',
        'js/dashboard.js',
      ]
    }
  }
});
  • Re-downloading the vendor code for every page (no code-sharing)

  • Can be solved (somewhat) by separating the common from the page specific

grunt.initConfig({
    concat: {
        files: {
            common: [
                'js/jquery.js',
                'js/jquery-ui.js',
                'js/some-jquery-plugin.js',
                'js/some-other-jquery-plugin.js',
                'js/react.js',
                'js/react-router.js'
            ],
            home: [
                'js/home.js',
            ],
            dashboard: [
                'js/dashboard.js',
            ]
        }
    }
});
  • But this means you have to know and manually separate the common from the page specific
     
  • This is easy when you only share vendor code, but hard when you share app code
  • Globals everywhere (namespace hell)
  • Difficult to reason about the definitions and use
  • Implicit coupling
  • Changing code order can cause unexpected issues
  • Hard to write tests without loading your entire app

Main issues

The solution

Modules

+

bundling

Tools for bundling assets

The State of Front-End Tooling – 2015

Webpack

  • Can use dependency management (npm)
  • Get to leverage npm (don't re-invent the wheel)
  • Every module declares their own dependencies, so the bundler can build the dependency graph
  • No more globals (unless you specifically declare them)
  • Explicit coupling
  • Everything always loads in the correct order
  • Enables you to test each module in isolation
  • Code splitting and on demand loading
  • Low initial load time
  • Every static asset as a module
  • 3rd-party libraries as modules
  • Every part customizable
  • Suited for big projects

Goals

Configuration

  • Command Line Interface (Passed when executed)
     
  • Using webpack API (for NodeJS) (Great to integrate with grunt, gulp or your own build scripts)
     
  • Configuration file (Not a JSON, it is a JavaScript file, really a module)
module.exports = {
  entry: './about',
  output: {
    filename: 'build.js'
  }
};

Options

  • context: Base directory for resolving the entry option.  Note it is absolute path
  • entry: The entry point of your bundle (the initial file where your application starts). Can be a string, an array or an object (for multiple entries).

  • output: Determines the out folder, file names, etc.
  • module: Options affecting normal modules, like which one must be automatically loaded.
  • resolve: Determines how modules are loaded.
  • target: Compiles depending the target environment (browser, node, webworker, etc).
  • devtool: Enhance debugging (generates map files).
  • plugins: Additional plugins added to the compiler.

Three main conepts

Entry points: The first JS code executed when a page is loaded. Dependencies are analyzed from this first module.

Loaders: Transformations on a resource file. Each module is loaded through a loader

Plugins: Injects themselves into the build process to make all sort of crazy things.

Basic example

"use strict";

var path = require("path");
var Webpack = require("webpack");

// Our configuration
module.exports = {
	// Define the entry point
	entry: path.resolve(__dirname, "js", "app.js"),

	// Output configuration
	output: {
		path: path.resolve(__dirname, "assets"),
		filename: "bundle.js"
	},

	module: {
		loaders: [
			// Inform about CSS loaders so that it can be bundled too
			{ test: /\.css$/, loader: "style-loader!css-loader" }
		]
	},

	// Generate source map files
	devtool: "source-map"
};
body {
    background: #eeeeee;
}
style.css
content.js
module.exports = "TehranJS";
require("!style!css!../css/style.css");
var content = require("./content.js");

document.write(content);
app.js
> webpack app.js bundle.js

bundle.js










    <html>
        <head>
            <meta charset="utf-8">
        </head>
        <body>
            <script type="text/javascript" src="bundle.js"></script>
        </body>
    </html>

Note, the CSS is included in the bundle but it is not applied until the bundle is loaded :(

...there is much more !!!

Loaders

  • Compiles SASS, LESS, stylus, etc.
  • Minimizes JS or CSS.
  • Generate map files (useful for production debugging).
  • Inline images and webfonts within CSS files as base64 (reducing number of server requests).
  • Offers a different way to create modular CSS code
  • Allow to work with different scripting languages (you can require a CoffeScript module within a JS)

Dependencies

  • By default works fine with npm modules.
    • Install modules with NPM
    • Use it

 

Easy integration with bower.

Webpack has many more features !!!

Explore by yourself and learn

Thank You

@TehranJS

Made with Slides.com