• Stars
    star
    10,126
  • Rank 3,320 (Top 0.07 %)
  • Language
    JavaScript
  • Created almost 10 years ago
  • Updated almost 7 years ago

Reviews

There are no reviews yet. Be the first to send feedback to the community and the maintainers!

Repository Details

webpack-howto

Goal of this guide

This is a cookbook of how to get things done with webpack. This includes most things we use at Instagram and nothing we don't use.

My advice: start with this as your webpack docs, then look at the official docs for clarification.

Prerequisites

  • You know browserify, RequireJS or something similar
  • You see the value in:
    • Bundle splitting
    • Async loading
    • Packaging static assets like images and CSS

1. Why webpack?

  • It's like browserify but can split your app into multiple files. If you have multiple pages in a single-page app, the user only downloads code for just that page. If they go to another page, they don't redownload common code.

  • It often replaces grunt or gulp because it can build and bundle CSS, preprocessed CSS, compile-to-JS languages and images, among other things.

It supports AMD and CommonJS, among other module systems (Angular, ES6). If you don't know what to use, use CommonJS.

2. Webpack for Browserify people

These are equivalent:

browserify main.js > bundle.js
webpack main.js bundle.js

However, webpack is more powerful than Browserify, so you generally want to make a webpack.config.js to keep things organized:

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  }
};

This is just JS, so feel free to put Real Code in there.

3. How to invoke webpack

Switch to the directory containing webpack.config.js and run:

  • webpack for building once for development
  • webpack -p for building once for production (minification)
  • webpack --watch for continuous incremental build in development (fast!)
  • webpack -d to include source maps

4. Compile-to-JS languages

webpack's equivalent of browserify transforms and RequireJS plugins is a loader. Here's how you can teach webpack to load CoffeeScript and Facebook JSX+ES6 support (you must npm install babel-loader coffee-loader):

See also the babel-loader installation instructions for additional dependencies (tl;dr run npm install babel-core babel-preset-es2015 babel-preset-react).

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  }
};

To enable requiring files without specifying the extension, you must add a resolve.extensions parameter specifying which files webpack searches for:

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  module: {
    loaders: [
      { test: /\.coffee$/, loader: 'coffee-loader' },
      {
        test: /\.js$/,
        loader: 'babel-loader',
        query: {
          presets: ['es2015', 'react']
        }
      }
    ]
  },
  resolve: {
    // you can now require('file') instead of require('file.coffee')
    extensions: ['', '.js', '.json', '.coffee'] 
  }
};

5. Stylesheets and images

First update your code to require() your static assets (named as they would with node's require()):

require('./bootstrap.css');
require('./myapp.less');

var img = document.createElement('img');
img.src = require('./glyph.png');

When you require CSS (or less, etc), webpack inlines the CSS as a string inside the JS bundle and require() will insert a <style> tag into the page. When you require images, webpack inlines a URL to the image into the bundle and returns it from require().

But you need to teach webpack to do this (again, with loaders):

// webpack.config.js
module.exports = {
  entry: './main.js',
  output: {
    path: './build', // This is where images AND js will go
    publicPath: 'http://mycdn.com/', // This is used to generate URLs to e.g. images
    filename: 'bundle.js'
  },
  module: {
    loaders: [
      { test: /\.less$/, loader: 'style-loader!css-loader!less-loader' }, // use ! to chain loaders
      { test: /\.css$/, loader: 'style-loader!css-loader' },
      { test: /\.(png|jpg)$/, loader: 'url-loader?limit=8192' } // inline base64 URLs for <=8k images, direct URLs for the rest
    ]
  }
};

6. Feature flags

We have code we want to gate only to our dev environments (like logging) and our internal dogfooding servers (like unreleased features we're testing with employees). In your code, refer to magic globals:

if (__DEV__) {
  console.warn('Extra logging');
}
// ...
if (__PRERELEASE__) {
  showSecretFeature();
}

Then teach webpack those magic globals:

// webpack.config.js

// definePlugin takes raw strings and inserts them, so you can put strings of JS if you want.
var definePlugin = new webpack.DefinePlugin({
  __DEV__: JSON.stringify(JSON.parse(process.env.BUILD_DEV || 'true')),
  __PRERELEASE__: JSON.stringify(JSON.parse(process.env.BUILD_PRERELEASE || 'false'))
});

module.exports = {
  entry: './main.js',
  output: {
    filename: 'bundle.js'       
  },
  plugins: [definePlugin]
};

Then you can build with BUILD_DEV=1 BUILD_PRERELEASE=1 webpack from the console. Note that since webpack -p runs uglify dead-code elimination, anything wrapped in one of these blocks will be stripped out, so you won't leak secret features or strings.

7. Multiple entrypoints

Let's say you have a profile page and a feed page. You don't want to make the user download the code for the feed if they just want the profile. So make multiple bundles: create one "main module" (called an entrypoint) per page:

// webpack.config.js
module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // Template based on keys in entry above
  }
};

