Existem boas estruturas que nos ajudam a criar micro-front-ends, como single-spa e OpenComponents. Mas e se não quisermos integrar uma estrutura diferente em nossa arquitetura? Vamos dar uma olhada em como implementar micro-front-ends em nossos aplicativos Vue.

Neste artigo, discutiremos como simplificar drasticamente a arquitetura de nosso aplicativo usando Federação de módulo do webpack 5 para consumir e compartilhar componentes de micro-front-end com código de exemplo.

O que é federação de módulo?

Federação de módulos é uma arquitetura JavaScript inventada por Zack Jackson . Esta arquitetura permite o compartilhamento de código e dependências entre duas bases de código de aplicativo diferentes.

O código é carregado dinamicamente e, se uma dependência estiver faltando, ela será baixada pelo aplicativo host, o que permite menos código duplicação no aplicativo.

O que são micro-front-ends?

O conceito de micro-front-ends tem ganhado força nos últimos tempos. O impulso para microsserviços também trouxe a mesma implementação para a web moderna na forma de micro-front-ends. Conforme o aplicativo monolith aumenta, torna-se difícil mantê-lo, especialmente em várias equipes que trabalham no mesmo aplicativo.

Podemos considerar os micro-front-ends baseados em recursos, em que existem equipes diferentes e cada equipe lida com um componente de recurso específico enquanto outra equipe lida com outra coisa. No final, todas as equipes mesclam os diferentes componentes que construíram para formar um aplicativo.

Os desenvolvedores usaram estruturas como single-spa e OpenComponents para conseguir isso, mas com o novo lançamento do webpack 5 e a federação de módulo, podemos atingir facilmente o mesmo objetivo, mas de forma mais fácil.

As vantagens dos micro-front-ends

A adoção de uma abordagem de micro-front-end para construir seus aplicativos da web é provavelmente o melhor estratégia. Isso é especialmente verdadeiro se você estiver construindo um aplicativo da web em grande escala com muitas partes móveis ou aplicativos que são ramificados em subaplicativos onde você deseja alguma consistência na aparência geral.

Deixe-me destacar alguns motivos pelos quais você pode querer mudar para a abordagem de micro-front-end:

A adoção de uma abordagem de micro-front-end nos permitirá criar uma arquitetura de recursos de ponta a ponta. Essa abordagem nos permitirá desenvolver e implantar recursos localmente, sem a necessidade de infraestruturas de implantação em grande escala. Com um tamanho de pacote menor e mais otimizado, os micro-front-ends fornecem uma experiência geral melhor para o desenvolvedor e o usuário como resultado de componentes compartilhados e dependências que pode ser lento sempre que quisermos. Uma das maiores vantagens para mim é a capacidade das equipes de desenvolvedores que trabalham naquele produto específico de escolher uma pilha de tecnologia de sua escolha sem medo de incompatibilidade com o código da outra equipe

Como dividimos nossos aplicativos?

Estes são algumas maneiras pelas quais os desenvolvedores dividem aplicativos grandes:

Por página ⁠— Em nossos aplicativos de front-end, às vezes ter páginas diferentes rodando ao mesmo tempo no navegador pode causar uma falha em dispositivos mais antigos, então a maneira mais segura é dividir por página. Se você tiver um bom roteamento, poderá executar microaplicativos separados e específicos para cada página, o que também é bom para os desenvolvedores de sua equipe, porque eles sempre trabalharão na página atribuída a eles por funcionalidade ⁠— Se você tiver uma página com vários recursos de coisas realizando operações diferentes, você pode dividir esses grandes recursos em aplicativos menores e torná-lo um aplicativo independente executando esse recurso específico Por seção ⁠— Você também pode dividir seus aplicativos por seção, com diferentes aplicativos compartilhando a mesma seção ou componentes

Prova de conceito

Explicamos alguns conceitos sobre micro-frontends e federação de módulos. Agora é hora de uma prova de conceito.

Aqui, vamos demonstrar como podemos usar a federação de módulo para criar micro-frontends no Vue. Para testar isso, criaremos dois aplicativos diferentes, para que possamos criar um micro-front-end em um deles e compartilhá-lo com o outro.

Primeiro, criamos uma pasta para hospedar os dois. Aplicativos Vue:

mkdir vue-mf

É na pasta vue-mf que executaremos nosso aplicativo Vue. Não usaremos o Vue CLI aqui. Em vez disso, usaremos a nova versão do webpack, que é webpack 5, para configurar o aplicativo Vue.

