This site runs best with JavaScript enabled.

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

September 20, 2018

Software Development

Beware: Angular CLI 6 makes it impossible to use Moment.js!

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 eject allowed 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:

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

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

1import * as moment from 'moment'
2console.log(moment())

Now run the build and have look at the bundle:

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

You get the following scary picture:

moment_locales

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:

1ng add ngx-build-plus

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

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

And run:

1npm run build -- --prod --stats-json --extra-webpack-config webpack.extra.js
2npx webpack-bundle-analyzer dist/my-project/stats.json

Yay! All the locales have disappeared from the bundle:

moment_no_locales

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?

This post is originally published at jonasbandi.net.

Discuss on TwitterEdit post on GitHub

Share article
Jonas Bandi

Jonas Bandi is an enthusiastic software professional. He is passionate about technology and methodologies - always trying to learn, improve and share knowledge.