Skip to content

Latest commit

 

History

History
272 lines (229 loc) · 13.1 KB

webpack-config.md

File metadata and controls

272 lines (229 loc) · 13.1 KB

Webpack Configurations

Standard configurations for Webpack.

Example

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:

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.

Configuration Details

  • config/webpack/app-base

    • Config factory handles the following fields in the options object:

      • babelEnvString — Babel environment to use for the Babel compilation step;
      • contextString — Base URL for the resolution of relative config paths;
      • cssLocalIdentString — 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].
      • entryObject|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;
      • keepBuildInfoBoolean — Optional. If true 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 to false.
      • modeStringWebpack mode.
      • publicPathString — 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, and config/babel/webpack config.
    • 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 with npm 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 the fs 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 for BUILD_RNDKEY;
      • timestamp — The value set for BUILD_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 of cssLocalIdent 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:
  • config/webpack/app-production

    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:
  • config/webpack/lib-base

    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:

      • babelEnvString — Babel environment to use for the Babel compilation step;

      • contextString — Base URL for the resolution of relative config paths;

      • cssLocalIdentString — 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].

      • entryObject|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;

      • libraryString — Name of the library to be build. It is important for proper resolution of the library assets.

      • modeStringWebpack 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 the dist/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, and config/babel/webpack config.
    • 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 with npm 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.

  • config/webpack/lib-production

    Extends and tunes config/webpack/lib-base to use production Babel environment, and sets [hash:base64:6] as the template for generated CSS classnames.

Example

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"