Angular CLI: Custom webpack Config

Paul Halliday

The Angular CLI gives us all sorts of power. One of these powers is the ability to forget about the webpack configuration process. This is great for most applications, but what if you want to add custom webpack functionality? This article looks at how we can achieve just that.

🐊 Alligator.io recommends

Our recommended Angular courses

📺 Watch a Video

Here’s a video I recorded that explains the content of this post:

New Angular Application

To establish a common base, we’ll create a new Angular application with the Angular CLI:

# Install the Angular CLI globally
$ npm i @angular/cli -g

# Create a new Angular project with a name of your choosing && change directory
$ ng new AngularCustomWebpackConfig

> N
> SCSS

$ cd AngularCustomWebpackConfig

# Open this up in VS Code and Serve
$ code . && ng serve

A common dependency to many projects is the date library - moment.js. This includes the ability to work with locales, but, it adds quite a bit to the overall bundle size.

Thankfully - there’s a webpack plugin which removes unnecessary locales. We’ll be using it in this project.

Dependencies

In order to use a custom webpack config, we’ll need the @angular-builders/custom-webpack dependency. Add it to your project as a devDependency like so:

$ npm i @angular-builders/custom-webpack -D

We can then install moment to our project and import this into our project:

$ npm i moment --save

Custom webpack Configuration

We can then create a custom webpack configuration that rips out any locales that we don’t specifically choose to keep.

Inside of the root of your project, create a new file named custom-webpack.config.js with the following:

const MomentLocalesPlugin = require('moment-locales-webpack-plugin');

module.exports = {
  plugins: [
    new MomentLocalesPlugin({
      localesToKeep: ['fr']
    })
  ]
};

This requires us to install the moment-locales-webpack-plugin:

$ npm i moment-locales-webpack-plugin -D

Adding this to angular.json

Afterwards, we need to configure angular.json to use this new configuration. Inside of the architect/build object, update the builder from @angular-devkit/build-angular:browser to @angular-builders/custom-webpack:browser and add the customWebpackConfig key:

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

Custom webpack Configuration When Using ng serve

This is all we need to do if we only want our final, built, application to use the webpack config. However, if we wanted to test this config while using ng serve, we have one more thing to do.

Install the @angular-builders/dev-server custom web server from within npm:

$ npm i @angular-builders/dev-server -D

We can then update this inside of serve/builder in the angular.json file:

"serve": {
  "builder": "@angular-builders/dev-server:generic"
}

Testing

Let’s check to see whether this works as intended! Head over to app.component.ts and set the locale to fr

import { Component, OnInit } from '@angular/core';

import * as moment from 'moment'

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  currentTimeFRLocale: string;

  ngOnInit(): void {
    moment.locale('fr');
    this.currentTimeFRLocale = moment().format('LLL');
  }
}

Then we can display this inside of app.component.html:

<h1></h1>

Angular Locale: FR

Great. We’re able to see the current date and time with the fr locale, as we’ve specifically told moment to keep this with the plugin.

Let’s remove this from the custom-webpack.config.js and select a different locale:

module.exports = {
  plugins: [
    new MomentLocalesPlugin({
      localesToKeep: ['de']
    })
  ]
};

You’ll need to restart the application with ng serve for the application to update.

Angular Locale: DE

The locale has disappeared from the bundle! You’ll also notice that the bundle size is significantly smaller with this extra configuration than without.

Here’s the results without the configuration:

chunk {main} main.js, main.js.map (main) 22.6 kB [initial] [rendered]

Here’s the results with the configuration:

chunk {main} main.js, main.js.map (main) 10.2 kB [initial] [rendered]
  Tweet It

🕵 Search Results

🔎 Searching...

Sponsored by #native_company# — Learn More
#native_title# #native_desc#
#native_cta#