UNPKG

13.4 kBMarkdownView Raw
1# Webpack Configurations
2Standard configurations for [Webpack](https://webpack.js.org/).
3
4[Example](#example)
5
6**Why?** — Webpack is the heart of our build pipeline for ReactJS
7applications. A proper Webpack configurations is necessary for many features in
8our code, and it has a serious impact on the performance of the compiled code.
9The standard Webpack configuration shared among our projects ensure consistency
10and the ease of maintanance of our codebases.
11
12Several Webpack configurations are provided by this package:
13- [**config/webpack/app-base**](#app-base) — Base Webpack configuration for
14 ReactJS applications. It is further extended for development and production
15 use by the *app-development* and *app-production* configs below.
16- [**config/webpack/app-development**](#app-development) — Development Webpack
17 configuration for ReactJS applications;
18- [**config/webpack/app-production**](#app-production) — Production Webpack
19 configuration for ReactJS applications;
20- [**config/webpack/lib-base**](#lib-base) — Base Webpack configuration
21 for ReactJS libraries. It is further extended for development and production
22 use by the *lib-development* and *lib-production* configs below;
23- [**config/webpack/lib-development**](#lib-development) — Development
24 Webpack configuration for ReactJS libraries;
25- [**config/webpack/lib-production**](#lib-production) — Production
26 Webpack configuration for ReactJS libraries.
27
28Each of these modules provides a configuration factory that takes an option hash
29as the argument, and returns config object. The option hash allows to easily
30modify the most useful configuration options; while other options of the
31returned config object can be further customized with use of
32[webpackMerge](https://www.npmjs.com/package/webpack-merge), or by the direct
33mutation of the config object.
34
35### Configuration Details
36- <a name="app-base">**`config/webpack/app-base`**</a>
37 - Config factory handles the following fields in the options object:
38 - **`babelEnv`** &mdash; *String* &mdash; Babel environment to use for
39 the Babel compilation step;
40 - **`context`** &mdash; *String* &mdash; Base URL for the resolution of
41 relative config paths;
42 - **`cssLocalIdent`** &mdash; *String* &mdash; Optional. The template for
43 the CSS classnames generation by the Webpack's `css-loader`; it is passed
44 into the `localIdentName` param of the loader. It should match the
45 corresponding setting in the Babel config. Defaults to `[hash:base64:6]`.
46 - **`entry`** &mdash; *Object*|*String*|*String[]* &mdash; Entry points.
47 If an object is passed in, the `polyfills` entry point (chunk) is extended
48 or appended to include some polyfills we consider obligatory
49 ([babel-polyfill](https://babeljs.io/docs/usage/polyfill/),
50 [nodelist-foreach-polyfill](https://www.npmjs.com/package/nodelist-foreach-polyfill)).
51 If a string or a string array is passed in, it is assigned to the *main*
52 entry pont, and the *polyfills* entry point is added then;
53 - **`keepBuildInfo`** &mdash; *Boolean* &mdash; Optional. If `true` and a
54 `.build-info` file from a previous build exists in the context directory,
55 it will be loaded and used, rather than re-generated by the config factory.
56 It allows to re-create the Webpack config during a server launch without
57 re-generation of the build info file created during a previous build
58 (and thus bundled into the frontend bundle). Defaults to `false`.
59 - **`mode`** &ndash; *String* &ndash; [Webpack mode](https://webpack.js.org/concepts/mode/).
60 - **`publicPath`** &mdash; *String* &mdash; Base URL for the output of
61 the build assets;
62
63 - The generated config will opt to:
64 - Bundle the font assets (EOF, OTF, SVG, TTF, WOFF, WOFF2 files from
65 the `src/assets/fonts` folder of your source code will be bundled
66 and output into the `[PUBLIC_PATH]/fonts` folder);
67 - Bundle image assets (GIF, JPEG, JPG, PNG files from any folder of
68 your source code will be bundled and output into the
69 `[PUBLIC_PATH]/images` folder);
70 - Bundle SCSS files from any folder of your source code, beside
71 `node_modules` and its subfolders. The files will be compiled,
72 bundled and extracted into the `[PUBLIC_PATH]/[CHUNK_NAME].css`
73 bundles;
74 - Bundle CSS files from any folder of your code. The files will be
75 bundled and extracted into the `[PUBLIC_PATH]/[CHUNK_NAME].css`
76 bundles;
77 - Bundle JS, JSX, and SVG files; they will be compiled into the
78 `[PUBLIC_PATH]/[CHUNK_NAME].js` bundles, using the Babel environment
79 specified in the factory options, and
80 [`config/babel/webpack`](./babel-config.js#webpack) config.
81
82 - The following path aliases will be automatically set:
83 - **`assets`** for `[CONTEXT]/src/assets`;
84 - **`components`** for `[CONTEXT]/src/shared/components`;
85 - **`fonts`** for `[CONTEXT]/src/assets/fonts`;
86 - **`styles`** for `[CONTEXT]/src/styles`.
87
88 Also `resolve.symlinks` Webpack option is set to *false* to avoid problems
89 with resolution of assets from packages linked with `npm link`.
90
91 - The following global variables will be emulated inside the output
92 JS bundle:
93 - **`BUILD_RNDKEY`** &mdash; A random 32 bit key that can be used
94 for encryption, it is set just as a global variable accessible in
95 the code;
96 - **`BUILD_TIMESTAMP`** &mdash; UTC timestamp of the beginning of
97 the build;
98 - **`FRONT_END`** &mdash; It will be set *true* inside the bundle,
99 so that shared code can use it to determine that it is executed
100 at the client side.
101
102 - It also opts to polyfill the `__dirname` global variable,
103 and to ignore imports of the `fs` Node package;
104
105 - Also, it will store to the disk (re-writes if exists) the file
106 `[CONTEXT]/.build-info` which will contain a stringified JSON
107 object with the following fields:
108 - **`rndkey`** &mdash; The value set for `BUILD_RNDKEY`;
109 - **`timestamp`** &mdash; The value set for `BUILD_TIMESTAMP`.
110
111- <a name="app-development">**`config/webpack/app-development`**</a>
112
113 This configration is based on the [`config/webpack/app-base`](#app-base) and
114 it differs from that in the following:
115 - *development* Babel environment is enforced, and sets
116 `[path][name]___[local]___[hash:base64:6]` as the value of
117 `cssLocalIdent` argument for the base config.
118 - Adds as polyfills the code necessary to support the Hot Module
119 Reloading:
120 - [`react-hot-loader/patch`](https://github.com/gaearon/react-hot-loader)
121 - [`webpack-hot-middleware/client?reload=true`](https://github.com/glenjamin/webpack-hot-middleware)
122 - Emulates the following environment variables:
123 - **`BABEL_ENV`** &mdash; It is set to *development* to inform any
124 interested code that it is running in dev mode;
125 - **`DEV_TOOLS`** &mdash; It is set to *true* to signal the code that
126 Redux dev tools should be enabled;
127 - **`NODE_ENV`** &mdash; It is set to *development*.
128 - Adds the following plugins:
129 - [HotModuleReplacementPlugin](https://webpack.js.org/plugins/hot-module-replacement-plugin/);
130 - [NoEmitOnErrorsPlugin](https://webpack.js.org/plugins/no-emit-on-errors-plugin/);
131 - [NamedModulesPlugin](https://webpack.js.org/plugins/named-modules-plugin/).
132
133- <a name="app-production">**`config/webpack/app-production`**</a>
134
135 This configuration is based on the [`config/webpack/app-base`](#app-base) and
136 it differs from that in the following:
137 - *production* Babel environment is enforced;
138 - Emulates the following environment variables:
139 - **`BABEL_ENV`** &mdash; It is set to *production*;
140 - **`NODE_ENV`** &mdash; It is set to *production*.
141 - Adds the following plugins:
142 - [OptimizeCssAssetsPlugin](https://www.npmjs.com/package/optimize-css-assets-webpack-plugin);
143 - [UglifyJsPlugin](https://webpack.js.org/plugins/uglifyjs-webpack-plugin/).
144
145- <a name="lib-base">**`config/webpack/lib-base`**</a>
146
147 This config is intended for ReactJS libraries; it allows to perform as much
148 compilation of isomorphic ReactJS code as possible, so that the package can be
149 further imported and used by another ReactJS package.
150
151 - Config factory handles the following fields in the options object:
152
153 - **`babelEnv`** &mdash; *String* &mdash; Babel environment to use for the
154 Babel compilation step;
155
156 - **`context`** &mdash; *String* &mdash; Base URL for the resolution of
157 relative config paths;
158
159 - **`cssLocalIdent`** &mdash; *String* &mdash; Optional. The template for
160 the CSS classnames generation by the Webpack's css-loader; it is passed
161 into the localIdentName param of the loader. It should match the
162 corresponding setting in the Babel config. Defaults to [hash:base64:6].
163
164 - **`entry`** &mdash; *Object|String|String[]* &mdash; Entry points. If an
165 object is passed in, the polyfills entry point (chunk) is extended or
166 appended to include some polyfills we consider obligatory (babel-polyfill,
167 nodelist-foreach-polyfill). If a string or a string array is passed in, it
168 is assigned to the main entry pont, and the polyfills entry point is added
169 then;
170
171 - **`library`** &mdash; *String* &mdash; Name of the library to be build.
172 It is important for proper resolution of the library assets.
173
174 - **`mode`** &ndash; *String* &ndash; [Webpack mode](https://webpack.js.org/concepts/mode/).
175
176 - The generated config will opt to:
177 - References to the font assets (EOF, OTF, SVG, TTF, WOFF, WOFF2 files from
178 the `src/assets/fonts` folder of the library source code) will rewritten
179 to `~LIBRARY_NAME/src/assets/fonts/FILENAME.FILE_EXTENSION`
180 so that the host package of the library will be able to find and bundle
181 them;
182 - Bundle SCSS files from any folder of your source code, beside
183 `node_modules` and its subfolders. The files will be compiled,
184 bundled and extracted into the `dist/style.css`
185 bundles;
186 - Bundle JS, JSX, and SVG files; they will be compiled into the
187 `dist/index.js` bundles, using the Babel environment
188 specified in the factory options, and
189 [`config/babel/webpack`](./babel-config.js#webpack) config.
190
191 - The following path aliases will be automatically set:
192 - **`assets`** for `[CONTEXT]/src/assets`;
193 - **`components`** for `[CONTEXT]/src/shared/components`;
194 - **`fonts`** for `[CONTEXT]/src/assets/fonts`;
195 - **`styles`** for `[CONTEXT]/src/styles`.
196
197 Also `resolve.symlinks` Webpack option is set to *false* to avoid problems
198 with resolution of assets from packages linked with `npm link`.
199
200 - The following packages are declared as externals:
201 - `babel-runtime`,
202 - `lodash`,
203 - `moment`,
204 - `prop-types`,
205 - `react`,
206 - `react-css-super-themr`,
207 - `react-dom`,
208 - `react-router-dom`,
209 - `topcoder-react-utils`,
210 - `url-parse`
211
212- <a name="lib-development">**`config/webpack/lib-development`**</a>
213
214 Extends and tunes [`config/webpack/lib-base`](#lib-base) to use *development*
215 Babel environment, and sets `[path][name]___[local]___[hash:base64:6]` as
216 the template for generated CSS classnames.
217
218- <a name="lib-production">**`config/webpack/lib-production`**</a>
219
220 Extends and tunes [`config/webpack/lib-base`](#lib-base) to use *production*
221 Babel environment, and sets `[hash:base64:6]` as the template for generated
222 CSS classnames.
223
224### Example
225Say, you want to setup Webpack configuration for development build in a new
226project. Create the following configuration file inside `config/webpack` folder
227(the exact folder is just a convention we like to use across the projects):
228```js
229// config/webpack/development.js
230
231/* Note that config JS files are not processed by Babel, thus you should use
232 * only the subset of JS syntax natively understood by the current Node version. */
233const configFactory = require('topcoder-react-utils/config/webpack/app-development');
234const path = require('path');
235
236const standardConfig = configFactory({
237 /* To resolve all paths in the config relative to the root folder of your code. */
238 context: path.resolve(__dirname, '../..'),
239
240 /* Entry point of you code. You can also pass in JS object with keys naming
241 * the separate bundles you want to pack, and the values specifying their
242 * entry points. */
243 entry: './src',
244
245 /* You can use "publicPath" option here if you want to serve generated
246 * assets from a non-root folder of your server. */
247});
248
249/* Here you can make additional modifications of the config, if you need to,
250 * using "webpack-merge" package, or in some custom way. */
251
252module.exports = standardConfig;
253```
254
255To wire this config to your NPM build script, create another simple file in
256the root of your code:
257```js
258// webpack.config.js
259
260/* eslint-disable global-require */
261/* eslint-disable import/no-dynamic-require */
262
263module.exports = function buildConfig(env) {
264 return require(`./config/webpack/${env}.js`);
265}
266```
267
268Now you can define your NPM build script, using the necessary config, like so
269(the clean step is handy, it should be defined as a separate `clean` script):
270```
271"build:dev": "npm run clean && ./node_modules/.bin/webpack --env=development --progress --profile --colors --display-optimization-bailout"
272```