当你使用 webpack 时,有什么方法可以阻止
moment.js
加载所有语言环境(我只需要英语)?我正在查看源代码,似乎如果定义了 hasModule
(这是针对 webpack 的),那么它总是尝试 require()
每个语言环境。我很确定这需要拉请求来修复。但是我们有什么办法可以通过 webpack 配置来解决这个问题吗?
这是我加载 momentjs 的 webpack 配置:
resolve: {
alias: {
moment: path.join(__dirname, "src/lib/bower/moment/moment.js")
},
},
然后在任何我需要的地方,我都会做
require('moment')
。这可行,但它向我的包中添加了大约 250 kB 不需要的语言文件。我还使用了 momentjs 和 gulp 的 Bower 版本。
此外,如果 webpack 配置无法解决此问题,这里是 指向加载语言环境的函数的链接。我尝试将
&& module.exports.loadLocales
添加到 if
语句中,但我猜 webpack 实际上并没有以这种方式工作。无论如何,这只是require
。我认为它现在使用正则表达式,所以我真的不知道你会如何修复它。
代码
require('./locale/' + name)
可以使用locale
目录中的每个文件。因此,webpack 将每个文件作为模块包含在包中。它无法知道您正在使用哪种语言。
有两个插件可以为 webpack 提供更多有关哪个模块应该包含在你的包中的信息:
ContextReplacementPlugin
和IgnorePlugin
。
require('./locale/' + name)
称为 context (包含表达式的 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$/)
]
};
在我们的项目中,我加入了这样的时刻:
import moment from 'moment/src/moment';
,这似乎可以解决问题。不过我们对moment的使用非常简单,所以我不确定是否会与SDK有任何不一致。我认为这是可行的,因为 WebPack 不知道如何静态查找区域设置文件,因此您会收到一条警告(通过在 moment/src/lib/locale/locale
添加空文件夹很容易隐藏),但不包含区域设置。
更新:2021 年
您可能还想查看许多其他库:
原答案:
似乎正确的模块化
moment
库永远不会出现但是,我刚刚结束使用https://github.com/ksloan/moment-mini,就像import * as moment from 'moment-mini';
一样
从 2.18 版本开始,所有语言环境都与核心库捆绑在一起(请参阅此 GitHub 问题)。
传递给 IgnorePlugin 的 resourceRegExp 参数不会针对导入或必需的已解析文件名或绝对模块名称进行测试,而是针对在发生导入的源代码中传递给 require 或 import 的字符串进行测试。例如,如果您尝试排除 node_modules/moment/locale/*.js,这将不起作用:
new webpack.IgnorePlugin({ resourceRegExp: /moment\/locale\// });
相反,因为 moment 使用此代码导入:
require('./locale/' + name);
您的第一个正则表达式必须与“./locale/”字符串匹配。然后,第二个 contextRegExp 参数用于选择发生导入的特定目录。以下内容将导致这些区域设置文件被忽略:
plugins:[
new webpack.IgnorePlugin({
resourceRegExp: /^\.\/locale$/,
contextRegExp: /moment$/,
}),
]
这意味着“任何以 'moment' 结尾的目录中与 './locale' 匹配的 require 语句都将被忽略。
根据 Adam McCrmick 的回答,您已经很接近了,请将您的别名更改为:
resolve: {
alias: {
moment: 'moment/src/moment'
},
},
使用
webpack2
和最新版本的 moment 您可以执行以下操作:
import {fn as moment} from 'moment'
然后在
webpack.config.js
你会:
resolve: {
packageMains: ['jsnext:main', 'main']
}
这是在 NPM 安装程序中使用 postinstall script 的另一个解决方案。
您可以在您的 package.json 文件中添加一行:
{
"scripts": {
...
"postinstall": "find node_modules/moment/locale -type f -not -name 'en-gb.js' -not -name 'pl.js' -printf '%p\\n' | xargs rm"
...
}
}
结果,在
npm install
完成安装软件包后,不需要的语言环境将立即被删除。
就我而言,只有
en-gb
和 pl
语言环境将保留在捆绑包中。
如果您已经有
postinstall
脚本,您可以将脚本添加到现有命令中:
{
"scripts": {
...
"postinstall": "previous_command && find node_modules/moment/locale -type f -not -name 'en-gb.js' -not -name 'pl.js' -printf '%p\\n' | xargs rm"
...
}
}
对于网络,如果您要使用很少的区域设置
moment
。您可以选择此解决方案。使用 externals
配置。此外,我们需要将 moment
库和特定语言环境脚本添加到 HTML 模板中。
优点:
require('moment/locale/zh-tw')
声明。缺点:
以下示例仅使用
zh-tw
的 moment
语言环境。
webpack.config.js
:
const HTMLWebpackPlugin = require("html-webpack-plugin");
module.exports = {
mode: 'production',
entry: './src/index.js',
externals: {
moment: 'moment'
},
plugins: [
new HTMLWebpackPlugin({
template: './src/index.html'
}),
]
};
src/index.html
:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/moment.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.29.4/locale/zh-tw.min.js"></script>
</body>
</html>
src/index.js
:
import moment from 'moment';
moment.locale('zh-tw');
console.log(moment().fromNow())