paxter v0.1.2
Paxter
Paxter is a middleware system for Webpack configuration. It aims to move Webpack configuration into the convention-over-configuration mindset, making it easier to get up and running with a new Webpack-based project while still allowing complete customization of your Webpack config.
Let's face it: Webpack configuration sucks. Configuration files can become huge and unwieldy even for typical technology stacks. Wouldn't it be great if there were a way to automatically detect the languages, frameworks, and libraries you are using, and begin with typical configurations?
This is what Paxter does. Paxter sets the groundwork for middleware to modify the Webpack configuration object with sensible defaults.
Usage
$ npm install -D paxter
The only thing you need to do is use a call to paxter()
as your Webpack configuration, and then npm install
whatever
middlewares you need for your project:
// webpack.config.json:
const paxter = require('paxter');
module.exports = paxter();
Now, install your middleware (i.e. any package beginning with paxter-
):
$ npm install -D paxter-babel-env paxter-sass paxter-pug
That's it! Webpack will now know what to do with ES6, SASS, and Pug files, with no additional configuration required.
Middleware configuration
Middlewares can be customized with further configuration if necessary. The first parameter to paxter()
provides
configuration to each middleware:
module.exports = paxter({
"babel-env": {
target: "node 6"
}
});
The object's keys must match the middleware's name (minus the package-
prefix). Each middleware defines its own
configuration format. See the middleware documentation for details.
A value of false
will disable that middleware.
Starter Webpack configuration object
To provide a starter Webpack configuration (an object that Paxter middlewares will modify, instead of creating a new
one), pass it as the second parameter to the paxter()
method:
module.exports = paxter(
{ /* Paxter configuration */ },
{
entry: "...",
output: { /* ... */ },
module: {
rules: [ /* ... */ ]
}
}
);
Values provided in the starter configuration will be overwritten (middlewares are encouraged to use a "merge" strategy to not completely overwrite configurations, but this is not guaranteed. See your middleware for details).
Further configuration modifications
Because paxter()
simply returns a configuration object, you are free to continue modifying it before it is exported.
Paxter provides several utility methods that make configuration modifications easier:
paxter.get
paxter.get(config, path)
Gets the value at
path
of theconfig
object.const paxter = require('paxter'); const config = paxter(); const hints = paxter.get(config, 'performance.hints');
Paxter uses the
_.get
method provided by lodash (see https://lodash.com/docs#merge for details).
paxter.set
paxter.set(config, path, value)
Sets the value at
path
of theconfig
object. Thevalue
will completely overwrite the current value atpath
(as opposed topaxter.merge
).const paxter = require('paxter'); const config = paxter(); paxter.set(config, 'performance.hints', 'warning');
The config object will be modified directly. The modified config value will also be returned.
Paxter uses the
_.set
method provided by lodash (see https://lodash.com/docs#merge for details).
paxter.push
paxter.push(config, path, value)
Pushes
value
onto the array atpath
of theconfig
object. If there is no array atpath
, one will be created.const paxter = require('paxter'); const config = paxter(); paxter.push(config, 'performance.hints', 'warning');
paxter.unshift
paxter.push(config, path, value)
Same as
paxter.push
, except it adds thevalue
to the beginning of the array.
paxter.merge
paxter.merge(config, path, value)
Merges
value
into theconfig
property specified bypath
.const paxter = require('paxter'); const config = paxter(); paxter.merge(config, 'performance', { hints: "warning", maxAssetSize: 200000 }); // If `config` already had a `performance` property with other values, they will be preserved. module.exports = config;
Paxter uses the
_.merge
method provided by lodash (see https://lodash.com/docs#merge for details).
module.rules
modifications
Because a Webpack configuration's module.rules
property can be especially difficult to work with (it may not be easy
to know which rules entry to modify), Paxter provides a more convenient way to modify the module.rules
property.
The third parameter to paxter()
is a callback function that will receive the middleware-modified configuration
object. This object will be a standard Webpack configuration object, however the configuration's module.rules
property will be an object (instead of an array), with each key corresponding to the name of the middleware that
created it. You can modify this object in any way, including with the utility methods mentioned above, as long as the
return object is a valid Webpack configuration.
const paxter = require('paxter');
module.exports = paxter(
{ /* starter configuration */ },
{ /* middleware configuration */ },
config => {
paxter.set(config, 'module.rules.sass.test', /\.s[ca]ss$/);
return config;
}
);
Developing middleware
Paxter middlewares are public npmjs.org node modules named with the prefix paxter-
. Middleware modules must export a
function that returns a Webpack configuration object. The function will receive the current Webpack config object
(which may be an empty object {}
), which it may modify in any way as long as the function's return value is a valid
Webpack configuration.
The only exception to this is the module.rules
property, which Paxter treats as an object instead of an array.
This object's keys are middleware package names (minus the paxter-
prefix), and the values are the module.rules
entries. Your middleware may add its own entry to this object, using your package's name as the key, or you may modify
entries of other packages (but play nice!). You may use an array to create multiple rule entry objects (arrays will be
recursively flattened).
The method also accepts a second options
parameter, with the middleware options that were provided by the user in the
call to paxter()
. This value only contains the options specified for your middleware package. The third allOptions
parameter provides all middleware options.
You can access the current Webpack 4 "mode" (development
or production
) using the paxter.mode
property.
Paxter middleware packages should specify a peerDependency on paxter
.
Example
// paxter-my-middleware/index.js:
let paxter = require('paxter');
module.exports = function(config, options) {
// Modify the config in some way:
config.target = 'web';
// Modify the module rules as an object:
config.module.rules['my-middleware'] = {
test: /\.ext$/,
loader: "some-loader"
};
// Or, use an array of module rules:
config.module.rules['my-middleware'] = [
{ /* rule */ },
{ /* rule */ },
];
// Do something different in development
config.output === 'development' ? 'dev-output.js' : 'output.js';
return config;
}
License
MIT
Contributing
Please file a bug or make a pull request to contribute to Paxter core libraries.
To create a Paxter middleware, just create your own project and publish it using paxter-
as the package name prefix.