Minha motivação para dar início ao projeto foi devido a um insight que tive durante uma situação em minha vida de desenvolvedor, estava passando por alguns problemas na empresa que estou trabalhando e pensei em olhar o que o mercado estava buscando, me deparei com uma procura absurda por profissionais com proficiência em React e suas stacks.
Decidi parar para estudar de fato e conheci o Next.js logo em seguida, me apaixonei pela tecnologia e suas funcionalidades (que ainda nem sei todas).
Assim que comecei a estudar vi que era importante entender todo o eco sistema de uma aplicação que foi, esta sendo ou vai ser construída e reparei que nunca tive a experiência de criar e me preocupar com um ecossistema desses. Foi aí que decidi dar o pontapé nessa direção e comecei a estudar sobre quais tecnologias um projeto next.js deveria ter para ser sustentável, escalável e de fácil manutenção.
Inicialmente não pensei que poderia ser tao extenso a criação do projeto, mas foi, e hoje fico grato por passar por essa experiencia, com isso decidi dividir isso com quem quer que esteja lendo esse artigo, agradeço desde já por consultar aqui e espero que tenha ajudado de alguma forma.
Começando
Inicialmente vamos criar um projeto base do Next.js:
Lembrando que vamos precisar ter instalado uma versão do node a partir da versão 10.13.
Vamos rodar o create next app no terminal:
npx create-next-app nome_do_seu_projeto
Ele vai criar uma estrutura como essa:
Vamos entrar na pasta criada:
cd nome_do_seu_projeto
Caso queira ver o que o comando criou é só rodar no terminal:
yarn run dev
e no seu navegador, entrar no localhost:3000
Vamos excluir os arquivos que inicialmente não vamos utilizar:
pasta styles -> vamos criar ela dentro do src, na minha opinião e mais organizado.
Arquivos dentro da pasta public -> São assets da Vercel que não vamos usar.
pasta API dentro de pages -> Essa pasta serve para escrevermos funções que vão ser executadas no servidor da Vercel caso você queira hospedar seu projeto lá.
Vamos ficar com uma estrutura parecida com essa:
Typescript
Escolhi usar typescript devido aos benefícios que ele trás atualmente como o Intellisense, permitindo pegar erros na hora, sem falar das funcionalidades que ainda não estão disponíveis no ES.
Vamos adicionar o typescript com os types dele e do node.js dado que estamos utilizando o Next.js e o mesmo utiliza o node:
yarn add typescript @types/react @types/node -D
Em seguida vamos trocar os formatos de alguns arquivos para os do typescript:
pages/_app.js -> pages/_app.tsx
Vamos remover a importação do styles nesse arquivo, ficaremos com algo assim:
pages/index.js -> pages/index.tsx
Vamos remover a importação do styles aqui também e no meu caso removi tudo o que eu não fosse usar para esse exemplo:
Agora vamos rodar o projeto, e o yarn vai entender que estamos usando typescript e criar as configurações dele e as tipagens que o next vai precisar automaticamente.
Quando ele terminar de rodar teremos uma estrutura parecida com essa:
Abrindo no seu navegador o localhost:3000
vamos ter algo parecido com isso:
Com isso colocamos o typescript no nosso projeto!
EsLint
Primeiramente vamos instalar ele como dependência:
yarn add eslint -D
Em seguida vamos rodar o init:
yarn init eslin
Com isso vamos fazer a configuração com o CLI do Eslint:
- Vamos escolher a terceira opção, checar sintaxe, encontrar problemas e forçar um estilo de código
- Aqui vamos selecionar a primeira opção, pôs estamos utilizando import/export
- Aqui também vai ser a primeira opção, estamos utilizando React
- Vamos dizer que sim, o projeto utiliza Typescript
- Agora vamos selecionar às duas opções com a barra de espaço, vamos rodar o projeto no navegador, mas o Next também utiliza o Node, logo nos queremos que os dois sejam vistos
- Aqui vamos escolher a primeira opção, utilizar um guia de estilo popular
- Vamos escolher o guia do Airbnb
- Aqui vamos escolher a terceira opção JSON como arquivo de configuração para o eslint
- Por final, vamos escolher sim, para instalar as dependências necessárias
As opções acabaram, mas vamos precisar de mais uma dependência o eslint-config-airbnb-typescript, precisaremos instalar ele com o Yarn:
yarn add eslint-config-airbnb-typescript -D
Vamos perceber que ele vai gerar um package-lock.json, porque ele instala via NPM, logo após de terminar de instalar vamos deletar o package-lock.json e rodar no terminal yarn para ele adicionar no yarn-lock
Terminando de instalar tudo pelo Yarn, teremos uma estrutura parecida com essa:
E vamos ver que o Eslint já esta acusando alguns erros no projeto.
Calma vamos resolver tudo!
Mas antes vamos alterar algumas coisas nas configurações do Eslint, .eslintrc.
Eu tive bastante dificuldade para configurar o Eslint estendido do AirBnB, pedi ajuda a alguns amigos e decidi ter poucas regras e extensões, então basicamente eu vou estender do airbnb-typescript e passar o projeto para ele.
Ficaremos com um .eslintrc parecido com:
Agora vamos criar o arquivo de ignore do Eslint .eslintignore na raiz do projeto e vamos ignorar os arquivos node_modules .next e arquivos .js no projeto.
Teremos uma configuração assim:
Inicialmente vamos à pasta pages/, no arquivo _app.tsx
vamos salvar, e ele já vai fixar alguns erros.
Lembrando que para isso acontecer se o seu VSCode estiver com a configuração de editor.codeActionsonSave configurada para o EsLint fixar os erros que ele consegue.
E em seguida vamos ver o seguinte erro, 'React' must be in scope when using JSX basicamente o lint pede para importarmos o React quando o escopo for JSX, conseguimos retirar isso desabilitando essa regra, em um projeto Next essa importação não é necessária, mas eu decidi manter por estar acostumado.
Por fim vamos converter a function MyApp para um componente. Teremos algo parecido com:
Porém, ainda temos um error, o Eslint não vai entender que o nosso componente esta recebendo as propriedades e para isso o Next possui um type que garante a tipagem e afins para nós. No final teremos algo assim:
Agora no arquivo index.tsx vamos fazer as mesmas coisas, vamos salvar o arquivo, em seguida importar o React e converter a function. Ficaremos com algo assim:
E finalizamos essa etapa de Eslint. Você pode rodar o yarn run dev para ver se esta tudo ok com o projeto.
Styled Components
Eu escolhi styled components para estilização, por simples curiosidade, como eu disse estou aprendendo e vi que era muito utilizado no mercado :).
Bom para adicionar a estilização eu segui um modelo do próprio next.JS.
Inicialmente vamos instalar o styled-components e o @types/styled-components
yarn add styled-components
e
yarn add @types/styled-components -D
Vamos criar um arquivo babelrc na raiz do projeto e adicionar a configuração dele, vamos criar um arquivo chamado __document.tsx na pasta ./pages/ e adicionar a configuração dele também.
Agora vamos precisar alterar algumas coisas dentro do arquivo __document.tsx, devido a utilizarmos o TS, provavelmente ele deve reclamar do retorno da função getInitialProps, vamos tipar o retorno dela da seguinte forma:
Vamos importar de next/document o tipo pronto desse retorno que o next disponibiliza para usarmos, o DocumentinitialProps
ele será o tipo da promessa que a função assincronia vai retornar, e teremos que tipar o contexto ("ctx" passado como argumento da função) também, vamos importar do mesmo cara o DocumentContext. Ficaremos com um arquivo parecido com isso:
Pronto, temos o styled-componentes configurado, porém precisamos usa-lo, para isso vamos fazer umas alterações na nossa estrutura.
Vamos criar um arquivo src na raiz do projeto e dentro dela outra pagina chamada styles e vamos criar um arquivo de estilos globais, esse arquivo é criado para fins de exemplos não uma regra. E por fim vamos mover a pasta pages para dentro da pasta src. Teremos algo assim no final:
Agora vamos colocar nosso arquivo de configuração de estilos globais pra fazer efeito na aplicação. Inicialmente vamos importar nele a função createGlobalStyle do styled-components,
vamos exportar ele de forma default, ele vai criar a nossa tag de estilização global para usarmos no início da aplicação.
Vamos adicionar alguns estilos padrão para a aplicação e para a tag body:
Vamos adicionar o nosso componente na aplicação, no arquivo __app.tsx vamos importar ele e adicionar no retorno da função MyApp:
Rodando o yarn dev podemos ver as estilizações funcionando!
E pronto, mais uma etapa chega ao fim, configuramos o styled- components no nosso projeto!
Uma ressalva aqui sobre o styled-component no Next.JS, Toda a estilização esta sendo feita no serve side, no servidor node que o next cria, se desabilitarmos o javascript no browser e dermos um F5 vamos ver que a estilização continua, por mais que estejamos usando o styled-components que funciona de forma dinamica com o JS.
Next Images
Eu quis trazer esse plugin do Next para o artigo pôs enquanto estava estudando vi que ele tem algumas limitações para lidar com imagens, ele pede para que coloquemos as imagens que vamos usar na pasta ./public, e não conseguiríamos utilizar de outra pasta, por exemplo, e não conseguiríamos tratar as imagens, mas com o plugin Next images isso muda, vamos conseguir lidar melhor.
Para instalar vamos começar com:
yarn add next-images
Vamos precisar criar um arquivo na raiz chamado next.config.js
e nele vamos adicionar essas linhas de código como configuração:
const withImages = require('next-images')
module.exports = withImages({
esModule: true,
})
Por último, como estamos utilizando Typescript vamos precisar adicionar mais uma linha de código no arquivo next-env.d.ts, para que o Next entenda os arquivos de imagem:
/// <reference types="next-images" />
Agora para ver se funcionou, vamos criar uma pasta de assets dentro de ./src e colocar um SVG para usarmos, ficaremos com uma estrutura assim:
Agora vamos usar a imagem na nossa pagina inicial:
E dependendo da sua imagem, teremos algo assim:
Porem se inspecionarmos a imagem, vamos ver que ela foi convertida para base64:
Essa conversão não e legal para imagens grandes, elas podem aumentar bastante de tamanho. Podemos melhorar isso com o plugin do babel inline-react-svg
vamos instalar o plugin:
yarn add babel-plugin-inline-react-svg -D
Em seguida vamos usar ele nas configurações do babel, no arquivo ./babel.rc:
E vamos usar agora a imagem como uma tag mesmo. Bem mais simples, não?
Agora vamos rodar o projeto de novo e ver a diferença:
Pronto, configuramos a utilização de imagens e o tratamento dos SVG's.
lembrando que esse tratamento da base64 serve somente para os SVG's.
Jest
Bom agora, vamos aos testes!
Eu escolhi o Jest por ter uma certa familiaridade e querer aprender um pouco mais como testar unitariamente com ele.
Vamos precisar instalar algumas dependências para o Jest funcionar no nosso projeto:
yarn add jest @testing-library/react @types/jest @testing-library/jest-dom babel-jest @babel/core -D
Em seguida nós vamos criar na raiz do projeto o arquivo de configuração do Jest, ./jest.config.js, ficaremos com uma estrutura parecida com essa:
Vamos adicionar a configuração:
module.exports = {
testPathIgnorePatterns: ['<rootDir>/.next/', '<rootDir>/node_modules/'],
bail: 1,
clearMocks: true,
collectCoverage: true,
collectCoverageFrom: ['components/**/*.tsx', 'pages/**/*.tsx'],
coverageReporters: ['lcov', 'text'],
};
Agora vamos adicionar ao babel.rc o presset para o Jest:
"presets": ["next/babel"]
No meu caso, na configuração que fizemos anteriormente, já havíamos colocado esse presset, porem pode ser que isso não aconteça com você então é bom lembrar!
Com a configuração feita, estamos prontos para rodar os testes! Vamos adicionar dois comandos no ./package.json para deixar pronto para rodar:
"test": "jest --watch",
"coverage": "jest --coverage"
Agora vamos adicionar um teste simples do arquivo ./pages/index.tsx para vermos o Jest em funcionamento.
Dentro da pasta pages vamos criar um arquivo chamado index.test.tsx e vamos adicionar esse teste simples:
import React from 'react';
import { render } from '@testing-library/react';
import '@testing-library/jest-dom/extend-expect';
import Home from './index';
it('should render Header', () => {
const { getByText } = render(<Home />);
expect(getByText('Pagina inicial')).toBeTruthy();
});
Aqui nos estamos vendo se o texto Pagina inicial vai ser renderizado.
Vamos para o terminal e rodar o comando de teste:
yarn test
Se a instalação e a configuração estiverem certas, vamos ter um resultado assim:
E pronto! Podemos testar o projeto sempre que quiser.
Uma ressalva, existem varias convenções de estruturas e formas de organizar os testes, eu particularmente prefiro, em projetos Next.JS a utilização da pasta
__test__
para organizar os testes, e mantenho eles sempre no escopo do que eu to testando, por exemplo, como estamos testando o index dentro de ./pages teríamos uma pasta__test__
, o Jest vai conseguir entender tudo e rodar os nossos testes. Decidi fazer dessa forma, pôs é mais simples de entender, na minha opinião.Gostaria de Incentivar você a testar o máximo que puder do seu projeto, existem vários conteúdos sobre testes com ou sem o Jest e afins então manter sempre seu projeto testado torna mais seguro para você e para seu possível cliente.
Cypress
Para os testes e2e eu decidi usar o Cypress para aprender e conhecer a ferramenta.
Vamos instalar o Cypress:
yarn add cypress --dev
Agora vamos abrir o Cypress:
yarn run cypress open
O Cypress vai criar o arquivo de configuração dele, cypress.json, a pasta na raiz do projeto e alguns testes de exemplo, não vamos precisar deles, vamos deletar o que for exemplo e ficaremos com uma estrutura assim:
Agora vamos adicionar um teste simples, para vermos o Cypress funcionando. Dentro da pasta cypress/integrations vamos adicionar um novo arquivo, index_spec.ts e adicionar as seguintes linhas de código:
describe('The Home Page', () => {
beforeEach(() => {
cy.visit('/');
});
it('successfully loads title', () => {
cy.contains('Pagina inicial');
});
});
export {};
Vamos perceber que ele vai acusar um erro no cy, basicamente o Typescript não esta entendendo o tipo dele, vamos adicionar o cypress nos tipos do TS no arquivo, tsconfig.json:
"types": ["cypress"],
...
Agora vamos rodar o Cypress para ver se o teste esta funcionando. Vamos ver que não funcionou :/.
O Cypress precisa acessar o nosso servidor local para conseguir visitar a nossa pagina, para isso acontecer precisamos configurar a URL base, vamos adicionar no arquivo cypress.json :
{
"baseUrl": "http://localhost:3000"
}
Agora vamos abrir outro terminal, e rodar a nossa aplicação, atualmente esta na porta 3000, e no outro terminal vamos rodar o cypress open e ver que agora os testes estão passando!
Temos o Cypress configurado, como um bônus, vou usar o Github Actions para rodar o Cypress nos nossos pull requests e commits :)
Inicialmente vamos criar o repositório no GitHub e fazer um git push. Vamos à aba de repositórios do Git, clicar em novo:
Em seguida vamos dar um nome ao repositório e desmarcar qualquer coisa, além da opção de public, que esteja marcada para não dar conflito e clicar em criar repositório:
Agora vamos voltar ao terminal e adicionar o nosso repositório ao Git:
Lembre-se de commitar as nossas alterações antes de fazer o push :)
Para você esse endereço na caixa vermelha vai ser outro, não tem problema algum, isso SO quer dizer que o projeto esta na minha conta do Github e o seu vai estar no seu Git.
Com isso vamos ter o nosso projeto no GitHub, dai para frente você pode alterar do jeito que quiser o projeto, deixar com a sua cara no Git!
Agora vamos adicionar o Cypress ao nosso projeto:
vamos ir na dashboard do cypress
ao logar, vamos precisar autorizar o Cypress no nosso github:
vamos pular essa etapa de criação de times.
Vamos adicionar o projectId gerado no arquivo cypress.json no nosso projeto.
Vamos guardar essa chave que nos permite enviar os vídeos para o dashboard do Cypress
Pronto temos um projeto no Cypress.io, agora vamos criar uma ligação entre ele e o nosso projeto no GitHub
Vamos entrar na aba Project Settings:
Vamos descer ate a parte de GitHub Integration e clicar em Install the Cypress GitHub App:
Selecione o seu GitHub:
Vamos descer ate a parte de Repository acess e selecionar o nosso repositório:
Vamos salvar e seremos redirecionados para o Cypress de novo,
em seguida vamos selecionar o repositório que vamos usar do github:
O Cypress vai fazer a configuração necessária para o hook funcionar no Git, só vamos precisar ativar no GitHub.
Vamos Agora na aba settings do projeto no GitHub:
Vamos selecionar a opção Branches depois Add Rule, vamos adicionar um nome para a regra, e selecionar a opção de status checks:
E já vamos ver o Cypress checando os commits que subimos para o GitHub:
Bom Agora vamos à aba de actions e selecionar a opção set up a workflow yourself:
Agora vamos adicionar o workflow do cypress no script:
name: End-to-end tests
on: [push]
jobs:
cypress-run:
runs-on: ubuntu-16.04
steps:
- name: Checkout
uses: actions/checkout@v1
- name: Cypress run
uses: cypress-io/github-action@v2
with:
record: true
start: yarn run dev
env:
# pass the Dashboard record key as an environment variable
CYPRESS_RECORD_KEY: <SUA CHAVE GERADA PELO CYPRESS>
E se abrirmos um pull request, vamos ver que só vamos poder fazer merge, quando o status do Cypress liberar:
E uma coisa legal e que o Cypress sempre reporta no pull request:
E assim finalizamos a questão do Cypress!
Travis
Eu considerei colocar o Travis CI como processo de CI aqui para deixar mais completo o projeto e se você quiser aprender mais sobre CI/CD recomendo muito a documentação deles, e bem completa!
Não vou configurar um processo de CD pôs o projeto tem a finalidade de ser um inicial, o CD fica a critério da evolução do projeto.
Inicialmente vamos entrar na dashboard do Travis CI, assim como no Cypress, vamos precisar instalar a App no Git e autorizar o mesmo.
Agora vamos adicionar a integração no nosso projeto, vamos clicar no + para adicionar uma integração nova, em seguida precisamos buscar pelo nosso projeto:
Vamos ser redirecionado para a tela anterior porem nao teremos configuração:
Vamos precisar criar um arquivo novo no nosso projeto, o .travis.yml, e vamos adicionar a ele as seguintes linhas de código:
language: node_js
node_js:
- "10"
install: yarn install --frozen-lockfile
cache:
- yarn
script:
- yarn run test
Em seguida, vamos remover o --watch do script de testes, ficando com `"test": "jest"
, para que o Travis não fique travado quando rodar os testes na pipeline, podemos também fazer um script novo para o Travis na pipeline, fique a vontade.
Vamos comitar e fazer o git push, já vamos perceber que o Travis esta rodando automaticamente:
Vamos fazer a mesma configuração nas regras que fizemos com o Cypress, vamos à aba de Settings, depois em Branches, precisamos editar a regra que já tínhamos adicionando mais um status check:
E com isso, configuramos o Travis para rodar nossos testes unitários no momento do pull request:
Conclusão
Bom, chegamos ao fim, eu queria concluir dizendo que sei que o texto ficou longo, espero que não massivo, mas minha intenção é expor o que estou aprendendo e aperfeiçoando, ao longo do meu aprendizado, vi poucos conteúdos em português dos assuntos que eu abordei aqui então espero que ajude a comunidade Brasileira nesse sentido, qualquer dúvida é só entrar em contato comigo pelo Twitter.
Vou deixar o link para o repositório do projeto que construímos e as referências que usei para construção do projeto:
Next
Configuração de projeto Next pela rocketseat
StyledComponents
vantagens do styled components pelo Dev Soutinho
Template do Next.JS usando styled components
Jest
Artigo - Configurar testes no Next.JS
Mais uma vez obrigado a todos que gostaram e espero ter ajudado, não esqueça de deixar seu feedback.
Top comments (7)
Muito da hora, quase não acha um guia de inicialização desse nível.
Me ajudou muito, tô começando no react hoje.
Ótimo posto, vai ajuda muito
Muito obrigada por esse guia pra iniciantes! Só um adendo: o comando yarn init eslin que você colocou é na verdade yarn run eslint --init segundo a documentação.
Vou atualizar assim que possivel, obrigado pela informação!
otimo conteúdo ,me ajudou muito ,esta de parabém pela iniciativa de compartilhar sua experiência
Valeu mesmo por compartilhar meu amigo!