ModuleFederationPlugin

ModuleFederationPlugin을 사용하면 런타임에 다른 독립 빌드와 함께 모듈을 제공하거나 사용할 수 있습니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // 여러 옵션을 타입스크립트로 작성합니다.
      runtime: string | false,
    }),
  ],
};

Options

runtime

특정한 이름으로 새로운 런타임 청크를 만듭니다.

webpack.config.js

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      runtime: 'my-runtime-name',
    }),
  ],
};

Sharing libraries

설정의 'shared' 키를 사용하면 모듈 연합 사이에 공유되는 라이브러리를 정의할 수 있습니다. 패키지 이름은 package.json의 'dependencies' 섹션에 있는 이름과 동일합니다. 그러나 기본적으로 webpack은 라이브러리의 루트 레벨만 공유합니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // date-fns를 공유 모듈로 추가합니다.
      shared: ['date-fns'],
    }),
  ],
};

따라서 응용 프로그램에서 다음과 같은 작업을 수행할 수 있습니다.

import { format } from 'date-fns';

format(new Date(2014, 1, 11), 'MM/dd/yyyy');

그리고 webpack은 date-fns를 공유 라이브러리로 정의하는 모든 모듈 연합 사이에 date-fns를 자동으로 공유합니다. 그러나 패키지의 루트 레벨에 없는 항목(예: date-fns/locale/en-GB/index.js)에 액세스하려면 '공유' 설정에서 패키지 이름에 /를 추가해야 합니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // date-fns를 공유 모듈로 추가합니다.
      // 패키지의 모든 파일이 공유됩니다
      shared: ['date-fns/'],
    }),
  ],
};

The / 구문을 사용하면 패키지의 모든 파일에 액세스할 수 있습니다. 그러나 특히 개발 모드에서는 성능에 영향을 미치므로 필요한 경우에만 사용해야 합니다.

Specify package versions

공유 라이브러리의 버전을 지정하는 세 가지 방법이 있습니다.

Array syntax

이 구문을 사용하면 패키지 이름만 있는 라이브러리를 공유할 수 있습니다. 이 접근 방식은 프로토타이핑에 적합하지만 reactreact-dom과 같은 라이브러리에 추가 요구 사항이 필요하기 때문에 대규모 프로덕션 환경으로 확장할 수 없습니다.

const { ModuleFederationPlugin } = require('webpack').container;
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // lodash를 공유 모듈로 추가합니다.
      // package.json으로부터 버전을 추론합니다.
      // 필수 버전을 확인하지 않습니다.
      // 그래서 항상 발견된 더 높은 버전을 사용합니다.
      shared: ['lodash'],
    }),
  ],
};
Object syntax

이 구문을 사용하면 패키지 이름을 키로 정의하고 버전(semver)을 값으로 정의할 수 있는 각 공유 라이브러리를 보다 세부적으로 제어할 수 있습니다.

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // lodash를 공유 모듈로 추가합니다.
        // package.json 으로부터 버전을 추론합니다.
        // 4.17 이상 5 미만의 버전 중 최상위 버전을 사용하게 됩니다.
        lodash: '^4.17.0',
      },
    }),
  ],
};
Object syntax with sharing hints

이 구문을 사용하면 각 공유 패키지에 힌트를 추가로 제공할 수 있습니다. 패키지의 이름을 키로, 공유 동작을 수정하기 위한 힌트를 포함한 객체를 값으로 정의하여 제공할 수 있습니다.

const deps = require('./package.json').dependencies;

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        // react를 공유 모듈로 추가합니다.
        react: {
          requiredVersion: deps.react,
          singleton: true,
        },
      },
    }),
  ],
};

Sharing hints

eager

boolean

이 힌트를 사용하면 webpack이 비동기식 요청을 통해 라이브러리를 가져오는 대신 제공된 모듈이나 대체 모듈을 직접 포함할 수 있습니다. 즉, 초기 청크에서 이 공유 모듈을 사용할 수 있습니다. 또한 이 힌트가 활성화되면 제공된 모든 모듈과 대체 모듈이 항상 다운로드된다는 점에 주의해야 합니다.

import

false | string

