get-webpack-config
v1.0.0
Published
Utilities to help you modularize your webpack configs
Downloads
155
Readme
get-webpack-config
Utilities to help you modularize your webpack configs
About get-webpack-config
get-webpack-config
is a set of lightweight utilities to help you modularize your webpack configs.
You can break up your webpack configs into small modular configs that are easier to understand & maintain, and then merge them together for webpack.
It also allows you to have optional settings that can be passed in to each config, allowing you to update the configs independently of the settings.
The other key feature is that because the configs are completely modularized, you can add or remove them easily, without fear of it affecting the rest of your webpack config.
get-webpack-config example
Here's an example of how you might use get-webpack-config
, this is a complete webpack config file for a real-world webpack.dev.js
config:
// webpack.dev.js
// developmental build config
// environment
process.env.NODE_ENV = process.env.NODE_ENV || 'development';
// webpack config file helpers
const { modernWebpackConfigs } = require('get-webpack-config');
// development module exports
module.exports = modernWebpackConfigs(
'app',
'dev-server',
'manifest',
'babel-loader',
'image-loader',
'font-loader',
'postcss-loader',
'typescript-loader',
'vue-loader',
);
You'd run it just as you'd run any webpack build, e.g.:
webpack serve --config webpack.dev.js
This would look for webpack configs in the default webpack-configs/
directory given names, with .config.js
appended to them.
It will also look for corresponding settings in the default webpack-settings/
directory, and pass them in to each config.
Then using webpack-merge, it merges the configs together, and passes them back to webpack.
Here's an example of what the directory structure would look like, with each .config.js
and optional .settings.js
file:
├── package.json
├── package-lock.json
├── webpack.dev.js
├── webpack-configs
│ ├── app.config.js
│ ├── babel-loader.config.js
│ ├── dev-server.config.js
│ ├── font-loader.config.js
│ ├── image-loader.config.js
│ ├── manifest.config.js
│ ├── postcss-loader.config.js
│ ├── typescript-loader.config.js
│ └── vue-loader.config.js
└── webpack-settings
├── app.settings.js
├── babel-loader.settings.js
├── dev-server.settings.js
├── manifest.settings.js
└── typescript-loader.settings.js
webpack-configs
A webpack config for get-webpack-config
is exactly the same as any webpack config: it's a .js
file that returns a webpack configuration object.
The webpack config is passed in the type
of build (either modern
or legacy
), and a settings
object. Modern builds are intended for modern browsers, and legacy builds are intended for legacy browsers, using the module/nomodule pattern
Here's an example of an empty example config:
// example.config.js
// returns a webpack config object for the example config
// return a webpack config
module.exports = (type = 'modern', settings) => {
// common config
const common = () => ({
});
// configs
const configs = {
// development configs
development: {
// legacy development config
legacy: {
},
// modern development config
modern: {
...common(),
},
},
// production configs
production: {
// legacy production config
legacy: {
...common(),
},
// modern production config
modern: {
...common(),
},
}
};
return configs[process.env.NODE_ENV][type];
}
Note that the above is just a convention, all the default export needs to do is return a webpack config object.
Following this convention, though, allows you to easily create webpack configs that are different depending on their type
and whether it's a development or production build.
The common()
function contains a common webpack config that's spread into the actual configs, then each specific config can add in whatever makes it unique.
N.B.: The development
/legacy
config combo is empty, because it's rare to want to use legacy builds in a HMR development environment.
webpack-settings
The .settings.js
files are just JavaScript modules that export an object of config settings.
Here's an example:
// example.settings.js
// node modules
require('dotenv').config();
// settings
module.exports = {
foo: 'bar',
};
We're require()
'ing the optional dotenv package because it's common to want to override settings from .env
files.
All you actually need to do is ensure that the default export returns an object of settings that your config can use.
The settings are kept separate from the config files so that webpack configs can be updated independent of the settings that affect them.
There is a special settings file app.settings.js
that is merged with all other settings files, so you can put global settings in there.
Exported functions
For all of the functions below, whether to return a production or development config is based on process.env.NODE_ENV
.
modernWebpackConfigs(configName, ...)
This function takes an arbitrary number of config names as arguments, and returns a merged webpack config from them all.
It ends up calling getModernWebpackConfig()
on each argument, to return the modern version of the config.
legacyWebpackConfigs(configName, ...)
This function takes an arbitrary number of config names as arguments, and returns a merged webpack config from them all.
It ends up calling getLegacyWebpackConfig()
on each argument, to return the legacy version of the config.
buildWebpackConfigs(configName, ...)
This function takes an arbitrary number of config names as arguments, and returns a merged webpack config from them all.
It ends up calling getModernWebpackConfig()
on each argument, to return the modern version of the config.
This function exists just as a way to logically separate out any webpack tasks that are not related to either the modern or legacy builds, such as "clean" or "copy" tasks.
getModernWebpackConfig(configName)
This function returns a single webpack config, by passing in the corresponding .settings.js
to it (if any) and returning the results.
It appends .config.js
to configName
to determine the name of the config to load.
It returns the modern version of the config.
getLegacyWebpackConfig(configName)
This function returns a single webpack config, by passing in the corresponding .settings.js
to it (if any) and returning the results.
It appends .config.js
to configName
to determine the name of the config to load.
It returns the legacy version of the config.
getWebpackSettings(settingsName)
This function returns a settings object for the passed in settingsName
.
It appends .settings.js
to configName
to determine the name of the settings to load.
Environment variables
The following environment variables allow you to override defaults in get-webpack-config
:
GET_WEBPACK_CONFIG_BASE_CONFIG_NAME
- the name of the global base settings file that should be merged into any webpack config specific settings. Default:app
GET_WEBPACK_CONFIG_SETTINGS_PATH
- The fully qualified path to the directory where the webpack configs are. Default:./webpack-configs
GET_WEBPACK_CONFIG_CONFIGS_PATH
- The fully qualified path to the directory where the webpack settings are. Default:./webpack-settings
webpack Multi-compiler example
Any webpack config file can return an object, which is a single webpack compiler. Or it can return an array of webpack objects, which is called a multi-compiler.
We leverage this to break up our builds into separate configs for modern
, legacy
, and build
webpack compiles.
Here's an example of a complete real-world webpack.prod.js
config file that uses the get-webpack-config
functions for a nice clean, semantically readable config:
// webpack.prod.js
// production build config
// environment
process.env.NODE_ENV = process.env.NODE_ENV || 'production';
// webpack config file helpers
const { buildWebpackConfigs, legacyWebpackConfigs, modernWebpackConfigs } = require('get-webpack-config');
// production multi-compiler module exports
module.exports = [
legacyWebpackConfigs(
'app',
'production',
'critical',
'manifest',
'babel-loader',
'image-loader',
'font-loader',
'postcss-loader',
'typescript-loader',
'vue-loader',
'banner',
'compression',
'bundle-analyzer',
),
modernWebpackConfigs(
'app',
'production',
'manifest',
'babel-loader',
'image-loader',
'imagemin-webp',
'font-loader',
'postcss-loader',
'typescript-loader',
'vue-loader',
'banner',
'compression',
'bundle-analyzer',
'workbox',
),
buildWebpackConfigs(
'build',
'clean',
'copy',
'favicons',
'create-symlink',
'save-remote-file',
),
];
You may have simpler needs than this, but it's easy to just remove the bits you don't need by just deleting a single line.