【问题标题】:How to bundle and then load i18n modules at runtime?如何在运行时捆绑并加载 i18n 模块?
【发布时间】:2016-04-11 18:00:17
【问题描述】:

我正在尝试从 RequireJS 迁移到 Webpack,但我不确定处理我们的语言环境文件的最佳方式。

目前,我们为每个语言环境生成一个单独的 JS 文件。这些文件包含 i18n 消息的 7 多个模块定义以及库配置(例如 moment)。例如,我们的 da_DK 文件如下所示:

(function (global, factory) {
   typeof exports === 'object' && typeof module !== 'undefined' ? factory(require('../moment')) :
   typeof define === 'function' && define.amd ? define('moment-locale',['moment'], factory) :
   factory(global.moment)
}(this, function (moment) { 'use strict';


    var da = moment.defineLocale('da', {
        ...
    });

    return da;

}));

define('messages',[],function(){
  var da_messages = {
    ...
  };
  
  return da_messages;
 });

在运行时,我们确定要与应用程序的其余部分一起加载的适当语言文件。我们的应用程序代码不知道加载了哪个语言环境;任何依赖于语言环境的模块都可以使用require('moment-locale') 和require('messages')。

我想用 Webpack 做一些类似的事情,但我还没有找到一个好的方法来完成这个。

我已经看到 require.context 用于动态需求,但听起来这最终会将所有可能的语言环境与我的应用程序捆绑在一起,我不想这样做。

我还查看了 DllPlugin,认为每个语言环境文件都可能是一个“dll”,但我注意到 dll 清单包含特定的模块名称(例如:node_modules/moment/locale/de-at.js),我想我需要它更通用,以便 webpack 知道我何时 require('moment-locale'),它需要查看那个 dll。

我能够让它工作的一种方法是更新我的语言环境包生成代码,以便它为每个语言环境创建一个条目,如下所示:

module.exports = {
    'messages': require('messages'),
    'moment-locale': require('moment-locale'),
    ...
};

然后在 webpack 配置中,我将 library 字段设置为我的应用程序的命名空间。然后在我的应用程序的 webpack 配置中,我在 externals 中引用了这些模块。所以换句话说,当 da_DK.js 被加载时,它会将 window 上的所有模块放在一个命名空间下,供应用程序在加载时引用。我宁愿不使用这种方法,但这是迄今为止我能够让它发挥作用的唯一方法。

还有其他/更好的方法来完成这个吗?

【问题讨论】:

    标签: webpack


    【解决方案1】:

    有多种方法可以解决这个问题。 3种可行的方法是:

    1. 将所有语言环境打包到您的包中。
    2. 让你的包延迟加载 语言环境
    3. 为每个语言环境制作单独的包

    将所有语言环境打包到您的捆绑包中

    这样,您可以用更大的捆绑包大小换取更少的 http 请求。如果语言环境很小,这可能是要采取的路线。在所有其他情况下,我建议不要这样做,因为它会使包大小变大并增加负载。

    让你的包延迟加载语言环境。

    为此,请利用Webpacks code splitting functionality。通过这种方式,您可以创建bundle.js、da_DK.js、sv_SE.js 等等,并根据 bundle.js 中的逻辑使用require()/require.ensure 加载语言环境文件之一。

    为每个语言环境制作单独的包

    根据您进行区域设置协商的方式,最好的方法可能是在构建时间创建单独的包。换句话说,创建一个bundle.da_DK.js 一个bundle.sv_SE.js 等等。如果您在加载捆绑包之前根据可用的内容进行区域设置协商(例如,url 中的 /da/ slug、会话设置等),这可能是要走的路。

    这样做,您将 a) 创建尽可能小的包 b) 将获得性能提升(尽管很小),因为不需要在运行时进行翻译。 i18n plugin for Webpack 将帮助您创建单独的捆绑包。

    旁注

    Moment.js,虽然它是一个非常好的库,但它对 Webpack 并不友好。它将加载 所有 语言环境。看看这个线程来改变这种行为:https://stackoverflow.com/a/25426019/2533681

    【讨论】:

    • 感谢您的反馈! 1. 我绝对想避免这种方法,因为我们支持多种语言环境,每个语言环境包大约 600KB。 2. 我尝试了这种方法,但由于直到运行时我才知道语言环境,我相信我必须使用动态的 require/require.context 最终捆绑所有可能的语言环境。 3. 我目前正在为每个语言环境生成捆绑包,但挑战在于加载它们并在运行时与应用程序的其余部分进行对话。
    • 关于 2. 如果您将语言环境拆分为不同的文件,您可以单独要求它们。关于 3. 我说的是为每个语言环境创建单独的包。包含both“应用程序代码”和语言环境的包。
    【解决方案2】:

    对于那些可能对动态(按需)加载与 webpack 捆绑的(语言)字典感兴趣的人,有一个新的包 https://github.com/whitecolor/lp-loader。

    【讨论】:

      猜你喜欢
      • 2011-01-18
      • 1970-01-01
      • 1970-01-01
      • 2011-02-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多