제공된 모듈은 공유 유효범위에 배치되어야 합니다. 이 제공된 모듈은 공유 유효범위에 공유 모듈이 없거나 버전이 유효하지 않은 경우 대체 모듈 역할도 합니다. (이 힌트의 값은 기본적으로 프로퍼티 이름으로 설정됩니다.)

packageName

string

설명 파일에서 필요한 버전을 결정하는 데 사용되는 패키지 이름입니다. ‘packageName’은 요청으로부터 패키지 이름을 자동으로 결정할 수 없는 경우에만 필요합니다.

requiredVersion

false | string

패키지의 필수 버전입니다. 시멘틱 버전 관리를 허용합니다. 예를들면 "^1.2.3"와 같이 사용합니다.

shareKey

string

요청된 공유 모듈은 공유 유효범위에서 ‘shareKey’ 키 안에서 조회됩니다.

shareScope

string

공유 범위의 이름입니다.

singleton

boolean

‘singleton’은 공유 범위에서 단일 버전의 공유 모듈만 허용합니다.(기본적으로 비활성화됨) 일부 라이브러리는 전역 내부 상태를 사용합니다.(예: react, react-dom) 따라서 한 번에 하나의 라이브러리 인스턴스만 실행하는 것이 중요합니다.

공유 범위에 동일한 종속성을 갖는 여러 버전이 있는 경우, 가장 높은 시멘틱 버전이 사용됩니다.

strictVersion

boolean

‘strictVersion’을 사용하면 버전이 유효하지 않은 경우 webpack이 공유 모듈을 거부할 수 있습니다(로컬 fallback 모듈을 사용할 수 있고 공유 모듈이 singleton이 아닌 경우 기본값은 true로 설정되고, 그렇지 않으면 false로 설정되며 필수 버전이 지정되지 않은 경우 효과가 없습니다). 필요한 버전이 없으면 런타임 오류가 발생합니다.

version

false | string

제공된 모듈의 버전입니다. Webpack이 일치하는 낮은 버전을 대체할 수 있지만, 더 높은 버전은 대체할 수 없습니다.

Webpack은 기본적으로 디펜던시의 package.json 파일에 있는 버전을 사용합니다.

Additional examples

module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // vue를 공유 모듈로 추가합니다.
      // package.json 으로부터 버전을 추론합니다.
      // 항상 공유 버전을 사용하지만 공유된 vue가 2.6.5 미만 또는 3 이상 버전인 경우 경고를 출력합니다.
      shared: {
        vue: {
          requiredVersion: '^2.6.5',
          singleton: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // vue를 공유 모듈로 추가합니다.
      // 제공된 로컬 버전이 없습니다.
      // 공유된 vue가 2.6.5 미만 또는 3 이상 버전이면 경고를 내보냅니다.
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      // vue를 공유 모듈로 추가합니다.
      // 제공된 로컬 버전이 없습니다.
      // 공유된 vue가 2.6.5 미만 또는 3 이상 버전이면 오류가 발생합니다.
      shared: {
        vue: {
          import: false,
          requiredVersion: '^2.6.5',
          strictVersion: true,
        },
      },
    }),
  ],
};
module.exports = {
  plugins: [
    new ModuleFederationPlugin({
      shared: {
        'my-vue': {
          // 'my-vue' 가져오기로 참조할 수 있습니다.
          import: 'vue', // 'vue' 패키지는 제공된 대체 모듈로 사용됩니다.
          shareKey: 'shared-vue', // 'shared-vue'이름으로 공유된 모듈은 공유 유효범위에 배치됩니다.
          shareScope: 'default', // 'default'로 공유 유효범위가 적용됩니다.
          singleton: true, // 공유 모듈의 단일 버전만 허용됩니다.
          strictVersion: true, // 버전이 유효하지 않을 때 공유 버전을 사용하지 말아야 합니다. fallback이 없는 Singleton 또는 모듈은 넘겨집니다. 그렇지 않으면 fallback이 사용됩니다.
          version: '1.2.3', // 공유 모듈의 버전입니다.
          requiredVersion: '^1.0.0', // 공유 모듈의 최소 버전 입니다.
        },
      },
    }),
  ],
};

Further Reading

4 Contributors

XiaofengXie16chenxsanburhanudaychristian24