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.jsbundle.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
webpack | a module Bundler
By Jalal Azimi
webpack | a module Bundler
@tehranjs
- 444