Angular CLI and Moment.js: A recipe for disaster … and how to fix it.

Jonas Bandi
reality-loop
Published in
4 min readSep 19, 2018

--

When I wrote about “To use Angular CLI or not?”, I claimed that there was not much risk involved in starting a project with Angular CLI, since ng ejectallowed you to change your mind later and jump to a vanilla Webpack setup.

This has changed since AngularCLI 6: the eject command is now disabled.

Relying on Angular CLI has just become a much bigger risk for your project.

When I wrote about “Angular vs. React: The CLI” I claimed that I have not yet had a mandatory reason to eject. In the meantime I have come across several cases where the is a need to modify the webpack config of an Angular CLI project, which could be achieved witheject … but not any more.

One reasons is an integration with three.js. Many three.js extension rely on the global variable THREE. The typical solution in a webpack build is to expose THREE globally via webpack config… bad luck, with Angular CLI v6 you don’t have that option any more.
Other solutions are much more hacky

Another nasty example where you typically need access to the webpack configuration is when you want to use the popular library Moment.js.

Let me illustrate the problem:

npx @angular/cli@6.1 new my-project
cd my-project
npm i moment @types/moment

Now use Moment.js in your project, i.e. in main.ts :

import * as moment from 'moment'
console.log(moment());

Now run the build and have look at the bundle:

npm run build -- --prod --stats-json
npx webpack-bundle-analyzer dist/my-project/stats.json

You get the following scary picture:

The main bundle of your application has a size of 498 KB of which Moment.js is 329 KB! The biggest part of Moment.js consists of a bunch of locales, which you most probably do not need!

Of course this is a shortcoming of Moment.js in combination with webpack. This is not inherently a problem of the Angular CLI. However Moment.js is a very popular library, many Angular projects want/need to use it. Maybe only because some other library depends on Moment.js (many do!).

There is an easy fix for the problem: how-to-optimize-momentjs-with-webpack.
However you need to modify the webpack config… which is not possible in a plain Angular CLI project! Bummer!

The answer of the Angular CLI is: that this is unfortunate, but they can’t deal with such special cases… bummer again!
Note: create-react-app accepts that Moment.js, as a very common library, deserves special handling and solves the problem out of the box.

At this point your project has a problem…

Of course the JavaScript ecosystem has a solution for everything:

… but I don’t like that a “state-of-the-art” framework forces me into hacks like this.

A solution (sort of …)

With ngx-build-plus you can change the webpack configuration in an Angular CLI project without ejecting.

(Note: The section below was updated on 2018–12–29 for Angular CLI 7.1.4)

In the example from above you can do the following:

ng add ngx-build-plus

Add a file webpack.extra.js in the root of your project:

const webpack = require('webpack');module.exports = {
plugins: [
new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/),
]
}

And run:

npm run build -- --prod --stats-json --extra-webpack-config webpack.extra.jsnpx webpack-bundle-analyzer dist/my-project/stats.json

Yay! All the locales have disappeared from the bundle:

You have now solved the problem! … But did you consider the price of the solution?

At best I can congratulate someone for quickly and simply solving a problem on top of the shit that they are given. The only software that I like is one that I can easily understand and solves my problems.
- Ryan Dahl on Software

Yup, ngx-build-plus is yet another “arcane” library you now depend on. Are you prepared to maintain that library yourself?

For Angular CLI v7.1.4 using ngx-build-plus is a working solution.

… but ngx-build-plus is was broken for Angular CLI 6.2:

… bummer!

Note: There are other projects similar to ngx-build-plus, maybe they make you happy:

https://github.com/meltedspark/angular-cli-builders
https://github.com/Angular-RU/angular-cli-webpack

The source code for the above example is available here: https://github.com/jbandi/ng-moment-problem

--

--