如何防止 moment.js 使用 webpack 加载语言环境?

问题描述 投票:0回答:8

当你使用 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
。我认为它现在使用正则表达式,所以我真的不知道你会如何修复它。

javascript gulp momentjs webpack
8个回答
321
投票

代码

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

9
投票

在我们的项目中,我加入了这样的时刻:

import moment from 'moment/src/moment';
,这似乎可以解决问题。不过我们对moment的使用非常简单,所以我不确定是否会与SDK有任何不一致。我认为这是可行的,因为 WebPack 不知道如何静态查找区域设置文件,因此您会收到一条警告(通过在
moment/src/lib/locale/locale
添加空文件夹很容易隐藏),但不包含区域设置。


5
投票

更新:2021 年
您可能还想查看许多其他库:

原答案:
似乎正确的模块化

moment
永远不会出现但是,我刚刚结束使用https://github.com/ksloan/moment-mini,就像
import * as moment from 'moment-mini';

一样

4
投票

从 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 语句都将被忽略。


3
投票

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

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

2
投票

使用

webpack2
和最新版本的 moment 您可以执行以下操作:

import {fn as moment} from 'moment'

然后在

webpack.config.js
你会:

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

2
投票

这是在 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"
    ...
  }
}

0
投票

对于网络,如果您要使用很少的区域设置

moment
。您可以选择此解决方案。使用
externals
配置。此外,我们需要将
moment
库和特定语言环境脚本添加到 HTML 模板中。

优点:

  • 提高webpack编译速度。
  • 减小捆绑包大小。
  • 不需要
    require('moment/locale/zh-tw')
    声明。

缺点:

  • 每个语言环境脚本都必须手动添加。
  • 即使您不在代码中使用区域设置脚本,也始终从 CDN 下载它们。这意味着有更多的 HTTP 请求。

以下示例仅使用

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())
© www.soinside.com 2019 - 2024. All rights reserved.