Standard configurations for Webpack.
Why? — Webpack is the heart of our build pipeline for ReactJS applications. A proper Webpack configurations is necessary for many features in our code, and it has a serious impact on the performance of the compiled code. The standard Webpack configuration shared among our projects ensure consistency and the ease of maintanance of our codebases.
Several Webpack configurations are provided by this package:
- config/webpack/app-base — Base Webpack configuration for ReactJS applications. It is further extended for development and production use by the app-development and app-production configs below.
- config/webpack/app-development — Development Webpack configuration for ReactJS applications;
- config/webpack/app-production — Production Webpack configuration for ReactJS applications;
- config/webpack/lib-base — Base Webpack configuration for ReactJS libraries. It is further extended for development and production use by the lib-development and lib-production configs below;
- config/webpack/lib-development — Development Webpack configuration for ReactJS libraries;
- config/webpack/lib-production — Production Webpack configuration for ReactJS libraries.
Each of these modules provides a configuration factory that takes an option hash as the argument, and returns config object. The option hash allows to easily modify the most useful configuration options; while other options of the returned config object can be further customized with use of webpackMerge, or by the direct mutation of the config object.
-
-
Config factory handles the following fields in the options object:
babelEnv
— String — Babel environment to use for the Babel compilation step;context
— String — Base URL for the resolution of relative config paths;cssLocalIdent
— String — Optional. The template for the CSS classnames generation by the Webpack'scss-loader
; it is passed into thelocalIdentName
param of the loader. It should match the corresponding setting in the Babel config. Defaults to[hash:base64:6]
.entry
— Object|String|String[] — Entry points. If an object is passed in, thepolyfills
entry point (chunk) is extended or appended to include some polyfills we consider obligatory (babel-polyfill, nodelist-foreach-polyfill). If a string or a string array is passed in, it is assigned to the main entry pont, and the polyfills entry point is added then;keepBuildInfo
— Boolean — Optional. Iftrue
and a.build-info
file from a previous build exists in the context directory, it will be loaded and used, rather than re-generated by the config factory. It allows to re-create the Webpack config during a server launch without re-generation of the build info file created during a previous build (and thus bundled into the frontend bundle). Defaults tofalse
.mode
– String – Webpack mode.publicPath
— String — Base URL for the output of the build assets;
-
The generated config will opt to:
- Bundle the font assets (EOF, OTF, SVG, TTF, WOFF, WOFF2 files from
the
src/assets/fonts
folder of your source code will be bundled and output into the[PUBLIC_PATH]/fonts
folder); - Bundle image assets (GIF, JPEG, JPG, PNG files from any folder of
your source code will be bundled and output into the
[PUBLIC_PATH]/images
folder); - Bundle SCSS files from any folder of your source code, beside
node_modules
and its subfolders. The files will be compiled, bundled and extracted into the[PUBLIC_PATH]/[CHUNK_NAME].css
bundles; - Bundle CSS files from any folder of your code. The files will be
bundled and extracted into the
[PUBLIC_PATH]/[CHUNK_NAME].css
bundles; - Bundle JS, JSX, and SVG files; they will be compiled into the
[PUBLIC_PATH]/[CHUNK_NAME].js
bundles, using the Babel environment specified in the factory options, andconfig/babel/webpack
config.
- Bundle the font assets (EOF, OTF, SVG, TTF, WOFF, WOFF2 files from
the
-
The following path aliases will be automatically set:
assets
for[CONTEXT]/src/assets
;components
for[CONTEXT]/src/shared/components
;fonts
for[CONTEXT]/src/assets/fonts
;styles
for[CONTEXT]/src/styles
.
Also
resolve.symlinks
Webpack option is set to false to avoid problems with resolution of assets from packages linked withnpm link
. -
The following global variables will be emulated inside the output JS bundle:
BUILD_RNDKEY
— A random 32 bit key that can be used for encryption, it is set just as a global variable accessible in the code;BUILD_TIMESTAMP
— UTC timestamp of the beginning of the build;FRONT_END
— It will be set true inside the bundle, so that shared code can use it to determine that it is executed at the client side.
-
It also opts to polyfill the
__dirname
global variable, and to ignore imports of thefs
Node package; -
Also, it will store to the disk (re-writes if exists) the file
[CONTEXT]/.build-info
which will contain a stringified JSON object with the following fields:rndkey
— The value set forBUILD_RNDKEY
;timestamp
— The value set forBUILD_TIMESTAMP
.
-
-
config/webpack/app-development
This configration is based on the
config/webpack/app-base
and it differs from that in the following:- development Babel environment is enforced, and sets
[path][name]___[local]___[hash:base64:6]
as the value ofcssLocalIdent
argument for the base config. - Adds as polyfills the code necessary to support the Hot Module Reloading:
- Emulates the following environment variables:
BABEL_ENV
— It is set to development to inform any interested code that it is running in dev mode;DEV_TOOLS
— It is set to true to signal the code that Redux dev tools should be enabled;NODE_ENV
— It is set to development.
- Adds the following plugins:
- development Babel environment is enforced, and sets
-
This configuration is based on the
config/webpack/app-base
and it differs from that in the following:- production Babel environment is enforced;
- Emulates the following environment variables:
BABEL_ENV
— It is set to production;NODE_ENV
— It is set to production.
- Adds the following plugins:
-
This config is intended for ReactJS libraries; it allows to perform as much compilation of isomorphic ReactJS code as possible, so that the package can be further imported and used by another ReactJS package.
-
Config factory handles the following fields in the options object:
-
babelEnv
— String — Babel environment to use for the Babel compilation step; -
context
— String — Base URL for the resolution of relative config paths; -
cssLocalIdent
— String — Optional. The template for the CSS classnames generation by the Webpack's css-loader; it is passed into the localIdentName param of the loader. It should match the corresponding setting in the Babel config. Defaults to [hash:base64:6]. -
entry
— Object|String|String[] — Entry points. If an object is passed in, the polyfills entry point (chunk) is extended or appended to include some polyfills we consider obligatory (babel-polyfill, nodelist-foreach-polyfill). If a string or a string array is passed in, it is assigned to the main entry pont, and the polyfills entry point is added then; -
library
— String — Name of the library to be build. It is important for proper resolution of the library assets. -
mode
– String – Webpack mode.
-
-
The generated config will opt to:
- References to the font assets (EOF, OTF, SVG, TTF, WOFF, WOFF2 files from
the
src/assets/fonts
folder of the library source code) will rewritten to~LIBRARY_NAME/src/assets/fonts/FILENAME.FILE_EXTENSION
so that the host package of the library will be able to find and bundle them; - Bundle SCSS files from any folder of your source code, beside
node_modules
and its subfolders. The files will be compiled, bundled and extracted into thedist/style.css
bundles; - Bundle JS, JSX, and SVG files; they will be compiled into the
dist/index.js
bundles, using the Babel environment specified in the factory options, andconfig/babel/webpack
config.
- References to the font assets (EOF, OTF, SVG, TTF, WOFF, WOFF2 files from
the
-
The following path aliases will be automatically set:
assets
for[CONTEXT]/src/assets
;components
for[CONTEXT]/src/shared/components
;fonts
for[CONTEXT]/src/assets/fonts
;styles
for[CONTEXT]/src/styles
.
Also
resolve.symlinks
Webpack option is set to false to avoid problems with resolution of assets from packages linked withnpm link
. -
The following packages are declared as externals:
babel-runtime
,lodash
,moment
,prop-types
,react
,react-css-super-themr
,react-dom
,react-router-dom
,topcoder-react-utils
,url-parse
-
-
config/webpack/lib-development
Extends and tunes
config/webpack/lib-base
to use development Babel environment, and sets[path][name]___[local]___[hash:base64:6]
as the template for generated CSS classnames. -
Extends and tunes
config/webpack/lib-base
to use production Babel environment, and sets[hash:base64:6]
as the template for generated CSS classnames.
Say, you want to setup Webpack configuration for development build in a new
project. Create the following configuration file inside config/webpack
folder
(the exact folder is just a convention we like to use across the projects):
// config/webpack/development.js
/* Note that config JS files are not processed by Babel, thus you should use
* only the subset of JS syntax natively understood by the current Node version. */
const configFactory = require('topcoder-react-utils/config/webpack/app-development');
const path = require('path');
const standardConfig = configFactory({
/* To resolve all paths in the config relative to the root folder of your code. */
context: path.resolve(__dirname, '../..'),
/* Entry point of you code. You can also pass in JS object with keys naming
* the separate bundles you want to pack, and the values specifying their
* entry points. */
entry: './src',
/* You can use "publicPath" option here if you want to serve generated
* assets from a non-root folder of your server. */
});
/* Here you can make additional modifications of the config, if you need to,
* using "webpack-merge" package, or in some custom way. */
module.exports = standardConfig;
To wire this config to your NPM build script, create another simple file in the root of your code:
// webpack.config.js
/* eslint-disable global-require */
/* eslint-disable import/no-dynamic-require */
module.exports = function buildConfig(env) {
return require(`./config/webpack/${env}.js`);
}
Now you can define your NPM build script, using the necessary config, like so
(the clean step is handy, it should be defined as a separate clean
script):
"build:dev": "npm run clean && ./node_modules/.bin/webpack --env=development --progress --profile --colors --display-optimization-bailout"