For profile, insert <script src="build/Profile.js"></script> into your page. Do a similar thing for feed.

8. Optimizing common code

Feed and Profile share a lot in common (like React and the common stylesheets and components). webpack can figure out what they have in common and make a shared bundle that can be cached between pages:

// webpack.config.js

var webpack = require('webpack');

var commonsPlugin =
  new webpack.optimize.CommonsChunkPlugin('common.js');

module.exports = {
  entry: {
    Profile: './profile.js',
    Feed: './feed.js'
  },
  output: {
    path: 'build',
    filename: '[name].js' // Template based on keys in entry above
  },
  plugins: [commonsPlugin]
};

Add <script src="build/common.js"></script> before the script tag you added in the previous step and enjoy the free caching.

9. Async loading

CommonJS is synchronous but webpack provides a way to asynchronously specify dependencies. This is useful for client-side routers, where you want the router on every page, but you don't want to have to download features until you actually need them.

Specify the split point where you want to load asynchronously. For example:

if (window.location.pathname === '/feed') {
  showLoadingState();
  require.ensure([], function() { // this syntax is weird but it works
    hideLoadingState();
    require('./feed').show(); // when this function is called, the module is guaranteed to be synchronously available.
  });
} else if (window.location.pathname === '/profile') {
  showLoadingState();
  require.ensure([], function() {
    hideLoadingState();
    require('./profile').show();
  });
}

webpack will do the rest and generate extra chunk files and load them for you.

webpack will assume that those files are in your root directory when you load then into a html script tag for example. You can use output.publicPath to configure that.

// webpack.config.js
output: {
    path: "/home/proj/public/assets", //path to where webpack will build your stuff
    publicPath: "/assets/" //path that will be considered when requiring your files
}

Additional resources

Take a look at a real world example on how a successful team is leveraging webpack: http://youtu.be/VkTCL6Nqm6Y This is Pete Hunt at OSCon talking about webpack at Instagram.com

FAQ

webpack doesn't seem modular

webpack is extremely modular. What makes webpack great is that it lets plugins inject themselves into more places in the build process when compared to alternatives like browserify and requirejs. Many things that may seem built into the core are just plugins that are loaded by default and can be overridden (i.e. the CommonJS require() parser).

More Repositories

1

react-howto

Your guide to the (sometimes overwhelming!) React ecosystem.
11,615
star
2

rwb

JavaScript
727
star
3

react-webpack-template

JavaScript
551
star
4

react-boilerplate

Boilerplate for creating a React npm package
JavaScript
545
star
5

react-touch

React photo viewer for mobile
JavaScript
446
star
6

ReactHack

React+Parse+Bootstrap Hackathon toolkit
JavaScript
249
star
7

react-server-rendering-example

Super-basic example of how server rendering works
JavaScript
221
star
8

webpack-require

JavaScript
198
star
9

react-one-hour-email

Build a very simple email client in an hour, step by step.
JavaScript
174
star
10

node-jsx

transparently require() jsx from within node
JavaScript
165
star
11

react-gss

JavaScript
155
star
12

langchain-github-bot

Python
144
star
13

react-raf-batching

A game-like batching strategy for React
JavaScript
134
star
14

loris

High-performance JavaScript UIs
JavaScript
133
star
15

react-tutorial

Code from the React tutorial
JavaScript
124
star
16

jsx-loader

JSX loader for webpack
JavaScript
108
star
17

famous-react

