【问题标题】:Webpack dynamic import .json file?Webpack 动态导入 .json 文件?
【发布时间】:2023-03-27 09:06:01
【问题描述】:

我将 React Intl 用于 x 种语言(如下示例),目前我在设置我的应用程序时导入以下内容:

import { addLocaleData } from 'react-intl';
import locale_en from 'react-intl/locale-data/en';
import locale_de from 'react-intl/locale-data/de';

import messages_en from './translations/en.json';
import messages_de from './translations/de.json';

addLocaleData([...locale_en, ...locale_de]);

...
export const messages = {
    en: messages_en,
    de: messages_de
}

由于无论使用哪种语言都会导入这些语言文件,因此我的主捆绑 js 文件变得非常大,尤其是来自 .json 文件。

如何使用 Webpack 拆分这些语言文件(或使用 CopyWebpackPlugin 将它们复制到我的 dist 文件夹),然后根据当前使用的语言动态导入它们?

该应用程序是同构的,因此相同的代码正在服务器上运行。

【问题讨论】:

    标签: javascript node.js reactjs webpack react-intl


    【解决方案1】:

    我最近一直在做类似的事情,尽管我的项目不需要 SSR。我发现将动态导入语法与 React 的 Suspense 组件配对可以达到预期的效果。这是我发现的工作的粗略概述,至少在我的情况下,不包括 SSR:

    // wrap this around your JSX in App.js:
    <React.Suspense fallback={<SomeLoadingComponent />}>
      <AsyncIntlProvider>
        {/* app child components go here */}
      </AsyncIntlProvider>
    </React.Suspense>
    
    // the rest is in support of this
    // can be placed in another file
    // simply import AsyncIntlProvider in App.js
    
    const messagesCache = {};
    
    const AsyncIntlProvider = ({ children }) => {
      // replace with your app's locale getting logic
      // if based on a hook like useState, should kick off re-render and load new message bundle when locale changes (but I haven't tested this yet)
      const locale = getLocale();
    
      const messages = getMessages(locale);
      return (
        <IntlProvider locale={locale} messages={messages}>
          {children}
        </IntlProvider>
      );
    };
    
    function getMessages(locale) {
      if (messagesCache[locale]) {
        return messagesCache[locale];
      }
      // Suspense is based on ErrorBoundary
      // throwing a promise will cause <SomeLoadingComponent /> to render until the promise resolves
      throw loadMessages(locale);
    }
    
    async function loadMessages(locale) {
      // dynamic import syntax tells webpack to split this module into its own chunk
      const messages = await import('./path/to/${locale}.json`);
      messagesCache[locale] = messages;
      return messages;
    }
    

    Webpack 应该将每个语言环境 JSON 文件拆分为自己的块。如果没有,则可能在动态导入语法到达 webpack 之前将其转换为不同的模块系统(require 等)。例如:如果使用 Typescript,tsconfig 需要 "module": "esnext" 来保留 import() 语法。如果使用 Babel,它也可能会尝试进行模块转译。

    单个语言环境的块输出将如下所示;肯定比通过 CopyWebpackPlugin 实现的要多:

    (window["webpackJsonp"] = window["webpackJsonp"] || []).push([[0],{
    
    /***/ "./path/to/en-US.json":
    /*!*************************************!*\
      !*** ./path/to/en-US.json ***!
      \*************************************/
    /*! exports provided: message.id, default */
    /***/ (function(module) {
    
    eval("module.exports = JSON.parse(\"{\\\"message.id\\\":\\\"Localized message text\\\"}\");//# sourceURL=[module]\n//# sourceMappingURL=data:application/json;charset=utf-8;base64,eyJ2ZXJzaW9uIjozLCJmaWxlIjoiLi9zcmMvbG9jYWxpemF0aW9uL2VuLVVTLmpzb24uanMiLCJzb3VyY2VzIjpbXSwibWFwcGluZ3MiOiIiLCJzb3VyY2VSb290IjoiIn0=\n//# sourceURL=webpack-internal:///./path/to/en-US.json\n");
    
    /***/ })
    
    }]);
    

    希望这是一个很好的起点,可以与 SSR 一起使用,也可以修改为与 SSR 一起使用。请报告您在该主题上的发现。 ?

    【讨论】:

      猜你喜欢
      • 2018-11-14
      • 1970-01-01
      • 2019-06-07
      • 1970-01-01
      • 1970-01-01
      • 2020-04-01
      • 2022-11-29
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多