Deploy de sites estáticos em Next.js no GH Pages
Nessa semana precisei realizar o deploy da nova versão do meu guia front end em português no Github Pages usando as Github Actions e, meu amigo, passei um certo sufoco pois o guia foi escrito em Next.js e tem alguns segredos para conseguirmos deixar tudo rodando da forma esperada. Por isso estou escrevendo esse post para a posteridade. Espero que as gerações futuras usufruam das descobertas dessa minha pequena conquista. 😄
Atualmente o guia é composto de uma página estática com diversos links, ou seja, é bem simples. Então o fluxo que imaginei foi:
Então escrevi um workflow para uma action de deploy e ele ficou assim:
name: Deploy
on:
push:
branches:
- master
jobs:
ci:
runs-on: ubuntu-latest
steps:
- name: Check out repository code
uses: actions/checkout@v2
- uses: actions/setup-node@v1
with:
node-version: 14.18
- name: Install node dependencies
run: yarn install
- name: Run linter
run: yarn lint
- name: Build
run: yarn build
- name: Deploy
uses: crazy-max/ghaction-github-pages@v1
with:
target_branch: gh-pages
build_dir: out
env:
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
Note que na minha Action acabei chamando apenas o comando yarn build
pois no meu package.json o script de build
está configurado para realizar tanto o build
quanto o export
do Next.js.
Simples, né?
Como no Github Pages os sites não ficam na raiz do domínio, o Next.js precisa de algumas configurações para conseguir gerar os arquivos com as referências corretas e, além disso, o Github Actions foi feito para trabalhar com projetos Jekyll por padrão e o Jekyll ignora arquivos e diretórios que iniciam com _
como a pasta /_next
, que é onde ficam todos os arquivos gerados pela build do Next.js.
Ok, mas como resolver?
O primeiro passo é adicionar uma configuração para o Github saber que o deploy não é de uma aplicação Jekyll, para isso nós iremos adicionar um arquivo chamado .nojekyll
no diretório /public
. Dessa forma, quando o Next.js realizar o build de nossa aplicação ele adicionará esse arquivo na raiz do output da build.
Além disso, ao realizar o deploy de uma aplicação Next.js em um diretório que é diferente da raiz, é necessário configurar o basePath
do projeto. Então, no meu caso precisei adicionar o valor guia-frontend
a ele, que é o nome do meu repositório no Github.
Porém, o basePath
não altera o caminho para os assets (arquivos css, js e imagens no nosso caso) da sua aplicação e é aí que entra o assetPrefix
. Com ele nós conseguimos especificar um diretório ou domínio onde nossos assets estarão presentes.
No caso do Github Pages, ambos os valores serão o nome do seu repositório precedido de /
.
const isProd = process.env.NODE_ENV === "production";
const prefix = isProd ? "/guia-frontend" : "";
module.exports = {
basePath: prefix,
assetPrefix: prefix,
};
Para finalizar, também adicionei uma condição para garantir que esses parâmetros só seriam aplicados a configuração do Next.js em produção. Assim, em ambiente de desenvolvimento os arquivos do projeto seriam servidos a partir da raiz, como normalmente acontece em projetos que utilizam o Next.js.
Voilá
E agora tudo funciona como o esperado. Tanto em produção quanto no ambiente de desenvolvimento local. Espero que esse artigo tenha ajudado alguém e qualquer dúvida ou sugestão estou a disposição em @JLCarv.
Ps.: Vale ressaltar que tive problemas com arquivos referenciados pelos meus estilos css ao usar a função url()
. O Next.js não estava adicionando o assetPrefix
no caminho para esses arquivos devido a um bug ainda não resolvido, então tive que mudar a implementação.