JavaScript
78
star
18

react-browserify-template

Quick template for building with Browserify + React
HTML
67
star
19

dagster-poor-mans-data-lake

Python
66
star
20

react-touch-lib

React component library for building inertial touch applications.
JavaScript
63
star
21

yologram

JavaScript
42
star
22

react-multiplayer

Multiplayer React with Firebase
JavaScript
40
star
23

morimodel

Models for Mori
JavaScript
38
star
24

react-xhr

JavaScript
37
star
25

react-tween

JavaScript
29
star
26

react-meteor-preso

JavaScript
26
star
27

react-classset

React.addons.classSet() packaged in npm
JavaScript
22
star
28

react-jqueryui

Wrap jQuery UI widgets in React components
JavaScript
22
star
29

django-reactify

Python
21
star
30

generator-react-library

Yeoman generator for React components
JavaScript
17
star
31

use-state-singleton

yet another redux alternative
TypeScript
15
star
32

dagster-github-stars-example

Python
15
star
33

rust-benchmark

JavaScript
14
star
34

js-css-loader

Define CSS in JS
JavaScript
13
star
35

commonjs-asset-spec

12
star
36

lockless

STM for Python
Python
11
star
37

ratelimiter

The easiest way to add rate limiting to your app
JavaScript
11
star
38

reactify-server-rendering

JavaScript
9
star
39

staticify

Browserify all of your static resources
JavaScript
9
star
40

jsxc

experimental jsx command-line tool
JavaScript
9
star
41

unrouter

JavaScript
8
star
42

zod-args

zod-args is the fastest way to throw together a simple CLI with TypeScript type checking.
JavaScript
8
star
43

sweetjs-loader

webpack loader for sweet.js
JavaScript
8
star
44

reacthack-core

JavaScript
8
star
45

dagster-script-to-assets

Python
6
star
46

sqlconfig

Python
4
star
47

oredev-workshop

JavaScript
4
star
48

rerequire

JavaScript
4
star
49

statics

static assets in npm
JavaScript
4
star
50

zod-json-rpc

TypeScript
4
star
51

generator-react-quickstart

Yeoman generator for React apps and libraries
JavaScript
3
star
52

sharable-components-prototype

JavaScript
3
star
53

react-ember-demo

JavaScript
3
star
54

react-main

JavaScript
3
star
55

ts-json-rpc

TypeScript
3
star
56

stylesheets

Client/server stylesheet management
JavaScript
3
star
57

reactify-server-rendering-tools

JavaScript
3
star
58

react-freezer

JavaScript
3
star
59

omgnosql

OMG! NoSQL!!!
Python
2
star
60

reactbars

DONT EVEN THINK ABOUT IT
JavaScript
2
star
61

dslpy

Domain specific languages embedded in Python
Python
2
star
62

jsxnode

JavaScript
2
star
63

react-graph

immutable client-side graph abstraction with great react integration. fulfills similar use cases to backbone.model
JavaScript
2
star
64

dagster-ml-example

Python
2
star
65

meteor-leaderboard-react

Meteor leaderboard example using React
JavaScript
2
star
66

objectid

Python
2
star
67

reactpad

JavaScript
2
star
68

htmldry

Don't Repeat your HTML
JavaScript
2
star
69

react-meteor

Meteor bindings for React, packaged for npm
JavaScript
2
star
70

browserify-bundler

JavaScript
1
star
71

dagster-data-sources

1
star
72

jsbs

JavaScript boot strap, or JavaScript bullshit, depending on what you prefer
JavaScript
1
star
73

jsonrpc2.0-cli

JavaScript
1
star
74

sketchpad

Python
1
star
75

odsc-talk

Python
1
star
76

inboxfeed

JavaScript
1
star
77

browserify-transform-server-side

JavaScript
1
star
78

ts-json-rpc-client

TypeScript
1
star
79

statics-stylesheets

JavaScript
1
star
80

rx-spinner

A simple reusable spinner component example
JavaScript
1
star
81

react-profiler

A simpler interface to ReactDefaultPerf
JavaScript
1
star
82

react-core

JavaScript
1
star
83

text-to-pydantic

Python
1
star
84

dagster-gitpod

Python
1
star