Webpack动态导入.json文件?

5
我正在使用 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 文件夹中),然后根据当前使用的语言动态地导入它们?

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

1个回答

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应该将每个区域设置文件分割成自己的块。如果没有,那么很可能是在到达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一起使用。请回报您在此主题上的发现。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接