在Module Federation项目中实现i18n拆分与优化 - 第一篇

1,138 阅读3分钟

在现代前端开发中,Module Federation(MF)是一种越来越流行的架构模式。它允许我们将前端应用拆分成更小的、独立可部署的组件。这种方式带来了一些明显的优势,如团队独立性、技术栈灵活性等,但也引入了一系列新的挑战。在本文中,我们将讨论其中一个常见的问题:如何在MF项目中优化i18n(国际化)配置。

问题背景

我们开发的项目包含多个MF组件,同时也需要实现多语言支持。在这种情况下,有两个关键点需要考虑:

  1. 共享组件需要使用国际化配置,而这些组件可能会被多个不同的团队使用。

  2. 我们希望避免因共享组件的引入,导致整个项目的国际化文案全部被打包,从而增大打包体积。

为了实现组件的国际化功能,最简单的方法是让这些组件使用主应用的i18n实例。然而,这样做的一个显著缺陷是会导致整个项目的所有文案一同被打包,从而大幅增加打包体积。

为了解决这个问题,我们可以使用i18n的createInstance方法,创建新的实例,最终实现项目与MF组件的i18n拆分。

解决方案

我们使用i18next库示例说明如何实现这一目标,包括创建新的i18n实例并逐步分离项目和MF组件的文案。

步骤一:安装i18next依赖

首先确保在项目中安装了i18next及其React绑定。

npm install i18next react-i18next

步骤二:配置主应用的i18n

在主应用中配置i18n实例,加载主应用特有的文案。

import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

import enLocaleResource from '@/public/locales/en.json';
import zhLocaleResource from '@/public/locales/zh.json';

import { getLangKey } from './localstorage';

export const i18nApp = i18n.createInstance();

i18nApp
  .use(initReactI18next)
  // init i18next
  // for all options read: https://www.i18next.com/overview/configuration-options
  .init({
    lng: getLangKey(),
    fallbackLng: 'en',
    keySeparator: '.',
    preload: ['en', 'zh'],
    interpolation: {
      escapeValue: false, // not needed for react as it escapes by default
    },
    react: {
      useSuspense: false,
      transSupportBasicHtmlNodes: true,
      transKeepBasicHtmlNodesFor: ['b', 'br'],
    },
    resources: {
      en: {
        translation: enLocaleResource,
      },
      zh: {
        translation: zhLocaleResource,
      },
    },
  });

export default i18n;

步骤三:为MF组件创建独立的i18n实例

在MF组件中创建一个新的i18n实例,只加载组件特有的文案。

import { getLangKey } from '@/utils/localstorage';
import i18n from 'i18next';
import { initReactI18next } from 'react-i18next';

import enLocaleResource from '@/expose/locales/en.json';
import zhLocaleResource from '@/expose/locales/zh.json';

export const i18nExpose = i18n.createInstance();
export const t = i18nExpose.t;

i18nExpose
  // pass the i18n instance to react-i18next.
  .use(initReactI18next)
  // init i18next
  // for all options read: https://www.i18next.com/overview/configuration-options
  .init({
    lng: getLangKey(),
    fallbackLng: 'en',
    keySeparator: '.',
    preload: ['en', 'zh'],
    interpolation: {
      escapeValue: false, // not needed for react as it escapes by default
    },
    react: {
      useSuspense: false,
      transSupportBasicHtmlNodes: true,
      transKeepBasicHtmlNodesFor: ['b', 'br'],
    },
    resources: {
      en: {
        translation: enLocaleResource,
      },
      zh: {
        translation: zhLocaleResource,
      },
    }
  });

export default i18n;

步骤四:在组件中使用独立的i18n实例

定义组件需要使用的hook

import { i18nExpose } from '../utils/i18n';

const useExposeTranslation = () => {
  return i18nExpose;
};

export default useExposeTranslation;

在需要使用国际化的MF组件中调用useExposeTranslation。

// MF组件 - MyComponent/index.js
import React from 'react';
import useExposeTranslation from './hooks/useExposeTranslation'

const MyComponent = () => {
  const { t } = useExposeTranslation();
  return (
      <div>
        {/* 你的组件内容 */}
      </div>
  );
};

export default MyComponent;

总结

通过使用i18next库的createInstance方法,我们可以为每个MF组件创建独立的i18n实例,从而实现项目与MF组件的i18n拆分。这样的方式不仅可以优化打包体积,还可以提高文案管理的灵活性,使得大型项目的国际化维护更加高效。希望本文对你有所帮助,欢迎交流更多的技术实践经验。