Como migrar do jQuery para o Next.js
Publicados: 2022-03-10Este artigo foi gentilmente apoiado por nossos queridos amigos da Netlify, que são um grupo diversificado de talentos incríveis de todo o mundo e oferece uma plataforma para desenvolvedores web que multiplica a produtividade. Obrigado!
Quando o jQuery apareceu em 2006, muitos desenvolvedores e organizações começaram a adotá-lo para seus projetos. A possibilidade de estender e manipular o DOM que a biblioteca oferece é grande, e também temos muitos plugins para adicionar comportamento às nossas páginas caso precisemos fazer tarefas que não são suportadas pela biblioteca principal do jQuery. Simplificou muito o trabalho dos desenvolvedores e, naquele momento, tornou o JavaScript uma linguagem poderosa para criar aplicativos web ou aplicativos de página única.
O resultado da popularidade do jQuery é mensurável ainda hoje: quase 80% dos sites mais populares do mundo ainda o utilizam. Algumas das razões pelas quais o jQuery é tão popular são:
- Ele suporta manipulação DOM.
- Ele fornece manipulação CSS.
- Funciona da mesma forma em todos os navegadores da web.
- Ele envolve métodos de evento HTML.
- Fácil de criar chamadas AJAX.
- Efeitos e animações fáceis de usar.
Ao longo dos anos, o JavaScript mudou muito e adicionou vários recursos que não tínhamos no passado. Com a redefinição e evolução do ECMAScript, algumas das funcionalidades fornecidas pelo jQuery foram adicionadas aos recursos padrão do JavaScript e suportadas por todos os navegadores da web. Com isso acontecendo, alguns dos comportamentos que o jQuery oferece não eram mais necessários , pois podemos fazer as mesmas coisas com JavaScript simples.
Por outro lado, uma nova maneira de pensar e projetar interfaces de usuário começou a surgir. Frameworks como React, Angular ou Vue permitem que os desenvolvedores criem aplicações web baseadas em componentes funcionais reutilizáveis. React, ou seja, trabalha com o “DOM virtual”, que é uma representação do DOM na memória, enquanto o jQuery interage diretamente com o DOM , de forma menos performática. Além disso, o React oferece recursos interessantes para facilitar o desenvolvimento de determinados recursos, como gerenciamento de estado. Com essa nova abordagem e a popularidade que os aplicativos de página única começaram a ganhar, muitos desenvolvedores começaram a usar o React para seus projetos de aplicativos da web.
E o desenvolvimento front-end evoluiu ainda mais, com frameworks criados em cima de outros frameworks. É o caso, por exemplo, do Next.js. Como você provavelmente sabe, é uma estrutura React de código aberto que oferece recursos para gerar páginas estáticas, criar páginas renderizadas no lado do servidor e combinar os dois tipos no mesmo aplicativo. Também permite criar APIs sem servidor dentro do mesmo aplicativo.
Há um cenário curioso: embora esses frameworks de front-end sejam cada vez mais populares ao longo dos anos, o jQuery ainda é adotado pela grande maioria das páginas da web. Uma das razões pelas quais isso acontece é que a porcentagem de sites usando WordPress é muito alta, e o jQuery está incluído no CMS . Outro motivo é que algumas bibliotecas, como o Bootstrap, possuem dependência do jQuery, e existem alguns templates prontos para uso que o utilizam e seus plugins.
Mas outro motivo para essa quantidade de sites usando jQuery é o custo de migrar uma aplicação web completa para um novo framework. Não é fácil, não é barato e é demorado. Mas, no final das contas, trabalhar com novas ferramentas e tecnologias traz muitos benefícios: suporte mais amplo, assistência à comunidade, melhor experiência do desenvolvedor e facilidade de fazer as pessoas trabalharem no projeto.
Existem muitos cenários em que não precisamos (ou não queremos) seguir a arquitetura que frameworks como React ou Next.js nos impõem, e tudo bem. No entanto, jQuery é uma biblioteca que contém muito código e recursos que não são mais necessários. Muitos dos recursos que o jQuery oferece podem ser realizados usando funções nativas JavaScript modernas e, provavelmente, de uma maneira mais eficiente.
Vamos discutir como podemos parar de usar jQuery e migrar nosso site para uma aplicação web React ou Next.js.
Definir a estratégia de migração
Precisamos de uma biblioteca?
Dependendo dos recursos do nosso aplicativo da web, podemos até ter o caso em que um framework não é realmente necessário. Como mencionado anteriormente, vários recursos do jQuery foram incluídos (ou pelo menos um muito semelhante) às últimas versões padrão da web. Então, considerando que:
- O padrão
$(selector)
do jQuery pode ser substituído porquerySelectorAll()
.
Em vez de fazer:
$("#someId");
Nós podemos fazer:
document.querySelectorAll("#someId");
- Temos agora a propriedade
Element.classList
se quisermos manipular classes CSS.
Em vez de fazer:
$(selector).addClass(className);
Nós podemos fazer:
element.classList.add(className);
- Muitas animações podem ser feitas diretamente usando CSS, em vez de implementar JavaScript.
Em vez de fazer:
$(selector).fadeIn();
Nós podemos fazer:
element.classList.add('show'); element.classList.remove('hide');
E aplique algum estilo CSS:
.show { transition: opacity 400ms; } .hide { opacity: 0; }
- Agora temos a função addEventListener se quisermos manipular eventos.
Em vez de fazer:
$(selector).on(eventName, eventHandler);
Nós podemos fazer:
element.addEventListener(eventName, eventHandler);
- Em vez de usar jQuery Ajax, podemos usar
XMLHttpRequest
.
Em vez de fazer:
$.ajax({ type: 'POST', url: '/the-url', data: data });
Nós podemos fazer:
var request = new XMLHttpRequest(); request.open('POST', '/the-url', true); request.setRequestHeader('Content-Type', 'application/x-www-form-urlencoded; charset=UTF-8'); request.send(data);
Para mais detalhes, você pode dar uma olhada nestes trechos de código JavaScript Vanilla.
Identificar componentes
Se estivermos usando jQuery em nossa aplicação, devemos ter algum conteúdo HTML gerado no servidor web e código JavaScript que adiciona interatividade à página. Provavelmente estamos adicionando manipuladores de eventos no carregamento da página que manipularão o DOM quando os eventos acontecerem, provavelmente atualizando o CSS ou o estilo dos elementos. Também poderíamos estar chamando serviços de backend para executar ações, que podem afetar o DOM da página, ou até mesmo recarregá-lo.
A ideia seria refatorar o código JavaScript que vive nas páginas e construir componentes React. Isso nos ajudará a unir código relacionado e compor elementos que farão parte de uma composição maior. Ao fazer isso, também poderemos ter um melhor manuseio do estado de nossa aplicação. Analisando o frontend do nosso aplicativo, devemos dividi-lo em partes dedicadas a uma determinada tarefa, para que possamos criar componentes com base nisso.
Se tivermos um botão:
<button>Click</button>
Com a seguinte lógica:
var $btnAction = $("#btn-action"); $btnAction.on("click", function() { alert("Button was clicked"); });
Podemos migrá-lo para um React Component:
import React from 'react'; function ButtonComponent() { let handleButtonClick = () => { alert('Button clicked!') } return <button onClick={handleButtonClick}>Click</button> }
Mas também devemos avaliar como o processo de migração será realizado, já que nosso aplicativo está funcionando e sendo usado, e não queremos afetá-lo (ou, pelo menos, afetá-lo o mínimo possível).
Boa migração
Uma boa migração é aquela em que todas as partes do aplicativo são totalmente migradas para a nova estrutura ou tecnologia. Este seria o cenário ideal para nossa aplicação, pois manteríamos todas as partes em sincronia, e estaríamos utilizando uma ferramenta unificada e uma versão referenciada única.
Uma migração boa e completa geralmente inclui uma reescrita completa do código do nosso aplicativo, e isso faz sentido. Se construirmos um aplicativo do zero, temos a possibilidade de decidir qual direção queremos tomar com o novo código. Poderíamos usar um novo ponto de vista sobre nossos sistemas e fluxos de trabalho existentes e criar um aplicativo totalmente novo com o conhecimento que temos neste momento, mais completo do que o que tínhamos quando criamos nosso aplicativo da web.
Mas uma reescrita completa tem alguns problemas. Em primeiro lugar, requer muito tempo. Quanto maior o aplicativo, mais tempo precisaremos para reescrevê-lo. Outro problema é a quantidade de trabalho e a quantidade de desenvolvedores necessários. E, se não fizermos uma migração progressiva, temos que pensar em quanto tempo nosso aplicativo ficará indisponível.
Normalmente, uma reescrita completa pode ser realizada com projetos pequenos, projetos que não mudam com frequência ou aplicativos que não são tão críticos para nossos negócios.
Migração rápida
Outra abordagem é dividir o aplicativo em partes ou partes. Migramos o aplicativo parte por parte e liberamos essas partes quando estiverem prontas. Assim, migramos partes de nosso aplicativo disponíveis para os usuários e coexistindo com nosso aplicativo de produção existente.
Com essa migração gradual, entregamos recursos separados do nosso projeto de forma mais rápida aos usuários, já que não precisamos esperar que a aplicação completa seja reescrita. Também recebemos feedback mais rápido dos usuários, o que nos permite detectar bugs ou problemas mais cedo.
Mas uma migração gradual nos leva a ter diferentes ferramentas, bibliotecas, dependências e frameworks. Ou podemos até ter que suportar diferentes versões da mesma ferramenta. Esse suporte estendido pode trazer conflitos ao nosso aplicativo.
Podemos até ter problemas se estivermos aplicando políticas no escopo global, pois cada uma das partes migradas pode funcionar de uma maneira diferente, mas sendo afetada pelo código que define os parâmetros globais do nosso sistema. Um exemplo disso é o uso de uma lógica em cascata para estilo CSS.
Imagine que trabalhamos com diferentes versões do jQuery em nosso aplicativo da Web porque adicionamos funcionalidades de versões mais recentes aos módulos que foram criados posteriormente. Quão complicado seria migrar todo o nosso aplicativo para uma versão mais recente do jQuery? Agora, imagine o mesmo cenário, mas migrando para uma estrutura completamente diferente, como Next.js. Isso pode ser complicado.
Migração de Frankenstein
Denys Mishunov escreveu um artigo na Smashing Magazine apresentando uma alternativa a essas duas ideias de migração, tentando obter o melhor das duas abordagens anteriores: A migração de Frankenstein. Baseia o processo de migração em dois componentes principais: Microsserviços e Componentes Web.
O processo de migração consiste em uma lista de etapas a serem seguidas:
1. Identifique os microsserviços
Com base no código do nosso aplicativo, devemos dividi-lo em partes independentes dedicadas a um pequeno trabalho. Se estivermos pensando em usar React ou Next.js, podemos vincular o conceito de microsserviços aos diferentes componentes que temos.
Vamos pensar em um aplicativo de lista de compras como exemplo. Temos uma lista de coisas para comprar e uma entrada para adicionar mais coisas à lista. Então, se quisermos dividir nosso aplicativo em pequenas partes, podemos pensar em um componente “lista de itens” e um “adicionar item”. Fazendo isso, podemos separar a funcionalidade e marcação relacionada a cada uma dessas partes em diferentes componentes do React.
Para confirmar que os componentes são independentes, devemos remover um deles do aplicativo e os outros não devem ser afetados por isso. Se recebermos um erro ao remover a marcação e a funcionalidade de um serviço, não estamos identificando corretamente os componentes ou precisamos refatorar a maneira como nosso código funciona.
2. Permitir acesso de host para estrangeiro
“Host” é o nosso aplicativo existente. “Alien” é o que vamos começar a criar, com o novo framework. Ambos devem funcionar de forma independente, mas devemos fornecer acesso do Host ao Alien. Devemos ser capazes de implantar qualquer um dos dois aplicativos sem quebrar o outro, mas mantendo a comunicação entre eles.
3. Escreva um componente estrangeiro
Reescreva um serviço de nosso aplicativo Host em nosso aplicativo Alien, usando a nova estrutura. O componente deve seguir o mesmo princípio de independência que mencionamos anteriormente.
Vamos voltar ao exemplo da lista de compras. Identificamos um componente “adicionar item”. Com jQuery, a marcação do componente será algo assim:
<input class="new-item" />
E o código JavaScript/jQuery para adicionar os itens à lista será algo assim:
var ENTER_KEY = 13; $('.new-item').on('keyup', function (e) { var $input = $(e.target); var val = $input.val().trim(); if (e.which !== ENTER_KEY || !val) { return; } // code to add the item to the list $input.val(''); });
Em vez disso, podemos criar um componente AddItem
React:
import React from 'react' function AddItemInput({ defaultText }) { let [text, setText] = useState(defaultText) let handleSubmit = e => { e.preventDefault() if (e.which === 13) { setText(e.target.value.trim()) } } return <input type="text" value={text} onChange={(e) => setText(e.target.value)} onKeyDown={handleSubmit} /> }
4. Gravar o wrapper do componente da Web em torno do serviço estrangeiro
Crie um componente wrapper que importe nosso serviço Alien recém-criado e o renderize. A ideia é criar uma ponte entre o aplicativo Host e o aplicativo Alien. Lembre-se de que podemos precisar de um empacotador de pacotes para gerar código JavaScript que funcione em nosso aplicativo atual, pois precisaremos copiar nossos novos componentes React e fazê-los funcionar.
Seguindo o exemplo da lista de compras, podemos criar um arquivo AddItem-wrapper.js
no projeto Host. Este arquivo conterá o código que envolve nosso componente AddItem
já criado e cria um elemento personalizado com ele:
import React from "../alien/node_modules/react"; import ReactDOM from "../alien/node_modules/react-dom"; import AddItem from "../alien/src/components/AddItem"; class FrankensteinWrapper extends HTMLElement { connectedCallback() { const appWrapper = document.createElement("div"); appWrapper.classList.add("grocerylistapp"); ... ReactDOM.render( <HeaderApp />, appWrapper ); … } } customElements.define("frankenstein-add-item-wrapper", FrankensteinWrapper);
Devemos trazer os módulos e componentes de nós necessários das pastas do aplicativo Alien, pois precisamos importá-los para que o componente funcione.
5. Substitua o serviço de host pelo componente da Web
Esse componente wrapper substituirá o componente do aplicativo Host e começaremos a usá-lo. Portanto, o aplicativo em produção será uma mistura de componentes Host e componentes encapsulados Alien.
Em nosso exemplo de aplicação Host, devemos substituir:
<input class="new-item" />
Com
<frankenstein-add-item-wrapper></frankenstein-add-item-wrapper> ... <script type="module" src="js/AddItem-wrapper.js"></script>
6. Enxágue e Repita
Siga as etapas 3, 4 e 5 para cada um dos microsserviços identificados.
7. Mude para Alien
Host agora é uma coleção de componentes wrapper que incluem todos os componentes da Web que criamos no aplicativo Alien. Como convertemos todos os microsserviços identificados, podemos dizer que o aplicativo Alien foi finalizado e todos os serviços foram migrados. Só precisamos apontar nossos usuários para o aplicativo Alien agora.
O método Frankenstein Migration funciona como uma combinação das abordagens Good e Fast. Migramos o aplicativo completo, mas liberamos os diferentes componentes quando eles são concluídos. Assim, eles ficam disponíveis para serem usados mais cedo e avaliados pelos usuários em produção.
Temos que considerar, no entanto, que estamos fazendo um trabalho excessivo com essa abordagem. Se quisermos usar os componentes que criamos para nosso aplicativo Alien, precisamos criar um componente wrapper para incluir no aplicativo Host. Isso nos faz gastar tempo desenvolvendo o código para esses elementos wrapper. Além disso, ao usá-los em nosso aplicativo Host, estamos duplicando a inclusão de código e dependências e adicionando código que afetará o desempenho de nosso aplicativo.
Aplicação do Estrangulador
Outra abordagem que podemos adotar é o Legacy Application Strangulation. Identificamos as bordas da nossa aplicação web existente, e sempre que precisamos adicionar funcionalidades ao nosso app fazemos isso usando um framework mais novo até que o sistema antigo seja “estrangulado”. Essa abordagem nos ajuda a reduzir o risco potencial que podemos experimentar ao migrar um aplicativo.
Para seguir essa abordagem, precisamos identificar diferentes componentes, como fazemos em Frankenstein Migration. Uma vez que dividimos nosso aplicativo em diferentes partes de código imperativo relacionado, nós os envolvemos em novos componentes React. Não adicionamos nenhum comportamento adicional, apenas criamos componentes React que renderizam nosso conteúdo existente.
Vejamos um exemplo para maiores esclarecimentos. Suponha que temos este código HTML em nosso aplicativo:
<div class="accordion"> <div class="accordion-panel"> <h3 class="accordion-header">Item 1</h3> <div class="accordion-body">Text 1</div> </div> <div class="accordion-panel"> <h3 class="accordion-header">Item 2</h3> <div class="accordion-body">Text 2</div> </div> <div class="accordion-panel"> <h3 class="accordion-header">Item 3</h3> <div class="accordion-body">Text 3</div> </div>> </div>
E esse código JavaScript (já substituímos as funções do jQuery por novos recursos padrão do JavaScript).
const accordions = document.querySelectorAll(".accordion"); for (const accordion of accordions) { const panels = accordion.querySelectorAll(".accordion-panel"); for (const panel of panels) { const head = panel.querySelector(".accordion-header"); head.addEventListener('click', () => { for (const otherPanel of panels) { if (otherPanel !== panel) { otherPanel.classList.remove('accordion-expanded'); } } panel.classList.toggle('accordion-expanded'); }); } }
Esta é uma implementação comum de um componente de accordion
para JavaScript. Como queremos apresentar o React aqui, precisamos envolver nosso código existente com um novo componente React:
function Accordions() { useEffect(() => { const accordions = document.querySelectorAll(".accordion") for (const accordion of accordions) { const panels = accordion.querySelectorAll(".accordion-panel") for (const panel of panels) { const head = panel.querySelector(".accordion-header") head.addEventListener("click", () => { for (const otherPanel of panels) { if (otherPanel !== panel) { otherPanel.classList.remove("accordion-expanded") } } panel.classList.toggle("accordion-expanded") }); } } }, []) return null } ReactDOM.render(<Accordions />, document.createElement("div"))
O componente não está adicionando nenhum novo comportamento ou recurso. Usamos useEffect
porque o componente foi montado no documento. É por isso que a função retorna null porque o gancho não precisa retornar um componente.
Portanto, não adicionamos nenhuma nova funcionalidade ao nosso aplicativo existente, mas introduzimos o React sem alterar seu comportamento. A partir de agora, sempre que adicionarmos novos recursos ou alterações em nosso código, faremos isso usando o framework selecionado mais recente.
Renderização do lado do cliente, renderização do lado do servidor ou geração estática?
Next.js nos dá a possibilidade de escolher como queremos renderizar cada página de nossa aplicação web. Podemos usar a renderização do lado do cliente que o React já nos oferece para gerar o conteúdo diretamente no navegador do usuário. Ou podemos renderizar o conteúdo de nossa página no servidor usando a renderização do lado do servidor. Finalmente, podemos criar o conteúdo da nossa página em tempo de construção usando geração estática.
Em nosso aplicativo, devemos carregar e renderizar o código no carregamento da página, antes de começarmos a interagir com qualquer biblioteca ou estrutura JavaScript. Podemos estar usando uma linguagem ou tecnologia de programação de renderização do lado do servidor, como ASP.NET, PHP ou Node.js. Podemos aproveitar os recursos do Next.js e substituir nosso método de renderização atual pelo método de renderização do lado do servidor Next.js . Fazendo isso, mantemos todo o comportamento dentro do mesmo projeto, que funciona sob o guarda-chuva do nosso framework selecionado. Além disso, mantemos a lógica da nossa página principal e os componentes do React dentro do mesmo código que gera todo o conteúdo necessário para nossa página.
Vamos pensar em uma página de painel como exemplo. Podemos gerar toda a marcação inicial da página no momento do carregamento, no servidor, ao invés de ter que gerá-la com React no navegador web do usuário.
const DashboardPage = ({ user }) => { return ( <div> <h2>{user.name}</h2> // User data </div> ) } export const getServerSideProps = async ({ req, res, params }) => { return { props: { user: getUser(), }, } }, }) export default DashboardPage
Se a marcação que renderizamos no carregamento da página for previsível e for baseada em dados que podemos recuperar em tempo de compilação, a geração estática seria uma boa escolha. A geração de ativos estáticos em tempo de compilação tornará nosso aplicativo mais rápido, mais seguro, escalável e mais fácil de manter. E, caso precisemos gerar conteúdo dinâmico nas páginas do nosso aplicativo, podemos usar a renderização do lado do cliente do React para recuperar informações de serviços ou fontes de dados.
Imagine que temos um site de blog, com muitos posts. Se usarmos Geração Estática, podemos criar um arquivo genérico [blog-slug].js
em nosso aplicativo Next.js e, adicionando o código a seguir, geraríamos todas as páginas estáticas para nossas postagens de blog em tempo de compilação.
export const getStaticPaths = async () => { const blogPosts = await getBlogPosts() const paths = blogPosts.map(({ slug }) => ({ params: { slug, }, })) return { paths, fallback: false, } } export const getStaticProps = async ({ params }) => { const { slug } = params const blogPost = await getBlogPostBySlug(slug) return { props: { data: JSON.parse(JSON.stringify(blogPost)), }, } }
Criar uma API usando rotas de API
Um dos grandes recursos que o Next.js oferece é a possibilidade de criar Rotas de API. Com eles, podemos criar nossas próprias funções serverless usando Node.js. Também podemos instalar pacotes NPM para estender a funcionalidade. Uma coisa legal sobre isso é que nossa API sairá no mesmo projeto/aplicativo que nosso frontend, então não teremos nenhum problema de CORS.
Se mantivermos uma API que é chamada de nosso aplicativo da web usando a funcionalidade jQuery AJAX, podemos substituí-la usando API Routes . Fazendo isso, manteremos toda a base de código do nosso aplicativo no mesmo repositório e simplificaremos a implantação do nosso aplicativo. Se estivermos usando um serviço de terceiros, podemos usar Rotas de API para “mascarar” as URLs externas.
Poderíamos ter uma rota de API /pages/api/get/[id].js
que retorna dados que usamos em nossa página.
export default async (req, res) => { const { id } = req.query try { const data = getData(id) res.status(200).json(data) } catch (e) { res.status(500).json({ error: e.message }) } }
E chame-o do código da nossa página.
const res = await fetch(`/api/get/${id}`, { method: 'GET', }) if (res.status === 200) { // Do something } else { console.error(await res.text()) }
Implantar no Netlify
Netlify é uma plataforma completa que pode ser usada para automatizar, gerenciar, construir, testar, implantar e hospedar aplicações web. Ele tem muitos recursos que tornam o desenvolvimento de aplicativos da Web modernos mais fácil e rápido. Alguns destaques da Netlify são:
- Plataforma global de hospedagem CDN,
- Suporte a funções sem servidor,
- Implante visualizações com base em solicitações pull do Github,
- Webhooks,
- Reversões instantâneas,
- Controle de acesso baseado em função.
O Netlify é uma ótima plataforma para gerenciar e hospedar nossos aplicativos Next.js, e é muito simples implantar um aplicativo da Web com ele.
Em primeiro lugar, precisamos acompanhar o código do nosso aplicativo Next.js em um repositório Git. O Netlify se conecta ao GitHub (ou à plataforma Git que preferirmos), e sempre que uma alteração é introduzida em um branch (um commit ou um Pull Request), uma tarefa automática de “build and deploy” será acionada.
Assim que tivermos um repositório Git com o código do nosso app, precisamos criar um “Netlify Site” para ele. Para isso, temos duas opções:
- Usando o Netlify CLI
Após instalarmos a CLI (npm install -g netlify-cli
) e entrar em nossa conta Netlify (ntl login
), podemos ir ao diretório raiz de nossa aplicação, executarntl init
e seguir os passos. - Usando o aplicativo Web Netlify
Devemos ir para https://app.netlify.com/start. Conecte-se ao nosso provedor Git, escolha o repositório do nosso aplicativo na lista, configure algumas opções de compilação e implante.
Para ambos os métodos, temos que considerar que nosso comando de compilação será a next build
e nosso diretório a ser implantado está out
.
Por fim, o plug-in Essential Next.js é instalado automaticamente, o que nos permitirá implantar e usar rotas de API, rotas dinâmicas e modo de visualização. E é isso, temos nosso aplicativo Next.js funcionando em um serviço de hospedagem CDN rápido e estável.
Conclusão
Neste artigo, avaliamos sites usando a biblioteca jQuery e os comparamos com novos frameworks frontend como React e Next.js. Definimos como poderíamos iniciar uma migração, caso nos beneficie, para uma ferramenta mais nova. Avaliamos diferentes estratégias de migração e vimos alguns exemplos de cenários que poderíamos migrar para projetos de aplicativos Web Next.js. Por fim, vimos como implantar nosso aplicativo Next.js no Netlify e colocá-lo em funcionamento.
Leitura e recursos adicionais
- Migração de Frankenstein: Abordagem agnóstica de framework
- Removendo jQuery do frontend do GitHub.com
- Primeiros passos com o Next.js
- Como implantar sites Next.js na Netlify
- Artigos Next.js no blog da Netlify