DEV Community

Cover image for Micro Frontends com Next.js Multi Zones
Rafael Thayto
Rafael Thayto

Posted on

Micro Frontends com Next.js Multi Zones

Quando estamos desenvolvendo uma aplicação Web e ela acaba escalando, geralmente precisamos de um time. Quando essa aplicação escala mais ainda, precisamos de mais times trabalhando na mesma aplicação.

Por que estou falando isso?

Porque geralmente quando temos muitas pessoas alterando o mesmo projeto, podemos ter diversos problemas. Sejam eles muitos Pull Requests, diferenças de escopos, regras de negócio distintas, conflitos de merge e até mesmo divergências de ideias.

Quando isso acontece o que geralmente pensamos é em separar um pedaço dele em outro projeto e criar o famoso Micro Frontend que vai agilizar nossas entregas e garantir que o projeto evolua de maneira mais rápida e independente de outros escopos.

O que facilita e muito o desenvolvimento!

Com o isso o time do Next.js criou uma feature avançada que chama Multi Zones, com ela a gente consegue criar diversos Micro Frontends de forma muito rápida e simples utilizando Next.js

Pré-requisitos

Antes de continuar a ler esse artigo, eu presumo que você tenha uma noção básica / familiaridade com Next.js

O que vamos fazer

Até o final desse artigo vamos fazer 2 apps com Next.js, combinar eles usando a feature de Multi Zones. Vou fazer também uma parte 2 mostrando como deployar as 2 aplicações na Vercel.

Criando a pasta do projeto

Abre seu terminal/cmd e manda o seguinte comando:

mkdir nextjs-multi-zones-post
cd nextjs-multi-zones-post
Enter fullscreen mode Exit fullscreen mode

Logo em seguida abram essa mesma pasta no editor preferido de vocês! (nessa época era o VSCode 💩, hoje em dia é o Neovim/VIM ❤️)

Criando os projetos

Após ter entrado na pasta que vai centralizar nossos projetos, chegou a hora de criá-los!

Primeira aplicação - Home

Abre seu terminal aí e escreve o seguinte comando para criarmos o primeiro projeto que vai ser nossa HOME:

npx create-next-app --ts home
cd home
Enter fullscreen mode Exit fullscreen mode

Depois de criar a home, vamos alterar a porta em que o projeto vai rodar pra facilitar a nossa vida e termos um padrão até o final do post

Abra o arquivo package.json que está dentro da sua home e altere o script de dev de:

...
"scripts": {
    "dev": "next dev",
    ...
  },
...
Enter fullscreen mode Exit fullscreen mode

para:

...
"scripts": {
    "dev": "next dev -p 4444",
    ...
  },
...
Enter fullscreen mode Exit fullscreen mode

Abra seu terminal na mesma pasta e rode o seguinte comando pra executar a aplicação:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Segunda aplicação - Blog

Abra outro terminal e rode o seguinte comando para criarmos o nosso segundo projeto que vai ser nosso BLOG:

npx create-next-app --ts blog
cd blog
Enter fullscreen mode Exit fullscreen mode

Vamos seguir o mesmo procedimento que fizemos para home agora com o blog

Abra o arquivo package.json que está dentro do seu blog e altere o script de dev de:

...
"scripts": {
    "dev": "next dev",
    ...
  },
...
Enter fullscreen mode Exit fullscreen mode

para:

...
"scripts": {
    "dev": "next dev -p 7777",
    ...
  },
...
Enter fullscreen mode Exit fullscreen mode

Abra seu terminal na mesma pasta e rode o seguinte comando pra executar a aplicação:

npm run dev
Enter fullscreen mode Exit fullscreen mode

Pronto, agora já temos as 2 aplicações rodando e o resultado tem que ser algo parecido com isso:

Resultado esperado

Home (Aplicação 1) rodando na porta http://localhost:4444 e o Blog (Aplicação 2) rodando na porta http://localhost:7777

Configurando a Home (Aplicação 1)

O primeiro projeto que vamos desenvolver e configurar vai ser Home que além de ser o projeto base também vai ser nossa Home. É nele onde vamos configurar as URLs que vamos fazer o rewrite para que o Micro Frontend e as Multi Zones funcionem.

Abram o arquivo next.config.js e adicionem as seguintes linhas de código:

const { BLOG_URL } = process.env

const nextConfig = {
  async rewrites() {
    return [
      {
        source: '/:path*',
        destination: `/:path*`,
      },
      {
        source: '/blog',
        destination: `${BLOG_URL}/blog`,
      },
      {
        source: '/blog/:path*',
        destination: `${BLOG_URL}/blog/:path*`,
      },
    ]
  },
}
Enter fullscreen mode Exit fullscreen mode

Na parte de rewrites é basicamente uma reescrita mesmo, vamos reescrever as rotas /blog e tudo que vier depois, como por exemplo /blog/posts/hello-world. Para saber mais sobre rewrites é só acessar a documentação oficial do Next.js.

E vocês podem perceber que também adicionamos uma constante usando uma desestruturação no objeto process.env para podermos pegara URL do blog via variáveis de ambiente.
Agora bora criar o arquivo .env na raiz do nosso projeto da home como mostra no exemplo abaixo.

Onde vai ficar localizado o arquivo .env

É nele onde vamos colocar o BLOG_URL apontando para o http://localhost:7777 que é onde está rodando nosso projeto do blog.
.env

BLOG_URL=http://localhost:7777
Enter fullscreen mode Exit fullscreen mode

Agora dentro do nosso projeto da home vamos transformar o index.tsx nisso daqui:

import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import Link from 'next/link'
import styles from '../styles/Home.module.css'

