1 | # Webpack Configurations
|
2 | Standard configurations for [Webpack](https://webpack.js.org/).
|
3 |
|
4 | [Example](#example)
|
5 |
|
6 | **Why?** — Webpack is the heart of our build pipeline for ReactJS
|
7 | applications. A proper Webpack configurations is necessary for many features in
|
8 | our code, and it has a serious impact on the performance of the compiled code.
|
9 | The standard Webpack configuration shared among our projects ensure consistency
|
10 | and the ease of maintanance of our codebases.
|
11 |
|
12 | Several 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 |
|
28 | Each of these modules provides a configuration factory that takes an option hash
|
29 | as the argument, and returns config object. The option hash allows to easily
|
30 | modify the most useful configuration options; while other options of the
|
31 | returned config object can be further customized with use of
|
32 | [webpackMerge](https://www.npmjs.com/package/webpack-merge), or by the direct
|
33 | mutation 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`** — *String* — Babel environment to use for
|
39 | the Babel compilation step;
|
40 | - **`context`** — *String* — Base URL for the resolution of
|
41 | relative config paths;
|
42 | - **`cssLocalIdent`** — *String* — 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`** — *Object*|*String*|*String[]* — 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`** — *Boolean* — 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`** – *String* – [Webpack mode](https://webpack.js.org/concepts/mode/).
|
60 | - **`publicPath`** — *String* — 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`** — 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`** — UTC timestamp of the beginning of
|
97 | the build;
|
98 | - **`FRONT_END`** — 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`** — The value set for `BUILD_RNDKEY`;
|
109 | - **`timestamp`** — 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`** — It is set to *development* to inform any
|
124 | interested code that it is running in dev mode;
|
125 | - **`DEV_TOOLS`** — It is set to *true* to signal the code that
|
126 | Redux dev tools should be enabled;
|
127 | - **`NODE_ENV`** — 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`** — It is set to *production*;
|
140 | - **`NODE_ENV`** — 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`** — *String* — Babel environment to use for the
|
154 | Babel compilation step;
|
155 |
|
156 | - **`context`** — *String* — Base URL for the resolution of
|
157 | relative config paths;
|
158 |
|
159 | - **`cssLocalIdent`** — *String* — 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`** — *Object|String|String[]* — 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`** — *String* — Name of the library to be build.
|
172 | It is important for proper resolution of the library assets.
|
173 |
|
174 | - **`mode`** – *String* – [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
|
225 | Say, you want to setup Webpack configuration for development build in a new
|
226 | project. 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. */
|
233 | const configFactory = require('topcoder-react-utils/config/webpack/app-development');
|
234 | const path = require('path');
|
235 |
|
236 | const 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 |
|
252 | module.exports = standardConfig;
|
253 | ```
|
254 |
|
255 | To wire this config to your NPM build script, create another simple file in
|
256 | the root of your code:
|
257 | ```js
|
258 | // webpack.config.js
|
259 |
|
260 | /* eslint-disable global-require */
|
261 | /* eslint-disable import/no-dynamic-require */
|
262 |
|
263 | module.exports = function buildConfig(env) {
|
264 | return require(`./config/webpack/${env}.js`);
|
265 | }
|
266 | ```
|
267 |
|
268 | Now 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 | ```
|