DEV Community

Cover image for Module Federation e as principais propriedades do Share
Helton
Helton

Posted on • Edited on

5 3

Module Federation e as principais propriedades do Share

O Module Federation é um plugin do webpack que permite trabalhar com microfrontends removendo uma carga de complexidade e com algum ganho de performance que iremos descrever nesse breve artigo.

Disclaimer:

  • Esse artigo não é um tutorial! é apenas um artigo de referência para descrever as opções da propriedade Share do plugin
  • Teremos o termo shell mais usado pela comunidade como a definição de um container que abriga ali vários microfrontends, e microfrontend chamaremos de MF ou MFs(plural) até o final do artigo.

Existem hoje algumas possibilidades de se trabalhar com MFs, algumas delas usando outros frameworks como single-spa, estratégias com monorepo como NX ou Angular Worskpace e até mesmo alguma proposta de compiler que tenta resolver o problema de duplicação de código que as abordagens citadas anteriormente não se propõem a fazer “meados de maio de 2022".

Mas o que seria a duplicação de código?

Tenha o seguinte cenário em mente, temos uma aplicação chamada de shell com a versão 17 do react e um MF utilizando a mesma versão, quando geramos o bundle final que vai para a produção temos a duplicação do core da biblioteca, pois mesmo que essas aplicações estejam utilizando a mesma versão da biblioteca ela não é compartilhada entre as mesmas, e esse cenário pode ser o mesmo utilizando frameworks como angular, então imagina uma aplicação com vários MFs, considere o tamanho do bundle que será consumido pelo client/browser, e existem algumas abordagens para resolver esse problema no processo de build, mas requer alguma complexidade.

E o que muda com o Module Federation

É exatamente nesse ponto que o module federation entra, ele não vem apenas para ser mais uma solução de MFs e sim para resolver o problema de duplicação de código.

Voltando para o mesmo cenário citado, as duas aplicações com a mesma dependência do React na versão 17, que agora utilizando module federation conseguirmos através da propriedade share criar estratégias que forneçam a possibilidade de ter o core da biblioteca compartilhado entre o Shell e os MFs gerando um ganho de performance considerável já que o cliente/browser vai consumir apenas o bundle necessário para a execução da aplicação.

Agora vamos entender as Opções do plugin

name: string é o nome que definimos para o nosso MF, e é uma boa prática que ela seja a mesma que o nome da aplicação.

filename: string é o nome dado ao entrypoint que o webpack vai gerar para que possa ser consumido pela aplicação shell ex: “meuModuleRemoteEntry.js".

library: object é um objeto com opções que ajudam descrever como um código/chunck gerado que foi exposto será armazenado e recuperado, essa propriedade tem seu próprio leque de configurações, como a proposta desse artigo é falar um pouco mais sobre a propriedade share vou deixar o link para documentação.

Mas no geral você pode configurar como consumir esse MF que vai expor, como uma variável ou módulo etc...

share: object -> É onde declaramos todas as bibliotecas que podem ser compartilhadas entre os MFs, quando o shell compartilha uma determinada lib com os MFs e os MFs tem a mesma lib compatível com o shell os MFs consomem a lib compartilhada pelo shell do contrário acabam utilizando a sua própria versão lib na aplicação, sendo assim teremos duas libs iguais mais que podem estar versões diferentes.

Entendo isso temos 3 formas de declarar as bibliotecas compartilhadas.

  1. Array:
shared: ['react']
Enter fullscreen mode Exit fullscreen mode
  1. objeto
shared: {
        // Será utilizado a maior versão do React
        // que pode se >= 17.0 and < 18
          react: '^17.0.2',
        },
Enter fullscreen mode Exit fullscreen mode
  1. Objeto da biblioteca com algumas opções de compartilhamento:
shared: {
         // adiciona o react como módulo compartilhado
         // e configura mais algumas opções
         react: {
           requiredVersion: '^17.0.2',
           singleton: true,
          },
        },
Enter fullscreen mode Exit fullscreen mode

E essas opções de compartilhamento podem ser:

