ngx-build-plus
allows us to ...- ?️ modify the ? CLI's build process by providing a partial webpack config
- ? modify the ? CLI's bahavior by providing ngx-build-plus plugins (node scripts)
- ➕ can be easily install by using
ng add ngx-build-plus
which automatically registers the solution in yourangular.json
.
The CLI does a myriad of things for us. Especially the provided build process is quite sophisticated and provides a lot of optimizations out of the box.
However, sometimes we want to extend its default behavior to address respective requirements in our projects. For this, we could eject from the CLI using ng eject
in the past. However, after ejecting, one was not able to use the CLI for the build process anymore, which is one of the reasons it's not supported since CLI 6.
In this article I provide a solution for this, which even seems to have some benefits over ejecting. The example used for this can be found in my GitHub repo.
How ngx-build-plus can help
To provide an easy way for extending the CLI's build steps, I've written ngx-build-plus. It inherits from the default webpack-based builder and hence mirrors the CLI's default behavior. In addition it allows you to do two things:
- Providing a partial webpack config which is merged with the CLI's one.
- Providing a simple javascript file (aka a plugin) which modifies the existing webpack configuration dynamically.
In addition, it also gives you an --single-bundle
switch for ng build
, which -- well -- puts the applications code into one single bundle. This is especially useful for Web Components/ custom elements build with Angular Elements.
Getting started with ngx-build-plus
If you're using Angular and CLI 7, just install ngx-build-plus
using ng add
:
ng add ngx-build-plus
If you have several projects in your CLI workspace, use the --project
switch to point to the project in question:
ng add ngx-build-plus --project getting-started
After this, you can provide a custom partial webpack config. I've put it in my project's root and called it webpack.extra.js
:
const webpack = require('webpack');
module.exports = {
plugins: [
new webpack.BannerPlugin('----- Manfred was here -----')
]
}
To keep things simple, this example just uses the BannerPlugin
which adds a comment at the top of each bundle.
To use the partial webpack config for your build process, call ng build
with the --extra-webpack-config
switch provided by ngx-build-plus
:
ng build --extra-webpack-config webpack.extra.js
Once again, if your CLI workspace contains several projects, also mention the project to build:
ng build --extra-webpack-config webpack.extra.js --project getting-started
After this, you'll see the added comment in the first lines of the generated bundles:
In order to automate this command, it seems to be a good idea to define a npm script.
Writing a plugin
Sometimes, just providing a custom webpack config is not enough. In those situations you have to modify some parts of the default configuration. For this, ng-build-plus
allows you to define a plugin.
Basically, such a plugin is just a javascript file exporting an object with three methods:
exports.default = {
pre: function() {
},
config: function(cfg) {
var time = new Date().getTime();
var pattern = 'getting-started.[name].' + time + '.js';
cfg.output.filename = pattern;
return cfg;
},
post: function() {
}
}
In my example I put this file into the project's root and I called it plugin.js
.
As you might imagine, the pre
method is executed at the beginning of the build chain and the post
method is called at the end. The config
method is called after pre
and gets the CLI's default webpack config. Here, you have the chance to modify it.
In this simple example, config just modifies the name of the bundles.
When calling ng build
, you can point to your plugin:
ng build --plugin ~plugin.js
The ~
means, that you want to use a local file. Without this character, ngx-build-plus
assumes that the provided name is the name of an installed npm package.
After this, you should see the new bundle names:
Once again, automating this command with a npm script seems to be a good idea.
A more sophisticated example for a plugin is my side project ngx-build-modern. It creates two sets of bundles: An ES5-based one for legacy browsers (IE) and an ES2015-based one for modern browsers. The latter one is more optimized and does not provide all the polyfills. Also, it provides an index.html
which loads the right set of bundles for your current browser.