如何防止Moment.js使用Webpack加载语言环境?


199

moment.js使用webpack时,有什么方法可以阻止加载所有语言环境(我只需要英语)?我正在查看源代码,似乎如果hasModule为webpack定义了它,那么它将始终尝试require()每个语言环境。我很确定这需要一个拉取请求来解决。但是,有什么办法可以通过webpack配置修复此问题?

这是我的webpack配置以加载momentjs:

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

然后,只要我需要它,我就可以做require('moment')。这可以工作,但是会在我的捆绑包中添加约250 kB的不需要的语言文件。另外我正在使用momentjs和gulp的凉亭版本。

另外,如果webpack配置无法解决此问题,则这里是指向加载语言环境的函数的链接。我尝试&& module.exports.loadLocalesif语句中添加内容,但我想webpack实际上无法正常工作。它只是require没什么不管是什么。我认为它现在使用了正则表达式,所以我真的不知道您什至会去修复它。


您是否尝试使用moment via nmp代替bower
2014年

我对所有客户端库都使用bower,对所有构建工具都使用npm。由于我的项目布置方式,我想保持这种状态。另外,如果您查看github.com/moment/moment/issues/1866的最后答复,我已经解决了自己的问题,但需要进行少量源代码编辑。我仍然不知道如何正确地解决此问题,因为我不知道如何区分节点和webpack。
epelc

Answers:


304

该代码require('./locale/' + name)可以使用目录中的每个文件locale。因此,webpack将每个文件都包含在捆绑软件中作为模块。它不知道您使用哪种语言。

两个插件可用于为webpack提供更多有关应在包中包含哪个模块的信息:ContextReplacementPluginIgnorePlugin

require('./locale/' + name)称为上下文(包含表达式的require)。webpack从此代码片段中推断出一些信息:目录和正则表达式。这里:directory = ".../moment/locale" regular expression = /^.*$/。因此,默认情况下locale会包含目录中的每个文件。

ContextReplacementPlugin允许覆盖推断的信息,即提供了一个新的正则表达式(选择要包括语言)。

另一种方法是使用忽略需求IgnorePlugin

这是一个例子:

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

3
您能解释一下如何使用忽略加载程序吗?我尝试了`new webpackreg.IgnorePlugin(/\.\/ locale \ /.+。js $ /,[])`,但是没有用。同样,contextReplacementPlugin仍将文件包含在我的捆绑软件中,我只是认为它没有使用它们。
epelc

9
您可以查看此问题(github.com/webpack/webpack/issues/198),其中包含有关moment + webpack的详细讨论。
Tobias K.

2
谢谢,我认为new webpack.IgnorePlugin(/^\.\/lang$/, /moment$/)您对github的评论会起作用。
epelc 2014年

16
在webpack文档中,第二个参数是正则表达式数组。我试过了 plugins: [ new webpack.IgnorePlugin(/^\.\/locale$/, [/moment$/]) ],,一切都很好。
Alex K

6
@AlexKinnee 文档中的括号表示这是一个可选参数,而不是数组。
yangmillstheory

8

在我们的项目中,我包括这样的时刻:import moment from 'moment/src/moment';这似乎可以解决问题。不过,我们对矩的使用非常简单,因此我不确定该SDK是否存在任何不一致之处。我认为这行得通,因为WebPack不知道如何静态查找语言环境文件,因此会收到警告(通过在上添加一个空文件夹很容易隐藏moment/src/lib/locale/locale),但不包括语言环境。


1
不确定这些家伙如何为您工作...我只是试图与github.com/angular/angular-cli/issues/6137战斗,然后最终通过使用github.com/ksloan/moment-mini结束了战斗。适当的模块化moment库将在某个时候随版本3 github.com/moment/moment/milestone/15一起提供。
kuncevic.dev


2

根据Adam McCrmick的回答,您很接近,将别名更改为:

resolve: {
    alias: {
        moment: 'moment/src/moment'
    },
},

1
只是警告一下,这将改变您包括的所有模块的行为,并可能导致第三方库出现有趣的问题。它应该在一般的工作,虽然
亚当·麦考密克

1
你能详细说明吗?我对所有别名用例都没有经验。以我的理解,这仅与您触摸该模块有关,在这种情况下为“片刻”
bigopon

3
设置解析别名时,它们将应用于系统中任何导入或需要的使用(包括您依赖的库)。因此,如果模块取决于所需的时间,那么您也将更改该模块的结果。如果您碰巧设置了一个与您的依赖项树中的节点模块冲突的别名(例如,如果您的依赖项使用该库,则为“事件”),这就会出现。实际上,我只遇到名称冲突的问题,而不是像这样的行为改进,但这是比更改一个导入语句更危险的方法。
亚当·麦考密克

2

使用webpack2最新版本的时刻,您可以执行以下操作:

import {fn as moment} from 'moment'

然后在webpack.config.js你做:

resolve: {
    packageMains: ['jsnext:main', 'main']
}

1
我想你的意思是mainFields: ...
Guillermo Grau

看一下webpack2,很确定该字段名称已更改。
凯文
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.