Webpack
The library provides several tuneable Webpack configs, intended for different kinds of target code (an application or a library), and environments (development or production).
Common for every config variant, the library exposes it as a "config factory function", which generates the actual configuration once called with necessary options. That config can be further customized by the host code, and then passed into Webpack.
For example, one can use the production app config the following way.
In the host codebase the /config/webpack/production.js
file is created:
const { merge } = require('webpack-merge');
const configFactory = require(
'@dr.pogodin/react-utils/config/webpack/app-production',
);
const baseConfig = configFactory({
context: '/path/to/context/folder',
entry: 'relative/path/to/entry/point',
});
module.exports = merge(baseConfig, {
// Additional Webpack config to merge with the base one.
});
Then in the main webpack.config.js
file do:
module.exports = function buildConfig(env) {
const config = require(`./config/webpack/${env}.js`);
// Some additional operations on config may happen here.
return config;
}
Application Config
Base
const configFactory = require('@dr.pogodin/react-utils/config/webpack/app-base');
configFactory(options) => object;
This factory function creates
the base Webpack config for apps, which includes the setup common for both
development and production environments. The options
argument is an object with the following valid fields:
-
Required:
babelEnv
- string - Environment to use for Babel compilation.context
- string - Base URL for relative paths resolution.entry
- string | string[] - Entry point(s) for the "main" chunk(s). Under the hood the config will prepend them by some polyfills, like babel-polyfill, nodelist-foreach-polyfill, etc.mode
- string - Webpack mode.
-
Optional:
-
babelLoaderExclude
— Setsexclude
option forbabel-loader
rule. Defaults to[/node_modules/]
, meaning Babel loader will not act on 3rd-party modules. -
babelLoaderOptions
- object - Overrides default Babel loader options for JSX and SVG files. -
cssLocalIdent
- string - Template for CSS classnames generated by the Webpack'scss-loader
. The value is passed into thelocalIdentName
option of the loader. It should match corresponding option in the Babel config. Defaultshash:base64:6
. -
dontEmitBuildInfo
- boolean - Set true to opt out of writing generated "build info" data to the disk. -
dontUseProgressPlugin
- boolean - Set true to opt out of including the Webpack's ProgressPlugin into the config. This is intended for test scenarious, to avoid polluting test logs with detailed console output from test Webpack builds. -
fs
- object - Alternative filesystem (e.g. memfs) to use instead of the standard Node's filesystem to output artifacts created during the Webpack config generation by the factory (e.g. "build info", etc.). -
publicPath
- string - Public URL of the output directory when referenced in a browser (see Webpack docs for details). The config factory will automatically append/
symbol to the end of given value, thuspublicPath
values should not include it.BEWAREWhen used alongside SSR,
publicPath
value provided into Webpack must match prefixes of asset URLs generated by Babel during SSR. In particular, if you use the standard server-side Babel preset be sure to set itsbaseAssetsOutputPath
to matchpublicPath
. -
keepBuildInfo
- boolean | object - Allows to re-use "build info" data from a previous Webpack build.- If an object is provided, it is used as build info.
- If true value is provided, the factory attempts to read build info
data from the
.build-info
file in the "context" folder of the build, and it falls back to generating from scratch and using a new build info data if.build-info
file cannot be read.
-
outputPath
- string - Output build path, relative to thecontext
. Defaults to "build/web-public
". -
sitemap
- function | string - The path to JS or JSON config for sitemap. It can be relative to the context, and can be a factory, which returns the config. The config should be compatible withsitemap
library library, and if provided the Webpack config factory will use it to gereratesitemap.xml
file in the output folder, and then serve it from the app root.Complex Sitemap SetupIn case a complex sitemap setup is needed (e.g. a runtime sitemap generation, or serving the sitemap from alternative routes, etc.), instead of this option use onExpressSetup option of the server factory to mount a custom sitemap controller implementing necessary sitemap logic on the desired route(s) of created ExpressJS server.
-
typescript
— boolean — Enables TypeScript support. -
workbox
- boolean | object - When set the Workbox's InjectManifest plugin is included into the array of Webpack plugins, and it generates server worker for browser. If the value is an object it is merged into options passed into the plugin, otherwise default options are used:
{
"importWorkboxFrom": "local",
"swSrc": "@dr.pogodin/react-utils/config/workbox/default.js",
"swDest": "__service-worker.js"
}If the service worker is generated by this option, it will be automatically initiated at the client side by the standard client-side initialization script provided by this library.
Note that
swDest
's value cannot be overriden by config options provided viaworkbox
object. -
-
The config factory returns a config object which
-
Bundles font assets (EOF, OTF, SVG, TTF, WOFF, WOFF2 files) from the
src/assets/fonts
folder of source code and emits them into the[PUBLIC_PATH]/fonts
folder. -
Bundles image assets (GIF, JPEG, JPG, PNG files) from any folder of source code and emits them into the
[PUBLIC_PATH]/images
folder. -
Bundle SCSS files from any folder of source code, beside
node_modules
and its subfolders. The files are compiled, bundled, and extracted into[PUBLIC_PATH]/[CHUNK_NAME].css
chunks. -
Bundles CSS files from any folder of source code. The files are bundled and extracted into
[PUBLIC_PATH]/[CHUNK_NAME].css
chunks. -
Aggregates source maps from dependencies, using source-map-loader.
-
Bundles
.cjs
,.js
,.jsx
,.svg
files + iftypescript
option is enabled,.ts
and.tsx
files.All these files are compiled using babel-loader with Babel config for Webpack, and with Babel environment specified in the factory options. The outputs are bundled and emitted into
[PUBLIC_PATH]/[CHUNK_NAME].js
chunks, . -
Automatically configures the following path aliases for the compilation (relative paths starting with these segments are resolved relative to the corresponding folders):
- assets for
[CONTEXT]/src/assets
; - components for
[CONTEXT]/src/shared/components
; - fonts for
[CONTEXT]/src/assets/fonts
; - styles for
[CONTEXT]/src/styles
.
- assets for
-
resolve.symlinks
Webpack option is set false to avoid problems with resolution of assets from packages linked withnpm link
. -
These global variables are automatically eemulated 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 is set *true inside the bundle, so that shared code can use it to determine that it is executed at the client side.
-
The config opts to polyfill the
__dirname
global variable, and to ignore imports of thefs
Node package; -
By default the config factory also generates and emits "build info" data.
Development
const configFactory = require('@dr.pogodin/react-utils/config/webpack/app-development');
configFactory(options) => object;
This factory function creates Webpack configuration for development environment. It accepts the same options as the base app config, and does the same stuff, with the following differences.
-
It accepts additional options:
-
dontUseHmr
- boolean - Set true to opt out of including HMR-specific bits into the generated config. It is intended for test scenarious, where without additional efforts, a code bundled with development config would trigger HMR failure warnings. -
dontUseReactGlobalStateDebugging
- boolean - Set true to opt out of injecting true value intoREACT_GLOBAL_STATE_DEBUG
global variable in development environment. This variable would enable debug logging related to the React Global State, and disabling that is intended for test scenarious, where these debug logs would unnecessary pollute test logs. -
cssExtractionOptions
— object — Optional. Customizes settings of MiniCssExtractPlugin (it emits CSS assets from the build), which is included into the config with the following configuration:{
chunkFilename: '[id].css',
filename: '[id].css',
...ops.cssExtractionOptions,
}
-
-
It also:
- Enforces development Babel environment, and sets its
cssLocalIdent
argument equal[path][name]___[local]___[hash:base64:6]
to generate verbose classnames for CSS modules, which are handy for debug purposes. - Adds
webpack-hot-middleware/client?reload=true
to entrypoints, which is necessary for HMR (Hot Module Reloading) setup. - Emulates the following environment variables:
- BABEL_ENV and NODE_ENV are both set equal development.
- DEV_TOOLS is set equal true.
- REACT_GLOBAL_STATE_DEBUG is set equal true.
- Adds the following plugins:
- HotModuleReplacementPlugin and react-refresh-webpack-plugin (these are required for HMR).
- Enforces development Babel environment, and sets its
Production
const configFactory = require('@dr.pogodin/react-utils/config/webpack/app-production');
configFactory(options) => object;
The factory function creates Webpack configuration for production environment. It accepts the same options as the base app config, and does the same stuff, then on top of that it:
-
Changes default value of
babelLoaderExclude
option to[]
, to ensure that Babel re-compiles all 3rd-party modules, to ensure compatibility of bundled code with requested target environments.It also defaults
compact
option of Babel config to true, to avoid warnings about Babel resetting code layout style of 3rd party modules. -
Accepts additional options:
cssExtractionOptions
— object — Optional. Customizes settings of MiniCssExtractPlugin (it emits CSS assets from the build), which is included into the config with the following configuration:{
chunkFilename: '[contenthash].css',
filename: '[contenthash].css',
...ops.cssExtractionOptions,
}
-
It also:
- Enforces production Babel environment.
- Emulates the following environment variables:
- BABEL_ENV and NODE_ENV are both set equal to production.
- Adds the following plugins:
Build Info
While creating a Webpack config for app builds, the base app config factory generates a "build info" object with the following fields:
-
key
- string - A random 32-bit encryption key.BEWAREThis key is not secure, as it is send to the client side within the JS bundle. During the runtime it is only used to encrypt at the server side, and then decrypt at the client side internal app's config and data injected into the initial HTML markup during SSR. This way we avoid sending these data as plain text within HTML, but apparently anybody having both HTML and JS bundle at hands (e.g. client browser) is able to easily decrypt these data.
-
publicPath
- string - A copy of build'spublicPath
value. -
useServiceWorker
- boolean - A flag indicating whether service worker should be used by the app.
This object is made accessible to the app during the runtime both at the client
side (it is injected into the bundled JS code), and at the server side (see
isomorphy.getBuildInfo()). The config factory writes this
object into the "context" folder of the build, as .build-info
file (it can be
opted out by dontEmitBuildInfo
option of the config factory, also fs
option
can be used to output the file into a virtual filesystem).
The keepBuildInfo
option of the base app config factory
allows to reuse old "build info" data, which is inteded for development and
test scenarious.
- In the library versions v1.17.2 ÷ v1.17.4 the "build info"
object was also exposed via the
.buildInfo
field attached to the standard config factories after each build. This was dropped in v1.17.5 in favour of passing it via a virtual filesystem (seefs
option of the config factory).
Library Config
Base
const configFactory = require('@dr.pogodin/react-utils/config/webpack/lib-base');
configFactory(options) => object;
This factory function creates
base Webpack config for libraries, which contains the core setup common
for development and production library targets.
The options
argument is an object with the following valid fields:
-
Required:
babelEnv
- string - Babel environment.context
- string - Base URL for resolution of relative config paths.entry
- string | string[] - Entry point(s). The config may prepend them by necessary polyfills.library
- string - Library name. It is important for proper resolution of library assets.
-
Optional:
-
babelLoaderOptions
- object - Overrides default Babel options for JSX and SVG loading. -
cssLocalIdent
- string - The template for CSS classnames generated by Webpack'scss-loader
. It should match the corresponding setting in Babel config. Defaults tohash:base64:6
. -
dontUseProgressPlugin
- boolean - Set true to opt out of including the Webpack's ProgressPlugin into the config. This is intended for test scenarious, to avoid polluting test logs with detailed console output from test Webpack builds. -
cssExtractionOptions
— object — Customizes settings of MiniCssExtractPlugin (it emits CSS assets from the build), which is included into the config with the following configuration:{
filename: 'style.css',
...ops.cssExtractionOptions,
} -
mode
- string - Webpack mode. -
outputPath
- string - Build output path. Defaultsbuild
.
-
The generated config does the following:
-
References to font asset (EOF, OTF, SVG, TTF, WOFF, WOFF2) files located in the
src/assets/fonts
folder of the library's source code are rewritten to toLIBRARY_NAME/src/assets/fonts/FILENAME.FILE_EXTENSION
so that the host package of the library is able to find and bundle them. -
Bundle SCSS files from any folder of source code, beside
node_modules
and its subfolders. The files are compiled, bundled and extracted into thebuild/{type}/style.css
chunks. -
Aggregates source maps from dependencies, using source-map-loader.
-
Bundles JS, JSX, and SVG files; they are compiled into
build/{type}/web.bundle.js
chunks, using the Babel environment specified in the factory options, and client-side Babel config. -
Sets The following path aliases (relative paths starting with these segments are resolved relative to the corresponding folders):
- assets for
[CONTEXT]/src/assets
. - components for
[CONTEXT]/src/shared/components
. - fonts for
[CONTEXT]/src/assets/fonts
. - styles for
[CONTEXT]/src/styles
.
- assets for
-
Sets
resolve.symlinks
Webpack option to false to avoid problems with resolution of assets from packages linked withnpm link
. -
Declares the following packages as externals:
@babel/runtime
@dr.pogodin/react-global-state
@dr.pogodin/js-utils
@dr.pogodin/react-themes
@dr.pogodin/react-utils
axios
cookie
dayjs
lodash
node-forge
qs
react
react-dom
react-helmet
react-router-dom
uuid
Development
const configFactory = require('@dr.pogodin/react-utils/config/webpack/lib-development');
configFactory(options) => object;
Extends and tunes the base library config for development
environment. This factory function accepts the same options, and does the same
stuff. On top of that it modifies the template for generated classnames to equal
[path][name]___[local]___[hash:base64:6]
which is handy for debug purposes,
and does some other small modifications of config.
Production
const configFactory = require('@dr.pogodin/react-utils/config/webpack/lib-production');
configFactory(options) => object;
Extends and tunes the base library config for production environment. This factory function accepts the same options, and does all the same stuff, and on top of that slightly modifies the resulting config as required for production needs.