- A equipe do Hardcover migrou para Ruby on Rails + Inertia.js devido a queda de desempenho na arquitetura baseada em Next.js, custos altos e redução na velocidade de desenvolvimento
- Escolheu o Inertia.js para atender aos requisitos de SSR com suporte a SEO, conexão direta com o banco de dados e manter o React
- A explosão inesperada de custos na Vercel e no Cloud Run, além da incerteza do cache no Next.js, foram os fatores decisivos para a mudança
- O Inertia.js se mostrou a forma ideal de conectar o backend Rails ao frontend React, facilitando SSR e gerenciamento de cache
- Após a transição, as pontuações no Google Pagespeed e em SEO melhoraram, e o tempo de permanência no site e a visibilidade na busca aumentaram
Contexto da mudança
- No início, a equipe escolheu o Next.js com suporte a SEO e SSR e construiu uma arquitetura baseada em API GraphQL
- A maior parte dos dados era solicitada no cliente pelo navegador, enquanto os dados estáticos eram armazenados em cache no servidor
- Com o tempo, surgiram mais requisições de API por falta de cache, queda de desempenho e lentidão no ambiente de desenvolvimento
Problemas que surgiram no Next.js
- Mesmo após a migração para o App Router, o ganho de velocidade foi mínimo; como as requisições POST do Apollo não eram armazenadas em cache, o efeito esperado não apareceu
- Com a mudança na política de preços da Vercel, a cobrança mensal saltou de $30 para $354
- O Cloud Run também era barato no início, mas subiu até $524
- Era difícil entender a estrutura de cache do Next.js, o que impedia uma gestão eficiente
- A velocidade de desenvolvimento caiu de forma significativa, dificultando o onboarding de novos integrantes
Por que escolher Rails + Inertia.js
- A equipe queria manter o SSR e, ao mesmo tempo, buscar dados diretamente no banco de dados
- Também queria continuar usando React; Remix, react-rails e react_on_rails foram avaliados, mas no fim a escolha foi inertia-rails
- Com o Inertia.js, é possível usar o roteamento do Rails sem roteamento no frontend, e o SSR também fica mais simples
- Nos controllers, a renderização é tratada com
inertia: '페이지명', e o cache é implementado com Rails.cache.fetch
- Nos componentes React, as props são recebidas com
usePage()
Estrutura de SSR e build
- Para SSR, em
application.tsx é feito o tratamento condicional entre hydrateRoot e createRoot
- O Vite roda como servidor independente e oferece hot reload durante o desenvolvimento
- A equipe automatizou o deploy de Rails + Vite com Docker e Kamal, separando staging e production
- No deploy, a execução é feita com o comando
make deploy, e o asset host usa CloudFlare para otimizar o cache
Efeitos da transição
- Após o deploy da migração em 18 de março de 2025, houve aumento da visibilidade no Google Search e melhora na velocidade das páginas
- O Total Blocking Time melhorou bastante, elevando a pontuação no Pagespeed
- O tempo médio de permanência dos visitantes mostrou tendência de alta, passando de 3 minutos para 6 minutos
- O tráfego foi mantido, enquanto o número de cadastros permaneceu estável
Desafios futuros e pontos de melhoria
- Ainda há dificuldade para reutilizar layouts comuns e o problema de rerenderização completa de cada página
- Depurar SSR é difícil, e a configuração do ambiente é complexa
- Há falta de documentação para a combinação de Inertia.js com Rails, então a equipe buscou soluções na comunidade do Discord
- É preciso se adaptar à forma de trabalhar do Inertia em vez de usar Suspense
- No momento, a equipe continua usando Hasura, então alguns recursos do Inertia, como form e flash, ainda não são aproveitados
Conclusão e expectativas
- A estrutura integrou React + Rails de forma natural, trazendo melhor produtividade de desenvolvimento e manutenção
- Com a escolha do Inertia.js, a equipe garantiu ao mesmo tempo velocidade, SSR e segurança de tipos
- Daqui para frente, há planos de abrir o projeto como open source e atrair contribuidores
2 comentários
Ao usar
Linkno Next.js, está havendo polêmica por causa da parte em que a URL é gerada e processada em um formato como?_rsc=1ip3ipara usar React Server Components. Também se ouve dizer que os custos com CDN dispararam, e que a equipe de desenvolvimento do Next.js já está ciente desse problema, mas ainda não está definido de que forma nem quando isso será resolvido.Comentários do Hacker News
A renderização no lado do servidor (SSR) nunca desapareceu, e a web só agora está se lembrando do motivo de isso ter sido o padrão. A primeira renderização e o SEO ainda funcionam melhor quando o markup vem do servidor. Vários frameworks, como Rails + Turbo, HTMX, Phoenix LiveView e React Server Components, adotam SSR como padrão. A maioria dos dashboards e apps CRUD não precisa de roteador no cliente, estado global nem de um bundle de hidratação de 200 kB, apenas de substituição parcial de HTML
O verdadeiro motor aqui é o custo da complexidade. Cada linha de JS no cliente traz ferramentas de build, ruído de auditoria do npm e risco na cadeia de suprimentos. Reduzir essa carga melhora desempenho e segurança ao mesmo tempo. Claro, apps como Figma ou Gmail ainda se beneficiam de lógica pesada no cliente. Por isso está surgindo o padrão de “HTML por padrão, JS só onde for necessário”. É melhor pensar em ilhas do que em um SPA completo
Então há, sim, um retorno ao servidor, mas isso não é nostalgia de PHP de 2004. É ajustar o JavaScript ao lugar certo e deixar o HTML fazer os 90% de trabalho entediante que ele sempre fez bem
Usamos NextJS em alguns projetos, mas já estamos descontinuando isso aos poucos. Há vários motivos, mas alguns fatores principais são os seguintes
A história de autenticação é difícil.
next-authtem algumas limitações, então acabamos usandoiron-session. Por exemplo, não dava para usar domínios dinâmicos de provedores de ID, então tivemos de assumir todo o fluxo de openid. Era possível, mas foi um gasto de tempo inesperado para um framework maduroComo o servidor NextJS não era nosso principal gateway de API, tivemos de fazer proxy de todas as requisições. A documentação não era clara, e isso ainda adicionou problemas aleatórios, como timeout de requisição/tamanho máximo de cabeçalho etc.
O framework empurrava de forma muito agressiva a migração para a nuvem, o que entrava em conflito com nossos objetivos
Os mantenedores não foram especialmente úteis. Usamos outras ferramentas/frameworks apesar dos defeitos porque os mantenedores são muito acessíveis e prestativos (obrigado ao Chillicream/HotChocolate)
Lembro de ter lido no ano passado um post de blog dizendo que o SEO melhorou ao migrar do pages router para o app router no Next.js. Desta vez estamos saindo de Next para React+Inertia.js por causa do aumento dos custos da Vercel. Implantar o mesmo app em nosso próprio VPS em vez de usar um provedor de nuvem resolveria o problema. Mas eu não entendo por que querer a complexidade. Fico me perguntando se um app de rastreamento de livros realmente precisava de GraphQL, de um framework de frontend separado e de um processo de build complexo, ou se isso não poderia ter sido resolvido desde o início implantando um único app em RoR com templates HTML em um VPS
Sempre que vejo artigos e discussões sobre a web e a stack, acabo fazendo a pergunta: “que problema isso está realmente resolvendo?”. A resposta é sempre “mostrar texto na tela”
Fico curioso sobre o que as pessoas fazem quando querem full stack em JS, especialmente quando há banco de dados envolvido. A situação de ORM é bem fragmentada, ou então é preciso escrever SQL puro. E ainda é preciso decidir o backend. Vai usar
express? Next.js é conhecido, mas tem uma agenda questionável. Remix, Astro, TanStack etc. É confuso, porque você sempre tem de recalibrar e reavaliar o que usarEm projetos pessoais, muitas vezes acabo voltando para Ruby on Rails. É sempre um prazer. Por outro lado, há poucos desenvolvedores Rails disponíveis (em comparação com JS), então não serve muito bem para projetos profissionais. Escolher JS e muitas vezes Java para o backend parece irresponsável
Fico me perguntando se mais alguém sente algo parecido
Desenvolvedores de frontend e backend não se comunicaram muito bem por muito tempo
Historicamente, como desenvolvedor backend, eu odiava Html/JS/CSS. É um paradigma significativamente diferente de Swing/Awt, WinForms, Android UX etc. Só isso já me frustrava e me fazia continuar no backend. Para aprender frontend, era preciso aprender essas três coisas. Só agora estou me acostumando
Mas os desenvolvedores frontend precisavam aprender “mais uma linguagem”. Muitas linguagens tinham sistemas de build diferentes/incômodos em comparação com o nvm. E, como qualquer pessoa que já mudou de linguagem sabe, também era preciso aprender novos frameworks, paradigmas etc.
Então alguns perceberam que dava para empurrar JavaScript para o backend. Havia muitas desvantagens, mas, para quem “faz acontecer”, especialmente no mundo de “é só adicionar mais servidores” e “dinheiro de VC é grátis! queime em infraestrutura!”, essas desvantagens não eram algo com que se preocupar
Mas os desenvolvedores frontend, agora “desenvolvedores full stack”, mas na prática “desenvolvedores de tudo em JavaScript”, continuam criando de maneiras bem visíveis. Isso se reflete hoje nas vagas do LinkedIn, que pedem funções com Next.JS/Node.JS/outras. Uma única linguagem para governar tudo
Só algumas reflexões, mas acho que isso está fortemente relacionado ao motivo pelo qual as pessoas escolhem Next.JS
Não posso falar do lado técnico (só conheço Next.js e não Rails, então não está claro para mim se este texto reflete o conforto do autor com Rails ou uma arquitetura tecnicamente mais adequada). Mas acho estranho uma empresa com vários engenheiros de software se preocupar com custos de infraestrutura abaixo de 1.000 dólares por mês. Não parece sábio se preocupar com custo de hospedagem
Se Rails tivesse focado em suporte de primeira classe e realmente nativo para interoperabilidade com frameworks de frontend, já seria muito maior hoje. Eles colocaram muito esforço em Hotwire, mas eu quero usar React, e outras pessoas também vão querer usar aquilo com que já estão acostumadas
Fico me perguntando por que existe uma discussão Next.js vs. SSR. Next.js é híbrido e faz isso muito bem. Em contraste com outros frameworks SPA, Next.js gera HTML pré-renderizado para carregamento inicial rápido, oferece switches de configuração para chunks de JS eficientes, pré-carregamento ao passar o mouse sobre links ou de todos os links n+1 após a renderização da página, e oferece carregamento de imagem eficiente (prévio) conforme os breakpoints (o que normalmente é o calcanhar de Aquiles em comparação com soluções puras de SSR)
Já escrevi um pouco de Rails, mas não entendo muito bem por que tanta empolgação. Achei totalmente ok, mas não encontrei nada de especial