Shikha
Shikha

Reputation: 551

How to exclude moment locales from angular build?

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 ?

Upvotes: 17

Views: 10735

Answers (8)

Dmitriy Ivanko
Dmitriy Ivanko

Reputation: 1075

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)

Upvotes: 13

Marina Osama
Marina Osama

Reputation: 61

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

Upvotes: 0

Kamran Taghaddos
Kamran Taghaddos

Reputation: 614

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.

Upvotes: 0

yLoeffler
yLoeffler

Reputation: 31

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

Upvotes: 0

AsGoodAsItGets
AsGoodAsItGets

Reputation: 3181

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.

Upvotes: 0

el-davo
el-davo

Reputation: 459

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$/
    })
  ]
};

Upvotes: 5

DWilches
DWilches

Reputation: 23065

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"
      ]
    }
}

Upvotes: 2

Zeeshan Adnan
Zeeshan Adnan

Reputation: 829

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"
  ]
}

Upvotes: 5

Related Questions