eager: boolean -> essa opção vai permitir fornecer um um módulo inicial no chunck da aplicação sendo ele o módulo principal ou um fallback, o módulo vai ser compilado junto com seu MF em vez de ser solicitado de forma assíncrona.

import: false | string -> fornece o módulo que deve ser adicionado ao Shared Scope, se o módulo compartilhado no Shared Scope não for encontrado ele vai usar o módulo fornecido no import como fallback

shareKey: string -> O módulo compartilhado é pesquisado através dessa chave do escopo compartilhado.

shareScope: string -> O nome do escopo compartilhado.
Exemplo da utilização do import, shareKey e shareScope

shared: {
        'my-extension-lib': {
          import: 'lib', // O pacote "lib" será usado como pacote fornecido e um substituto
          shareKey: 'shared-lib', // Nome dado ao módulo que será colocado no Share Scope
          shareScope: 'default', // Nome dado ao Share Scope
          version: '1.2.3', // A versão da lib
          requiredVersion: '^1.0.0', // A versão minima solicitada pela lib
        },
      },
Enter fullscreen mode Exit fullscreen mode

packageName: string -> Necessário APENAS para quando precisamos determinar uma versão de biblioteca que não pode ser determinada automaticamente.

requiredVersion: string -> Usado para declarar a versão especifica de uma biblioteca.

singleton: boolean ->Essa opção permite ter uma única versão do módulo que foi compartilhado no escopo de compartilhamento o que seria o shell.

Usar mais do que uma versão de biblioteca não é uma escolha muito interessante, pois quando falamos de bibliotecas que mantém o estado, você utilizar mais de uma versão fornece automaticamente a duplicidade de um Estado Principal para a aplicação.

Por esse motivo o Module Federation permite definir bibliotecas como singletons, se temos versões da biblioteca compatíveis considerando a Minor version o Module Federation vai decidir pela versão mais recente pela lib.

É possível usar versões diferentes de uma lib usando um range no requiredVersion, mesmo optando pelo singleton: true e strictVersion true.

strictVersion: boolean -> Essa opção deve rejeitar o módulo compartilhado e emitir um erro se a versão não é válida, por default ela é true quando um módulo de fallback está disponível e não estamos utilizando a opção singleton, a outra opção é false mas ele não tem efeito se houver declarado a versão obrigatória da biblioteca.

version: false | string -> A versão do módulo fornecido, permite que o webpack substitua uma versão correspondente Minor version, mas não a Major version.

Em resumo falando sobre Share e o compartilhamento de libs, o Shell sempre vai assumir a responsabilidade de manter a versão mais atual da biblioteca compartilhada com os MFs, mas quando o carregamento dos MFs não for feito de forma estática em suma quando for feito de forma dinâmica, e o Shell tenha uma versão menor do que o MF cada um vai ficar responsável por subir sua própria versão da biblioteca.

Ainda podemos através do compartilhamento dos MFs de forma dinâmica carregar dinamicamente apenas o ponto de entrada remoto no início do programa e carregar o micro frontend posteriormente sob demanda. Ao dividir isso em dois processos de carregamento, o comportamento é exatamente o mesmo do compartilhamento de forma estática ("clássica"). A razão é que neste caso os metadados da entrada remota estão disponíveis com antecedência suficiente para serem considerados durante a negociação das versões.

Caso eles sejam estáticos essas libs vão ser conhecidas no tempo de build tanto do shell quanto do microfrontend e com isso será carregado a versão mais atual da lib em questão.

Bom é isso, Module Federation trás um cenário bem interessante e com muitas possibilidades para se trabalhar com Microfrontends.

Referências:
Documentação Webpack
Angular Architects

Heroku

Build apps, not infrastructure.

Dealing with servers, hardware, and infrastructure can take up your valuable time. Discover the benefits of Heroku, the PaaS of choice for developers since 2007.

Visit Site

Top comments (0)

A Workflow Copilot. Tailored to You.

Pieces.app image

Our desktop app, with its intelligent copilot, streamlines coding by generating snippets, extracting code from screenshots, and accelerating problem-solving.

Read the docs

👋 Kindness is contagious

Please leave a ❤️ or a friendly comment on this post if you found it helpful!

Okay