Como integrar elixir phoenix e next.js no mesmo monorepo com PNPM
Voltar para blog

Como integrar elixir phoenix e next.js no mesmo monorepo com PNPM

14/06/2026 · 2 min · Desenvolvimento

Acoplar a robustez da máquina virtual do Erlang (BEAM) rodando Elixir (Phoenix) no backend com uma interface moderna em Next.js/React gerenciada pelo PNPM no frontend sob uma estrutura de monorepo híbrido é uma das decisões de arquitetura mais resilientes para sistemas de alta concorrência.

O desafio reside em coordenar os lifecycles de compilação, o gerenciamento de assets, o ambiente de desenvolvimento local e a infraestrutura de deploy de forma coesa. Abaixo, detalho como estruturar essa integração para produção.

1. A estrutura do monorepo#

Para evitar misturar dependências do Node com arquivos do Elixir na raiz do projeto, estruturo os ecossistemas de forma isolada dentro de pastas do diretório apps:

/meu-projeto-monorepo
  ├── apps/
  │    ├── backend/                    # Elixir Phoenix (BEAM)
  │    │    ├── lib/
  │    │    ├── config/
  │    │    ├── priv/static/           # Destino dos assets estáticos
  │    │    └── mix.exs
  │    └── frontend/                   # Next.js / React (Node.js/V8)
  │         ├── src/
  │         ├── public/
  │         ├── next.config.js
  │         └── package.json
  ├── package.json                     # Root do monorepo Node
  ├── pnpm-workspace.yaml              # Definição de escopo do workspace Node
  ├── docker-compose.yml               # Orquestração local de serviços
  ├── Makefile                         # Atalhos de comandos do projeto
  └── .github/workflows/ci.yml         # Pipeline de integração contínua

O arquivo pnpm-workspace.yaml na raiz especifica a pasta do frontend:

# pnpm-workspace.yaml
packages:
  - 'apps/frontend'

2. Estratégias de integração entre frontend e backend#

Abordagem a: static export (SSG/SPA integrado)#

Ideal para painéis administrativos onde as views são servidas de forma estática pelo endpoint HTTP do Phoenix (priv/static):

Abordagem b: servidor híbrido (SSR separado)#

Recomendado se o frontend necessita de Server-Side Rendering (SSR) dinâmico do Next.js ou otimização pesada de imagens:

3. Configuração do next.config.js#

Para abordagem a (static export):#

// apps/frontend/next.config.js
module.exports = {
  output: 'export',
  distDir: 'out',
  images: {
    unoptimized: true,
  },
};

Script de sincronização no package.json do frontend:

{
  "scripts": {
    "build": "next build",
    "postbuild": "rsync -av --delete --exclude=\"phoenix_dashboard/\" out/ ../backend/priv/static/"
  }
}

4. Phoenix watchers e hot module replacement (HMR)#

Para rodar todo o ambiente em um único comando no desenvolvimento, integre o lifecycle do Next.js aos Watchers do Phoenix no apps/backend/config/dev.exs:

config :backend, BackendWeb.Endpoint,
  http: [port: 4000],
  debug_errors: true,
  code_reloader: true,
  check_origin: false,
  watchers: [
    pnpm: [
      "run",
      "dev",
      cd: Path.expand("../../frontend", __DIR__)
    ]
  ]

5. Dockerização multi-stage#

# apps/backend/Dockerfile
FROM elixir:1.16-alpine AS builder

RUN apk add --no-cache build-base git
WORKDIR /app
RUN mix local.hex --force && mix local.rebar --force
ENV MIX_ENV=prod

COPY mix.exs mix.lock ./
RUN mix deps.get --only prod && mix deps.compile

COPY config config
COPY lib lib
COPY priv priv

RUN mix compile && mix release

FROM alpine:3.19 AS runtime
RUN apk add --no-cache libstdc++ openssl ncurses-libs bash
WORKDIR /app
COPY --from=builder /app/_build/prod/rel/backend ./

ENV PORT=4000
EXPOSE 4000
CMD ["./bin/server"]

6. Alta disponibilidade na BEAM#

A máquina virtual BEAM oferece tolerância a falhas nativa através de árvores de supervisão (Supervisor Trees) e clustering de nós distribuídos sem necessidade de brokers externos como Redis:

def start(_type, _args) do
  children = [
    Backend.Repo,
    BackendWeb.Telemetry,
    {Phoenix.PubSub, name: Backend.PubSub},
    BackendWeb.Endpoint
  ]

  opts = [strategy: :one_for_one, name: Backend.Supervisor]
  Supervisor.start_link(children, opts)
end

Recomendações para monorepos híbridos#

  1. Isole os workspaces: Mantenha dependências do Node restritas ao frontend e bibliotecas Hex no backend.
  2. Utilize o Makefile como orquestrador local: Um comando único (make dev ou make test) simplifica a integração de novos membros no time.
  3. Configure healthchecks no proxy: Garanta que o Nginx teste a disponibilidade de ambas as portas antes de encaminhar tráfego de produção.

Este artigo foi útil?

Deixe uma reação rápida para apoiar o conteúdo:

CC BY-NC

Este post está licenciado sob CC BY-NC.

Comentários

Participe da discussão abaixo.

0 comentários