Nomearemos os dois aplicativos que queremos compartilhar componentes como Empresa e Loja, respectivamente. Criamos uma pasta para cada um deles na pasta vue-mf e, em seguida, pegamos um arquivo inicial do webpack do Vue criado por Jherr do GitHub em cada pasta:

git clone https://github.com/jherr/wp5-starter-vue-3.git

Vamos dar uma olhada na estrutura do arquivo agora que temos configurar o aplicativo:

+-vue-mf/| +-Empresa/| +-Lojas/

Quando abrimos uma das pastas do aplicativo, esta é a estrutura:

+-vue-mf/| +-Empresa/| +-src/| +-App.vue | +-bootloader.js | +-index.css | +-index.html | +-index.js | +-package.json | +-webpack.config.js | +-Lojas/

Definir a configuração do webpack

Portanto, temos dois aplicativos, Empresa e Loja, que são exatamente os mesmos por enquanto. Quando examinamos a estrutura do arquivo, damos uma olhada no package.json. Temos nosso carregador de webpack, carregador de CSS e todos os carregadores básicos e coisas do webpack de que precisamos:

const ModuleFederationPlugin=require (“webpack/lib/container/ModuleFederationPlugin”); const {VueLoaderPlugin}=require (“vue-loader”); module.exports={output: {publicPath:”http://localhost: 8080/”,}, resolve: {extensions: [“.vue”,”.jsx”,”.js”,”.json”], }, devServer: {port: 8080,}, módulo: {rules: [{test:/.vue$/, loader:”vue-loader”,}, {test:/.css$/i, use: [“style-loader”,”css-loader”],}, {test:/.(js|jsx)$/, exclua:/node_modules/, use: {loader:”babel-loader”,},},], }, plug-ins: [new VueLoaderPlugin (), new ModuleFederationPlugin ({name:”starter”, filename:”remoteEntry.js”, remotes: {}, expõe: {}, shared: require (“./package.json”).dependências,}), novo HtmlWebPackPlugin ({template:”./src/index.html”,}),],};

Se dermos uma olhada no arquivo webpack.config.js, podemos ver que nosso caminho público está configurado para a porta 8080. Também podemos ver o webpack verificando nossas extensões de arquivo e usando os carregadores apropriados.

O importante a se notar aqui é o nosso plug-in carregador Vue usado na análise de nossos arquivos e o plug-in de federação do módulo do webpack 5 que importamos e usamos, o que nos permitirá executar a funcionalidade de compartilhamento. Voltaremos à configuração do ModuleFederationPlugin posteriormente neste tutorial.

NB, certifique-se de definir o caminho público e a porta do servidor de desenvolvimento no outro aplicativo (Shop) para a porta 8081, para que possamos ser capaz de executar os dois aplicativos simultaneamente.

Criar componentes a serem compartilhados

Em nosso aplicativo, o arquivo App.vue servirá como a página inicial, então vamos adicionar alguma marcação:

O componente de cabeçalho é uma parte de um aplicativo que gostaríamos de compartilhar entre os aplicativos. Digamos que uma das equipes de desenvolvedores decida construir o cabeçalho, então criamos um componente de cabeçalho que podemos compartilhar nos dois aplicativos.

Na pasta src em nosso aplicativo da empresa, criaremos um cabeçalho componente. Para fazer isso, criamos um arquivo Header.vue, e nele, criamos o componente de cabeçalho:

App Header

Depois de criar o cabeçalho, navegue até App.vue e importe o componente do cabeçalho:

Agora podemos iniciar nosso servidor de desenvolvimento navegando para cada pasta e executando:

yarn && yarn start

Neste momento, nosso aplicativo se parece com isso no aplicativo da empresa.

Expondo o componente do cabeçalho por meio do plugin Module Federation

Agora temos nosso cabeçalho no aplicativo da empresa, gostaríamos de usar no app Shop. Então, vamos para a configuração do webpack no aplicativo Company:

plugins: [new VueLoaderPlugin (), new ModuleFederationPlugin ({name:”Company”, filename:”remoteEntry.js”, remotes: {}, expõe: {“./Header”:”./src/Header”,}, compartilhado: require (“./package.json”). Dependências,}), novo HtmlWebPackPlugin ({template:”./src/index.html”,}),],

Na configuração do webpack Module Federation, definimos o nome como o nome do aplicativo, que é Company, e remoteEntry.js como nosso nome de arquivo. Quando navegamos até o nome do arquivo remoteEntry.js, vemos o código relacionado aos componentes e dependências que queremos compartilhar. Também expusemos o componente do cabeçalho com sua localização.

Agora, se reiniciarmos nosso servidor e navegarmos para http://localhost: 8080/remoteEntry.js , veremos isto:

Agora pegue o URL de entrada remota e mude para o arquivo de configuração do webpack em nosso aplicativo Shop:

plugins: [new VueLoaderPlugin (), new ModuleFederationPlugin ({name:”Shop”, filename:”remoteEntry.js”, remotes: {Company:”Company @ http://localhost: 8080/remoteEntry.js”}, expõe: { }, compartilhado: require (“./package.json”). dependencies,}), new HtmlWebPackPlugin ({template:”./src/index.html”,}),],

Aqui, damos o plugin um nome de Loja e defina o remoto para remoteEntry URL. Então, em nosso arquivo App.vue no aplicativo Shop, importamos e usamos o componente de cabeçalho de nosso aplicativo Company:

Our Shop Page

Se reiniciarmos nosso servidor, podemos ver que a página da loja agora tem o componente header, o que significa que compartilhamos com sucesso o componente entre os dois aplicativos. Yay!

NB, se a equipe que trabalha no cabeçalho decidir enviar uma nova atualização para o componente do cabeçalho, a equipe do aplicativo Shop verá imediatamente a atualização assim que o aplicativo Shop for atualizado.

Compartilhando o estado do aplicativo entre os módulos da federação

Digamos que você esteja usando um gerenciador de estado em seu aplicativo Vue, como o Vuex. Você pode estar se perguntando como pode ter o estado, compartilhá-lo entre os dois componentes e também atualizá-lo. Então, vamos instalar o Vuex para os dois aplicativos:

yarn install vuex @ next

Depois de instalar o Vuex, navegue até o arquivo bootloader.js em nosso aplicativo Company, onde inicializamos nosso aplicativo Vue.
Aqui, importamos nossa loja e criamos um estado:

import {createApp} from”vue”; import {createStore} de’vuex’import”./index.css”; importar App de”./App.vue”; const app=createApp (App) const store=createStore ({state () {return {cartItems: 0}}}) app.use (store) app.mount (“# app”);

Se, por exemplo, esta for uma loja de comércio eletrônico onde desejamos exibir o número de itens do carrinho que temos em nosso carrinho, criamos um estado cartItems e o exibimos no cabeçalho da empresa. Em seguida, vá para nosso componente de cabeçalho, acesse o estado e exiba-o:

Cabeçalho do aplicativo

itens: {{cartCount}}

f

Com sucesso configurar nosso estado, mas o problema com isso é se iniciarmos o servidor para ambos os aplicativos e verificarmos o aplicativo da empresa, podemos ver a exibição do cabeçalho com o estado:

Mas se navegamos até o aplicativo Shop, não podemos mais ver o componente de cabeçalho compartilhado, muito menos o estado que adicionamos. Em vez disso, recebemos uma mensagem de erro que diz que não podemos ler o estado de indefinido, porque em nosso aplicativo Shop, não configuramos nenhuma loja.

Para corrigir esse problema, copiamos todos os código que temos no bootloader do aplicativo Company e cole-o no arquivo bootloader.js do aplicativo Shop. Desta vez, mudamos o estado cartCount para 12. Se reiniciarmos o servidor, agora temos nosso cabeçalho no aplicativo Shop, com itens do carrinho de 12.

Digamos que queremos imitar a adição de mais comprar itens no carrinho, portanto, no aplicativo Loja, adicionamos um botão que incrementa o estado cartCount:

Nossa página da loja

Se reiniciarmos o aplicativo Shop, podemos ver que os itens no cabeçalho agora são atualizados. Oba!

Recursos

Código-fonte do GitHub webpack 5’s Module Federation

Conclusão

Chegamos ao final deste tutorial.

Aqui, discutimos como simplificar drasticamente a arquitetura de nosso aplicativo usando webpack 5 da Federação de Módulos para consumir e compartilhar componentes de micro-front-end com código de exemplo.

Se você deve ou não adotar micro-front-ends depende do tipo de projeto que você está construindo, porque essa abordagem não será a melhor para pequenos aplicativos ou empresas. Uma abordagem de arquitetura de micro-front-end é sua melhor aposta ao trabalhar em um grande projeto com equipes distribuídas.