17

In my angular 5 application, when I create build using

ng build --prod --sm

and open source map explorer, moment takes lot of space in the main.js file. I have found all the locales gets loaded when I use

import * as moment from 'moment';

I have used material-moment-adapter to some functionality in the application that requires the moment package also.

I have created the application using angular-cli. I have found many links that excludes locales using settings in webpack.config.js Is there any way to exclude locales using angular-cli ?

Shikha
  • 551
  • 5
  • 20

8 Answers8

13

This article describe good solution: https://medium.jonasbandi.net/angular-cli-and-moment-js-a-recipe-for-disaster-and-how-to-fix-it-163a79180173

Briefly:

  1. ng add ngx-build-plus

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

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

    npm run build --prod --extra-webpack-config webpack.extra.js
    

Warning moment.js has been deprecated officially https://momentjs.com/docs/#/-project-status/ (try use day.js or luxon)

Dmitriy Ivanko
  • 950
  • 8
  • 17
5

If you don't want to use any third party libraries the simplest way to do this is to add the following in compilerOptions of your tsconfig.json file

"paths": {
  "moment": [
    "../node_modules/moment/min/moment.min.js"
  ]
}
Zeeshan Adnan
  • 769
  • 6
  • 10
4

For anyone on angular 12 or latest

This does not work for me

const webpack = require('webpack');

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

However this does

const webpack = require('webpack');

module.exports = {
  plugins: [
    new webpack.IgnorePlugin({
      resourceRegExp: /^\.\/locale$/,
      contextRegExp: /moment$/
    })
  ]
};
el-davo
  • 223
  • 6
  • 10
2

There is another solution in this Angular Issue: https://github.com/angular/angular-cli/issues/6137#issuecomment-387708972

Add a custom path with the name "moment" so it is by default resolved to the JS file you want:

"compilerOptions": {
    "paths": {
      "moment": [
        "./node_modules/moment/min/moment.min.js"
      ]
    }
}
Daniel
  • 21,933
  • 14
  • 72
  • 101
0

In Angular 12, I did the following:

npm i --save-dev @angular-builders/custom-webpack

to allow using a custom webpack configuration.

npm i --save-dev moment-locales-webpack-plugin
npm i --save-dev moment-timezone-data-webpack-plugin

Then modify your angular.json as follows:

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

and in the extra-webpack.config.js file:

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

module.exports = {
    plugins: [
        new MomentLocalesPlugin({
            localesToKeep: ['en-ie']
        }),
        new MomentTimezoneDataPlugin({
            matchZones: /Europe\/(Belfast|London|Paris|Athens)/,
            startYear: 1950,
            endYear: 2050,
        }),
    ]
};

Modify the above options as needed, of course. This gives you far better control on which exact locales and timezones to include, as opposed to the regular expression that I see in some other answers.

AsGoodAsItGets
  • 2,886
  • 34
  • 49
0

the solutions above didn't work for me because they address the wrong path (don't use ../ ) in the tsconfig.app.json

{
...
   "compilerOptions": {
      "paths": {
        "moment": [
          "node_modules/moment/min/moment.min.js"
        ]
      }
   }
}

Works for me in Angular 12.2.X. The changes must be done in the tsconfig.app.json, than also the type information of your IDE will work. enter image description here

enter image description here

Don't change it in the tsconfig.json or your IDE will lose type information. enter image description here

This fix the usage in the app as in the lib. I used source-map-explorer to verify it.

ng build --sourceMap=true --namedChunks=true --configuration production && source-map-explorer dist/**/*.js

enter image description here

yLoeffler
  • 11
  • 2
0

I had the same problem with momentjs library and solve it as below:

The main purpose of this answer is not to use IgnorePlugin for ignoring the library but I use ContextReplacementPlugin to tell the compiler which locale files I want to use in this project.

  1. Do all of the configurations mentioned in this answer: https://stackoverflow.com/a/72423671/6666348

  2. Then in your webpack.config.js file write this:

    const webpack = require("webpack");
    
    module.exports = {
        plugins: [
            new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /(en|fr)$/)
        ]
    };
    

This configuration will add only en and fr locale in your application dist folder.

Kamran Taghaddos
  • 452
  • 1
  • 10
  • 22
0

You can try to use moment-mini-ts instead of moment

npm i moment-mini-ts

import * as moment from 'moment-mini-ts'

Don’t forget to uninstall moment

npm uninstall moment 

I’m using angular 9

Suraj Rao
  • 29,388
  • 11
  • 94
  • 103