const Home: NextPage = () => {
  return (
    <div className={styles.container}>
      <Head>
        <title>Next.js Blog With Multi Zones</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>
          Welcome to <Link href="/">Home!</Link> :D
        </h1>

        <div className={styles.grid}>
          <a href="/blog" className={styles.card}>
            <h2>Go Blog &rarr;</h2>
            <p>Click here and go home on our other Next.js app :D</p>
          </a>

          <Link href="/about" passHref>
            <a href="/about" className={styles.card}>
              <h2>About us &rarr;</h2>
              <p>Click here and go to About Us page!</p>
            </a>
          </Link>

          <a href="/blog/posts/hello-hello" className={styles.card}>
            <h2>Go to Hello post &rarr;</h2>
            <p>Click here and go to the Hello Hello post</p>
          </a>
        </div>
      </main>

      <footer className={styles.footer}>
        <a
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{' '}
          <span className={styles.logo}>
            <Image src="/vercel.svg" alt="Vercel Logo" width={72} height={16} />
          </span>
        </a>
      </footer>
    </div>
  )
}

export default Home
Enter fullscreen mode Exit fullscreen mode

Basicamente adicionamos 3 links, sendo 2 deles para páginas do nosso blog (ainda não construído) e 1 link para o redirecionamento para uma página interna nossa que é a About Us.

Home page

Agora vamos criar o arquivo about.tsx dentro de home/pages/about.tsx:

Local onde vai ficar o nosso arquivo about.tsx
about.tsx

import type { NextPage } from 'next'
import Link from 'next/link'

const About: NextPage = () => {
  return (
    <div>
      <p>About us :O</p>
      <hr />
      <div>
        <Link href="/">
          <a>Go home</a>
        </Link>
      </div>
    </div>
  )
}

export default About
Enter fullscreen mode Exit fullscreen mode

Aqui criamos uma página sobre nós bem simples que só tem um texto e um link que nos faz voltar para a home.

E assim finalizamos a parte da Home. Agora bora pro Blog!

Configurando o Blog (Aplicação 2)

Agora vamos configurar o blog. No blog vai ser um pouco mais simples, basicamente vamos abrir o arquivo next.config.js e adicionar a propriedade basePath dentro do nextConfig, ele vai dizer para o next que a URL base dele vai começar no endereço que escolhermos, que nesse caso vai ser /blog
next.config.js

const nextConfig = {
  basePath: '/blog',
}

module.exports = nextConfig
Enter fullscreen mode Exit fullscreen mode

Lembrando que toda vez que alteramos o arquivo next.config.js ou adicionamos algo no .env precisamos parar o servidor e inicia-lo novamente 😁

Agora dentro do nosso projeto da blog vamos transformar o index.tsx nisso daqui:

import type { NextPage } from 'next'
import Head from 'next/head'
import Image from 'next/image'
import Link from 'next/link'
import styles from '../styles/Home.module.css'

const Blog: NextPage = () => {
  return (
    <div className={styles.container}>
      <Head>
        <title>Next.js Blog With Multi Zones</title>
        <meta name="description" content="Generated by create next app" />
        <link rel="icon" href="/blog/favicon.ico" />
      </Head>

      <main className={styles.main}>
        <h1 className={styles.title}>
          Welcome to <Link href="/">Blog!</Link>
        </h1>

        <div className={styles.grid}>
          <a href="/" className={styles.card}>
            <h2>Go Home &rarr;</h2>
            <p>Click here and go home on our other Next.js app :D</p>
          </a>

          <Link href="/posts/it-works" passHref>
            <a href="/blog/posts/it-works" className={styles.card}>
              <h2>Go to It Works post &rarr;</h2>
              <p>Click here and go to the It Works post</p>
            </a>
          </Link>

          <Link href="/posts/hello-hello" passHref>
            <a href="/blog/posts/hello-hello" className={styles.card}>
              <h2>Go to Hello post &rarr;</h2>
              <p>Click here and go to the Hello Hello post</p>
            </a>
          </Link>
        </div>
      </main>

      <footer className={styles.footer}>
        <a
          href="https://vercel.com?utm_source=create-next-app&utm_medium=default-template&utm_campaign=create-next-app"
          target="_blank"
          rel="noopener noreferrer"
        >
          Powered by{' '}
          <span className={styles.logo}>
            <Image
              src="/blog/vercel.svg"
              alt="Vercel Logo"
              width={72}
              height={16}
            />
          </span>
        </a>
      </footer>
    </div>
  )
}

export default Blog
Enter fullscreen mode Exit fullscreen mode

Na raiz do nosso blog temos 1 link que leva para nossa Home e 2 links que nos levam a posts no nosso blog

Blog page

Na imagem acima vocês já conseguem ver a mágica acontecendo, se vocês olharem para o URL vão perceber que estamos rodando no http://localhost:4444/blog, mas por quê isso acontece?

Quando configuramos o basePath dentro do next.config.js do projeto Blog, dizemos para o next que o index.tsx e todos os outros arquivos vão ser acessados sempre a partir do nosso basePath que nesse caso é /blog.

Também devemos nos lembrar que no next.config.js do nosso projeto Home configuramos que sempre que estivermos em http://localhost:4444 e acessarmos o /blog ou qualquer coisa depois de blog, estaremos fazendo um rewrite da rota e estaremos apontando para o nosso Blog via Home.

Ou seja: http://localhost:4444/blog vai apontar para http://localhost:7777/blog

O mais incrível de tudo isso é que conseguimos acessar a nossa outra aplicação (blog) dentro da nossa aplicação (home) sem alterar a URL 🤯, não é impressionante?

Top comments (1)

Collapse
 
criskell profile image
criskell

belo post