1 | [![npm version](https://badge.fury.io/js/parallel-webpack.svg)](https://badge.fury.io/js/parallel-webpack)
|
2 | [![Build Status](https://travis-ci.org/trivago/parallel-webpack.svg?branch=master)](https://travis-ci.org/trivago/parallel-webpack) [![CircleCI](https://circleci.com/gh/trivago/parallel-webpack.svg?style=svg)](https://circleci.com/gh/trivago/parallel-webpack) [![Coverage Status](https://coveralls.io/repos/github/trivago/parallel-webpack/badge.svg?branch=coverage)](https://coveralls.io/github/trivago/parallel-webpack?branch=coverage)
|
3 | [![Install Size](https://packagephobia.now.sh/badge?p=parallel-webpack)](https://packagephobia.now.sh/result?p=parallel-webpack)
|
4 | # parallel-webpack - Building multi-configs in parallel
|
5 |
|
6 | `parallel-webpack` allows you to run multiple webpack builds in parallel,
|
7 | spreading the work across your processors and thus helping to significantly speed
|
8 | up your build. For us at [trivago](http://www.trivago.com) it has reduced
|
9 | the build from 16 minutes to just 2 minutes - for 32 variants. That performance
|
10 | improvement naturally comes at the expense of utilizing all available CPU cores.
|
11 |
|
12 | ## Installation
|
13 |
|
14 | ```sh
|
15 | npm install parallel-webpack --save-dev
|
16 | ```
|
17 |
|
18 | You can choose whether to install `parallel-webpack` globally or locally.
|
19 | At [trivago](http://www.trivago.com), we keep our build tools locally to the project
|
20 | so that we have full control over its versions.
|
21 |
|
22 | ## Basic example
|
23 |
|
24 | Given a `webpack.config.js` like this:
|
25 |
|
26 | ```javascript
|
27 | var path = require('path');
|
28 | module.exports = [{
|
29 | entry: './pageA.js',
|
30 | output: {
|
31 | path: path.resolve(__dirname, './dist'),
|
32 | filename: 'pageA.bundle.js'
|
33 | }
|
34 | }, {
|
35 | entry: './pageB.js',
|
36 | output: {
|
37 | path: path.resolve(__dirname, './dist'),
|
38 | filename: 'pageB.bundle.js'
|
39 | }
|
40 | }];
|
41 | ```
|
42 |
|
43 | `parallel-webpack` will run both specified builds in parallel.
|
44 |
|
45 | ## Variants example
|
46 |
|
47 | Sometimes, just using different configurations like above won't be enough and what
|
48 | you really want or need is the same configuration with some adjustments.
|
49 | `parallel-webpack` can help you with generating those `configuration variants` as
|
50 | well.
|
51 |
|
52 | ```javascript
|
53 | var createVariants = require('parallel-webpack').createVariants;
|
54 |
|
55 | // Those options will be mixed into every variant
|
56 | // and passed to the `createConfig` callback.
|
57 | var baseOptions = {
|
58 | preferredDevTool: process.env.DEVTOOL || 'eval'
|
59 | };
|
60 |
|
61 | // This object defines the potential option variants
|
62 | // the key of the object is used as the option name, its value must be an array
|
63 | // which contains all potential values of your build.
|
64 | var variants = {
|
65 | minified: [true, false],
|
66 | debug: [true, false],
|
67 | target: ['commonjs2', 'var', 'umd', 'amd']
|
68 | };
|
69 |
|
70 | function createConfig(options) {
|
71 | var plugins = [
|
72 | new webpack.optimize.DedupePlugin(),
|
73 | new webpack.optimize.OccurenceOrderPlugin(),
|
74 | new webpack.DefinePlugin({
|
75 | DEBUG: JSON.stringify(JSON.parse(options.debug))
|
76 | })
|
77 | ];
|
78 | if(options.minified) {
|
79 | plugins.push(new webpack.optimize.UglifyJsPlugin({
|
80 | sourceMap: false,
|
81 | compress: {
|
82 | warnings: false
|
83 | }
|
84 | }));
|
85 | }
|
86 | return {
|
87 | entry: './index.js',
|
88 | devtool: options.preferredDevTool,
|
89 | output: {
|
90 | path: './dist/',
|
91 | filename: 'MyLib.' +
|
92 | options.target +
|
93 | (options.minified ? '.min' : '') +
|
94 | (options.debug ? '.debug' : '')
|
95 | + '.js',
|
96 | libraryTarget: options.target
|
97 | },
|
98 | plugins: plugins
|
99 | };
|
100 | }
|
101 |
|
102 | module.exports = createVariants(baseOptions, variants, createConfig);
|
103 | ```
|
104 |
|
105 | The above configuration will create 16 variations of the build for you, which
|
106 | `parallel-webpack` will distribute among your processors for building.
|
107 |
|
108 | ```
|
109 | [WEBPACK] Building 16 targets in parallel
|
110 | [WEBPACK] Started building MyLib.umd.js
|
111 | [WEBPACK] Started building MyLib.umd.min.js
|
112 | [WEBPACK] Started building MyLib.umd.debug.js
|
113 | [WEBPACK] Started building MyLib.umd.min.debug.js
|
114 |
|
115 | [WEBPACK] Started building MyLib.amd.js
|
116 | [WEBPACK] Started building MyLib.amd.min.js
|
117 | [WEBPACK] Started building MyLib.amd.debug.js
|
118 | [WEBPACK] Started building MyLib.amd.min.debug.js
|
119 |
|
120 | [WEBPACK] Started building MyLib.commonjs2.js
|
121 | [WEBPACK] Started building MyLib.commonjs2.min.js
|
122 | [WEBPACK] Started building MyLib.commonjs2.debug.js
|
123 | [WEBPACK] Started building MyLib.commonjs2.min.debug.js
|
124 |
|
125 | [WEBPACK] Started building MyLib.var.js
|
126 | [WEBPACK] Started building MyLib.var.min.js
|
127 | [WEBPACK] Started building MyLib.var.debug.js
|
128 | [WEBPACK] Started building MyLib.var.min.debug.js
|
129 | ```
|
130 |
|
131 | ## Running the watcher
|
132 |
|
133 | One of the features that made webpack so popular is certainly its watcher which
|
134 | continously rebuilds your application.
|
135 |
|
136 | When using `parallel-webpack`, you can easily use the same feature as well by
|
137 | specifying the `--watch` option on the command line:
|
138 |
|
139 | ```
|
140 | parallel-webpack --watch
|
141 | ```
|
142 |
|
143 | ## Specifying retry limits
|
144 |
|
145 | As a side-effect of using `parallel-webpack`, an error will no longer lead to
|
146 | you having to restart webpack. Instead, `parallel-webpack` will keep retrying to
|
147 | build your application until you've fixed the problem.
|
148 |
|
149 | While that is highly useful for development it can be a nightmare for
|
150 | CI builds. Thus, when building with `parallel-webpack` in a CI context, you should
|
151 | consider to use the `--max-retries` (or `-m` option) to force `parallel-webpack` to give
|
152 | up on your build after a certain amount of retries:
|
153 |
|
154 | ```
|
155 | parallel-webpack --max-retries=3
|
156 | ```
|
157 |
|
158 | ## Specifying the configuration file
|
159 |
|
160 | When you need to use a configuration file that is not `webpack.config.js`, you can
|
161 | specify its name using the `--config` parameter:
|
162 |
|
163 | ```
|
164 | parallel-webpack --config=myapp.webpack.config.js
|
165 | ```
|
166 |
|
167 | ## Switch off statistics (improves performance)
|
168 |
|
169 | While the statistics generated by Webpack are very usually very useful, they also
|
170 | take time to generate and print and create a lot of visual overload if you don't
|
171 | actually need them.
|
172 |
|
173 | Since version *1.3.0*, generating them can be turned off:
|
174 |
|
175 | ```
|
176 | parallel-webpack --no-stats
|
177 | ```
|
178 |
|
179 | ## Limiting parallelism
|
180 |
|
181 | Under certain circumstances you might not want `parallel-webpack` to use all of your
|
182 | available CPUs for building your assets. In those cases, you can specify the `parallel`,
|
183 | or `p` for short, option to tell `parallel-webpack` how many CPUs it may use.
|
184 |
|
185 | ```
|
186 | parallel-webpack -p=2
|
187 | ```
|
188 |
|
189 |
|
190 | ## Configurable configuration
|
191 |
|
192 | Sometimes, you might want to access command line arguments within your `webpack.config.js`
|
193 | in order to create a more specific configuration.
|
194 |
|
195 | `parallel-webpack` will forward every parameter specified after `--` to the configuration
|
196 | as is:
|
197 |
|
198 | ```
|
199 | parallel-webpack -- --app=trivago
|
200 | ```
|
201 |
|
202 |
|
203 | Within `webpack.config.js`:
|
204 |
|
205 | ```
|
206 | console.log(process.argv);
|
207 | // => [ 'node', 'parallel-webpack', '--app=trivago' ]
|
208 | ```
|
209 |
|
210 | `parallel-webpack` adds the first two values to `process.argv` to ensure that there
|
211 | are no differences between various ways of invoking the `webpack.config.js`.
|
212 |
|
213 | ## Node.js API
|
214 |
|
215 | Just like webpack, you can also use `parallel-webpack` as an API from node.js
|
216 | (You can specify any other option used in [worker-farm](https://www.npmjs.com/package/worker-farm)):
|
217 |
|
218 | ```javascript
|
219 | var run = require('parallel-webpack').run,
|
220 | configPath = require.resolve('./webpack.config.js');
|
221 |
|
222 | run(configPath, {
|
223 | watch: false,
|
224 | maxRetries: 1,
|
225 | stats: true, // defaults to false
|
226 | maxConcurrentWorkers: 2 // use 2 workers
|
227 | });
|
228 | ```
|
229 |
|
230 | You can pass a notify callback as well.
|
231 | ```javascript
|
232 | var run = require('parallel-webpack').run,
|
233 | configPath = require.resolve('./webpack.config.js'),
|
234 | options = {/*...*/};
|
235 |
|
236 | function notify() {
|
237 | // do things
|
238 | }
|
239 |
|
240 | run(configPath, options, notify);
|
241 | ```
|
242 | **NOTE:** In watch mode notify callback provided with Node.js API will run **only once**
|
243 | when all of the builds are finished.
|
244 |
|
245 | ### createVariants
|
246 |
|
247 | ---
|
248 |
|
249 | #### createVariants(baseConfig: Object, variants: Object, configCallback: Function): Object[]
|
250 |
|
251 | Alters the given `baseConfig` with all possible `variants` and maps the result into
|
252 | a valid webpack configuration using the given `configCallback`.
|
253 |
|
254 | #### createVariants(variants: Object, configCallback: Function): Object[]
|
255 |
|
256 | Creates all possible variations as specified in the `variants` object and
|
257 | maps the result into a valid webpack configuration using the given `configCallback`.
|
258 |
|
259 | #### createVariants(baseConfig: Object, variants: Object): Object[]
|
260 |
|
261 | Alters the given `baseConfig` with all possible `variants` and returns it.
|
262 |
|
263 | #### createVariants(variants: Object): Object[]
|
264 |
|
265 | Creates all possible variations from the given `variants` and returns them as a flat array.
|