# Customizing Angular CLI build

Published 2021-06-30 · https://www.justjeb.com/post/customizing-angular-cli-build

Simple ng build is not enough? Need to customize the underlying webpack config? Learn how to do this using the custom webpack builder.

An alternative to **ng eject**

So, your Angular CLI project just went a bit beyond a TODO app and you have to customize your build configuration.

The question is, how?

## Angular CLI 1.x ng eject VS Angular CLI builders

In Angular CLI 1.x up to Angular 5 you had the **ng eject** command for this, which was ejecting the whole underlying Webpack configuration and allowing you to modify it as you please.

In Angular CLI 6 this command has been removed and it is not coming back. Instead Angular CLI exposes an API for developers allowing them to hook into the build process by providing their own [builders](https://www.justjeb.com/post/angular-cli-under-the-hood-builders-demystified). With the new Angular CLI you can customize the build process by defining your own builders as well as using any of the builders provided by the community.

## Extending underlying Webpack config

So let’s go ahead and customize our build by extending the underlying Webpack configuration:

- Install @angular-builders/custom-webpack: `npm i -D @angular-builders/custom-webpack`

- In **angular.json** change the **@angular-devkit/build-angular:browser** builder to **@angular-builders/custom-webpack:browser**:

```json
"architect": {
   ...
  "build": {
      "builder": "@angular-builders/custom-webpack:browser",
      "options": {
            ...
      }
  ...
}
```

- If you build a universal app and would like to modify your server build configuration use **@angular-builders/custom-webpack:server** instead of **@angular-builders/custom-webpack:browser**

- Add **customWebpackConfig** to the **build** target options:

```json
"architect": {
   ...
  "build": {
      "builder": "@angular-builders/custom-webpack:browser",
      "options": {
            "customWebpackConfig": {
               "path": "./extra-webpack.config.js"
            }  
            ...
      }
  ...
}
```

Check out the full description of **customWebpackConfig** object [here](https://github.com/just-jeb/angular-builders/tree/master/packages/custom-webpack#custom-webpack-config-object).

- Create **extra-webpack.config.js** in the root of your application (or whatever path you have specified in **angular.json**).

- Fill in the extra configuration required (plain Webpack configuration).

- Note that in contrary to **ng eject** this configuration will be *merged* with the default Angular build configuration so you only have to configure the part you want to change/add. For example, if you want to add another Webpack loader, your Webpack config will look like this:

```js
module.exports = {
  module: {
    rules: [
      {
        test: /\.cool$/,
        use: 'cool-loader'
      }
    ]
  }
};
```

- Run **ng build**

## Advanced Webpack config

There are use cases when just merging the delta of Webpack config is not enough. If it’s just a matter of multiple configurations (use one build config for development and another for staging etc.) you can keep these configurations in separate files and utilize the [configurations](https://angular.dev/reference/configs/workspace-config#alternate-build-configurations) option of [build target](https://angular.dev/reference/configs/workspace-config#build-target).

However, sometimes it’s still not enough. When you have a complicated logic for modifying your build configuration you can export a function from **custom-webpack.config.js** rather than exporting an object. The function receives base Webpack config and the builder options as parameters and returns a modified config. No merge performed. For example:

```js
const webpack = require('webpack');
const pkg = require('./package.json');

module.exports = (config, options) => {
  config.plugins.push(
    new webpack.DefinePlugin({
      'APP_VERSION': JSON.stringify(pkg.version),
    }),
  );

  return config;
};
```

## Modifying index.html

Since Angular CLI 8 **index.html** is not generated as part of Webpack build. This means that you cannot modify **index.html** by modifying Webpack config. Instead you should use [indexTransform](https://github.com/just-jeb/angular-builders/blob/master/packages/custom-webpack/README.md#index-transform) option. This option allows you to provide a function that transforms **index.html** (either synchronously or not).

This is what you have to do:

- Install @angular-builders/custom-webpack (≥8.1.0 required): `npm i -D @angular-builders/custom-webpack`

- Create a file **index-html-transform.js** in the root of your application (or whatever path you have specified in **angular.json**)

- Export a transform function from the file like this:

```js
module.exports = async (targetOptions, indexHtmlContent) => {
    //your transformation here
    return newIndexHtmlContent;
}
```

*Note that it doesn’t have to be async.*

- Modify the builder entry and add **indexTransform** option in angular.json:

```json
"architect": {
   ...
  "build": {
      "builder": "@angular-builders/custom-webpack:browser",
      "options": {
            "indexTransform": "./index-html-transform.js"
            ...
      }
  ...
}
```

- Run **ng build**

## And what about ng serve?

Just replace **@angular-devkit/build-angular:dev-server** inside the serve target with [@angular-builders/custom-webpack:dev-server](https://github.com/just-jeb/angular-builders/blob/master/packages/custom-webpack/README.md#custom-webpack-dev-server). Now when you run **ng serve** the build will use the config you’ve specified in **build** target.

*Note that it is necessary to change the build in the* ***build*** *target to* ***@angular-builders/custom-webpack****, otherwise the custom config won't be applied to the dev server.*

## Additional sources

- Check out this example project which uses **customWebpackConfig** as well as **indexTransform**.

- Another example that leverages the power of custom-webpack builder to build Angular Electron app with Native Node Addons.

## What is next

In the [next article](https://www.justjeb.com/post/angular-cli-under-the-hood-builders-demystified) we will learn how to create your own builder.
