DEV Community

Cover image for Criando meu project starter com Next.JS
Caio M. Veloso Dias
Caio M. Veloso Dias

Posted on • Updated on

Criando meu project starter com Next.JS

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
Enter fullscreen mode Exit fullscreen mode

Ele vai criar uma estrutura como essa:

Alt Text

Vamos entrar na pasta criada:

cd nome_do_seu_projeto
Enter fullscreen mode Exit fullscreen mode

Caso queira ver o que o comando criou é só rodar no terminal:

yarn run dev
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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 
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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:

Alt Text

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:

Alt Text

Abrindo no seu navegador o localhost:3000
vamos ter algo parecido com isso:

Alt Text

Com isso colocamos o typescript no nosso projeto!

EsLint

Primeiramente vamos instalar ele como dependência:

yarn add eslint -D
Enter fullscreen mode Exit fullscreen mode

Em seguida vamos rodar o init:

yarn init eslin
Enter fullscreen mode Exit fullscreen mode

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

Alt Text

  • Aqui vamos selecionar a primeira opção, pôs estamos utilizando import/export

Alt Text

  • Aqui também vai ser a primeira opção, estamos utilizando React

Alt Text

  • Vamos dizer que sim, o projeto utiliza Typescript

Alt Text

  • 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

Alt Text

  • Aqui vamos escolher a primeira opção, utilizar um guia de estilo popular

Alt Text

  • Vamos escolher o guia do Airbnb

Alt Text

  • Aqui vamos escolher a terceira opção JSON como arquivo de configuração para o eslint

Alt Text

  • Por final, vamos escolher sim, para instalar as dependências necessárias

Alt Text

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
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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:

Alt Text

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:

Alt Text

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:

Alt Text

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:

Alt Text

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:

Alt Text

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
Enter fullscreen mode Exit fullscreen mode

e

yarn add @types/styled-components -D
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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:

Alt Text

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:

Alt Text

Vamos adicionar o nosso componente na aplicação, no arquivo __app.tsx vamos importar ele e adicionar no retorno da função MyApp:

Alt Text

Rodando o yarn dev podemos ver as estilizações funcionando!

Alt Text

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
Enter fullscreen mode Exit fullscreen mode

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,
})
Enter fullscreen mode Exit fullscreen mode

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" />
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

Agora vamos usar a imagem na nossa pagina inicial:

Alt Text

E dependendo da sua imagem, teremos algo assim:

Alt Text

Porem se inspecionarmos a imagem, vamos ver que ela foi convertida para base64:

Alt Text

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
Enter fullscreen mode Exit fullscreen mode

Em seguida vamos usar ele nas configurações do babel, no arquivo ./babel.rc:

Alt Text

E vamos usar agora a imagem como uma tag mesmo. Bem mais simples, não?

Alt Text

Agora vamos rodar o projeto de novo e ver a diferença:

Alt Text

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
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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'],
};
Enter fullscreen mode Exit fullscreen mode

Agora vamos adicionar ao babel.rc o presset para o Jest:

"presets": ["next/babel"]
Enter fullscreen mode Exit fullscreen mode

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"
Enter fullscreen mode Exit fullscreen mode

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();
});
Enter fullscreen mode Exit fullscreen mode

Aqui nos estamos vendo se o texto Pagina inicial vai ser renderizado.

Vamos para o terminal e rodar o comando de teste:

yarn test
Enter fullscreen mode Exit fullscreen mode

Se a instalação e a configuração estiverem certas, vamos ter um resultado assim:

Alt Text

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
Enter fullscreen mode Exit fullscreen mode

Agora vamos abrir o Cypress:

yarn run cypress open
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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 {};
Enter fullscreen mode Exit fullscreen mode

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"],
...
Enter fullscreen mode Exit fullscreen mode

Agora vamos rodar o Cypress para ver se o teste esta funcionando. Vamos ver que não funcionou :/.

Alt Text

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"
}
Enter fullscreen mode Exit fullscreen mode

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!

Alt Text

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:

Alt Text

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:

Alt Text

Agora vamos voltar ao terminal e adicionar o nosso repositório ao Git:

Alt Text

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:
    Alt Text

  • vamos criar uma organização nova:
    Alt Text

  • vamos pular essa etapa de criação de times.

  • vamos criar um projeto novo:
    Alt Text

  • selecione a opção public:
    Alt Text

  • 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:

Alt Text

Vamos descer ate a parte de GitHub Integration e clicar em Install the Cypress GitHub App:

Alt Text

Selecione o seu GitHub:

Alt Text

Vamos descer ate a parte de Repository acess e selecionar o nosso repositório:

Alt Text

Vamos salvar e seremos redirecionados para o Cypress de novo,
em seguida vamos selecionar o repositório que vamos usar do github:

Alt Text

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:

Alt Text

Vamos selecionar a opção Branches depois Add Rule, vamos adicionar um nome para a regra, e selecionar a opção de status checks:

Alt Text

E já vamos ver o Cypress checando os commits que subimos para o GitHub:

Alt Text

Bom Agora vamos à aba de actions e selecionar a opção set up a workflow yourself:

Alt Text

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>
Enter fullscreen mode Exit fullscreen mode

E se abrirmos um pull request, vamos ver que só vamos poder fazer merge, quando o status do Cypress liberar:

Alt Text

E uma coisa legal e que o Cypress sempre reporta no pull request:

Alt Text

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:

Alt Text

Alt Text

Vamos ser redirecionado para a tela anterior porem nao teremos configuração:

Alt Text

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
Enter fullscreen mode Exit fullscreen mode

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:

Alt Text

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:

Alt Text

E com isso, configuramos o Travis para rodar nossos testes unitários no momento do pull request:

Alt Text

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:

projeto de exemplo

Next
Configuração de projeto Next pela rocketseat

Typescript

EsLint

StyledComponents
vantagens do styled components pelo Dev Soutinho

Template do Next.JS usando styled components

Next Image

React inline SVG

Jest
Artigo - Configurar testes no Next.JS

Cypress
Cypress pelo Agilize

Travis CI

Mais uma vez obrigado a todos que gostaram e espero ter ajudado, não esqueça de deixar seu feedback.

Top comments (7)

Collapse
 
eliasfaical profile image
Elias Faiçal

Muito da hora, quase não acha um guia de inicialização desse nível.

Collapse
 
matheusalba profile image
Matheus

Me ajudou muito, tô começando no react hoje.

Collapse
 
marcelorafael profile image
Marcelo Rafael Gonçalves

Ótimo posto, vai ajuda muito

Collapse
 
giuliabriao profile image
Giulia Brião

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.

Collapse
 
caiomdias profile image
Caio M. Veloso Dias

Vou atualizar assim que possivel, obrigado pela informação!

Collapse
 
alxassis profile image
Alx-Assis

otimo conteúdo ,me ajudou muito ,esta de parabém pela iniciativa de compartilhar sua experiência

Collapse
 
heberbr profile image
heberbr

Valeu mesmo por compartilhar meu amigo!