epelc epelc - 1 month ago 429
Javascript Question

How to prevent moment.js from loading locales with webpack?

Hello is there anyway you can stop moment.js from loading all the locales(I just need english) when your using webpack? I'm looking at the source it seems that if hasModule is defined which it is for webpack then it always tries to require() every locale. I'm pretty sure this needs pull request to fix. But is there anyway we can fix this with a webpack config.

Here is my webpack config to load momentjs

resolve: {
alias: {
moment: path.join(__dirname, "src/lib/bower/moment/moment.js")
},
},


Then anywhere I need it I just do require('moment') this works but its adding about 250kb of unneeded language files to my bundle. Also I'm using the bower version of momentjs and gulp.

Also if this can't be fixed by a webpack config here is a link to the function where it loads the locales https://github.com/moment/moment/blob/develop/moment.js#L760-L772 I tried adding "&& module.exports.loadLocales" to the if statement but I guesse webpack doesnt acaully work in a way where that would work it just requires no matter what I think it uses a regex now so I don't really know how you would even go about fixing it. Anyways thanks for any help.

Answer

The code require('./locale/' + name) can use every file in the locale dir. So webpack includes every file as module in your bundle. It cannot know which language you are using.

There are two plugins that are useful to give webpack more information about which module should be included in your bundle: ContextReplacementPlugin and IgnorePlugin.

require('./locale/' + name) is called a context (a require which contains an expression). webpack infers some information from this code fragment: A directory and a regular expression. Here: directory = ".../moment/locale" regular expression = /^.*$/. So by default every file in the locale directory is included.

The ContextReplacementPlugin allows to override the inferred information. I. e. provide a new regular expression (to choose the languages you want to include).

Another approach is to ignore the require with the IgnorePlugin.

Here is an example:

var webpack = require("webpack");
module.exports = {
  // ...
  plugins: [
    new webpack.ContextReplacementPlugin(/moment[\/\\]locale$/, /de|fr|hu/)
    // new webpack.IgnorePlugin(/^\.\/locale$/, /moment$/)
  ]
};