Implantar sites Next.js híbridos nos Aplicativos Web Estáticos do Azure (Visualização)

Neste tutorial, você aprenderá a implantar um site Next.js nos Aplicativos Web Estáticos do Azure, usando o suporte para recursos Next.js, como Componentes do Servidor React, Renderização do Lado do Servidor (SSR) e rotas de API.

Nota

Next.js suporte híbrido está em pré-visualização.

Pré-requisitos

Funcionalidades não suportadas na pré-visualização

Os seguintes recursos de aplicativos Web estáticos não são suportados para Next.js com renderização híbrida:

  • APIs vinculadas usando o Azure Functions, o Serviço de Aplicativo do Azure, os Aplicativos de Contêiner do Azure ou o Gerenciamento de API do Azure.
  • Emulação e implantação local da CLI SWA.
  • Suporte parcial para staticwebapp.config.json arquivo.
    • Não há suporte para fallback de navegação.
    • As regravações de rota em rotas dentro do aplicativo Next.js devem ser configuradas em next.config.js.
    • A configuração dentro do staticwebapp.config.json arquivo tem precedência sobre a configuração dentro next.config.jsdo .
    • A configuração para o site Next.js deve ser tratada usando next.config.js para compatibilidade total de recursos.
  • skip_app_build e skip_api_build não pode ser usado na imagem de Azure/static-web-apps-deploy@v1 implantação.
  • A regeneração estática incremental (ISR) não suporta imagens em cache.

Nota

O tamanho máximo do aplicativo para o aplicativo Next.js híbrido é de 250 MB. Use o recurso autônomo por Next.js para tamanhos de aplicativos otimizados. Se isso não for suficiente, considere usar HTML estático exportado Next.js se o requisito de tamanho do aplicativo for superior a 250 MB.

Criar um repositório

Este artigo usa um repositório de modelos do GitHub para facilitar os primeiros passos. O modelo apresenta um aplicativo inicial para implantar nos Aplicativos Web Estáticos do Azure.

  1. Navegue até o seguinte local para criar um novo repositório.

    https://github.com/staticwebdev/nextjs-hybrid-starter/generate

  2. Nomeie seu repositório como my-first-static-web-app

  3. Selecione Criar repositório a partir de modelo.

    Captura de tela do botão criar repositório a partir do modelo.

Criar uma aplicação Web estática

Agora que o repositório foi criado, você pode criar um aplicativo Web estático no portal do Azure.

  1. Aceda ao portal do Azure.
  2. Selecione Criar um Recurso.
  3. Pesquise por aplicativos Web estáticos.
  4. Selecione Aplicações Web Estáticas.
  5. Selecione Criar.

Na seção Noções básicas, comece configurando seu novo aplicativo e vinculando-o a um repositório do GitHub.

Captura de ecrã da secção de noções básicas no portal do Azure.

Definição Value
Subscrição Selecione a subscrição do Azure.
Grupo de Recursos Selecione o link Criar novo e insira static-web-apps-test na caixa de texto.
Nome Digite my-first-static-web-app na caixa de texto.
Tipo de plano Selecione Gratuito.
Azure Functions e detalhes de preparo Selecione a região mais próxima de si.
Source Selecione GitHub.

Selecione Entrar com o GitHub e autentique-se com o GitHub.

Depois de entrar com o GitHub, insira as informações do repositório.

Definição Value
Organization Selecione a sua organização.
Repositório Selecione my-first-web-static-app.
Filial Selecione principal.

Captura de ecrã dos detalhes do repositório no portal do Azure.

Nota

Se não vir nenhum repositório:

  • Talvez seja necessário autorizar os Aplicativos Web Estáticos do Azure no GitHub. Navegue até o repositório do GitHub e vá para Configurações de Aplicativos > OAuth Autorizados, selecione Aplicativos Web Estáticos do Azure e selecione Conceder>.
  • Talvez seja necessário autorizar os Aplicativos Web Estáticos do Azure em sua organização do Azure DevOps. Você deve ser um proprietário da organização para conceder as permissões. Solicite acesso a aplicativos de terceiros via OAuth. Para obter mais informações, consulte Autorizar acesso a APIs REST com OAuth 2.0.

Na seção Detalhes da compilação, adicione detalhes de configuração específicos à sua estrutura de front-end preferida.

  1. Selecione Next.js na lista suspensa Predefinições de compilação.

  2. Mantenha o valor padrão na caixa Local do aplicativo.

  3. Deixe a caixa Localização da api vazia.

  4. Deixe a caixa Local do artefato do aplicativo vazia.

Selecione Rever + criar.

Captura de ecrã do botão criar.

Ver o site

Há dois aspetos na implantação de um aplicativo estático. O primeiro cria os recursos subjacentes do Azure que compõem seu aplicativo. O segundo é um fluxo de trabalho que cria e publica seu aplicativo.

Antes de poder ir para o novo site estático, a compilação de implantação deve primeiro concluir a execução.

A janela Visão geral de aplicativos Web estáticos exibe uma série de links que ajudam você a interagir com seu aplicativo Web.

Captura de ecrã da janela de descrição geral das Aplicações Web Estáticas do Azure.

Selecionar no banner que diz, Selecione aqui para verificar o status de suas execuções de Ações do GitHub leva você para as Ações do GitHub em execução no seu repositório. Depois de verificar se o trabalho de implantação está concluído, você pode acessar seu site por meio da URL gerada.

Quando o fluxo de trabalho de Ações do GitHub estiver concluído, você poderá selecionar o link de URL para abrir o site em uma nova guia.

Configure seu projeto Next.js localmente para fazer alterações

  1. Clone o novo repositório para a sua máquina. Certifique-se de substituir <YOUR_GITHUB_ACCOUNT_NAME pelo nome da> sua conta.

    git clone http://github.com/<YOUR_GITHUB_ACCOUNT_NAME>/my-first-static-web-app
    
  2. Abra o projeto no Visual Studio Code ou no editor de código de sua preferência.

Adicionar dados renderizados pelo servidor com um componente de servidor

Para adicionar dados renderizados em servidor em seu projeto Next.js usando o App Router, edite um componente Next.js para adicionar operações do lado do servidor para renderizar dados no componente. Por padrão, Next.js componentes são componentes de servidor que podem ser renderizados pelo servidor.

  1. Abra o app/page.tsx arquivo e adicione uma operação que defina o valor de uma variável, que é computada no lado do servidor. Os exemplos incluem a busca de dados ou outras operações do servidor.

    export default function Home() {
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            ...
        );
    }
    
  2. Importe unstable_noStorenext/cache e chame-o dentro do Home componente para garantir que a rota seja renderizada dinamicamente.

    import { unstable_noStore as noStore } from 'next/cache';
    
    export default function Home() {
        noStore();
    
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            ...
        );
    }
    

    Nota

    Este exemplo força a renderização dinâmica desse componente para demonstrar a renderização do servidor da hora atual do servidor. O modelo do App Router do Next.js recomenda armazenar em cache solicitações de dados individuais para otimizar o desempenho do seu aplicativo Next.js. Leia mais sobre busca de dados e armazenamento em cache no Next.js.

  3. Atualize o Home componente em app/pages.tsx para renderizar os dados do lado do servidor.

    import { unstable_noStore as noStore } from 'next/cache';
    
    export default function Home() {
        noStore();
    
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            <main className="flex min-h-screen flex-col items-center justify-between p-24">
                <div>
                    This is a Next.js application hosted on Azure Static Web Apps with 
                    hybrid rendering. The time on the server is <strong>{timeOnServer}</strong>.
                </div>
            </main>
        );
    }
    

Adicionando uma rota de API

Além de Componentes de Servidor, Next.js fornece Manipuladores de Rota que você pode usar para criar rotas de API para seu aplicativo Next.js. Essas APIs podem ser buscadas em Componentes de cliente.

Comece adicionando uma rota de API.

  1. Crie um novo arquivo em app/api/currentTime/route.tsx. Esse arquivo contém o manipulador de rotas para o novo ponto de extremidade da API.

  2. Adicione uma função de manipulador para retornar dados da API.

    import { NextResponse } from 'next/server';
    
    export const dynamic = 'force-dynamic';
    
    export async function GET() { 
        const currentTime = new Date().toLocaleTimeString('en-US');
    
        return NextResponse.json({ 
            message: `Hello from the API! The current time is ${currentTime}.`
        });
    }
    
  3. Crie um novo arquivo em app/components/CurrentTimeFromAPI.tsx. Esse componente cria um contêiner para o componente cliente que busca a API do navegador.

  4. Adicione um componente de cliente que busque a API neste arquivo.

    'use client';
    
    import { useEffect, useState } from 'react';
    
    export function CurrentTimeFromAPI(){
        const [apiResponse, setApiResponse] = useState('');
        const [loading, setLoading] = useState(true);
    
        useEffect(() => {
            fetch('/api/currentTime')
                .then((res) => res.json())
                .then((data) => {
                setApiResponse(data.message);
                setLoading(false);
                });
            }, 
        []);
    
        return (
            <div className='pt-4'>
                The message from the API is: <strong>{apiResponse}</strong>
            </div>
        )
    }
    

Este componente cliente busca a API com um useEffect gancho React para renderizar o componente após a conclusão da carga. A 'use client' diretiva identifica este elemento como um componente cliente. Para obter mais informações, consulte Componentes do cliente.

  1. Edite app/page.tsx para importar e renderizar o CurrentTimeFromAPI componente cliente.

    import { unstable_noStore as noStore } from 'next/cache';
    import { CurrentTimeFromAPI } from './components/CurrentTimeFromAPI';
    
    export default function Home() {
        noStore();
    
        const timeOnServer = new Date().toLocaleTimeString('en-US');
        return(
            <main className="flex min-h-screen flex-col items-center justify-between p-24">
                <div>
                    This is a Next.js application hosted on Azure Static Web Apps with 
                    hybrid rendering. The time on the server is <strong>{timeOnServer}</strong>.
                </div>
                <CurrentTimeFromAPI />
            </main>
        );
    }
    
  2. O resultado da rota da API é exibido na página.

Captura de tela mostrando a exibição da saída da rota da API.

Configurar a versão de tempo de execução para Next.js

Algumas versões Next.js requerem versões Node.js específicas. Para configurar uma versão específica do Node, você pode definir a propriedade 'engines' do seu package.json arquivo para designar uma versão.

{
  ...
  "engines": {
    "node": "18.17.1"
  }
}

Definir variáveis de ambiente para Next.js

Next.js usa variáveis de ambiente em tempo de compilação e em tempo de solicitação, para oferecer suporte à geração de páginas estáticas e à geração de páginas dinâmicas com renderização no servidor. Portanto, defina variáveis de ambiente dentro da tarefa de compilação e implantação e nas variáveis de Ambiente do seu recurso de Aplicativos Web Estáticos do Azure.

...
      - name: Build And Deploy
        id: builddeploy
        uses: Azure/static-web-apps-deploy@v1
        with:
          azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN }}
          repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
          action: "upload"
          app_location: "/" 
          api_location: ""
          output_location: "" 
        env:
          DB_HOST: ${{ secrets.DB_HOST }}
          DB_USER: ${{ secrets.DB_USER }}
          DB_DATABASE: ${{ secrets.DB_DATABASE }}
          DB_PASSWORD: ${{ secrets.DB_PASSWORD }}
          DB_PORT: ${{ secrets.DB_PORT }}
...

Ativar recurso autônomo

Quando o tamanho do aplicativo excede 250Mb, o recurso de rastreamento de arquivos de saída Next.js ajuda a otimizar o tamanho do aplicativo e melhorar o desempenho.

O Output File Tracing cria uma versão compactada de todo o aplicativo com as dependências de pacote necessárias incorporadas em uma pasta chamada .next/standalone. Esta pasta destina-se a ser implantada por conta própria, sem dependências node_modules adicionais.

Para habilitar o standalone recurso, adicione a seguinte propriedade adicional ao seu next.config.js:

module.exports ={
    output:"standalone",
}

Você também precisará configurar o buildpackage.json comando no arquivo para copiar arquivos estáticos para sua saída autônoma.

{
  ...
  "scripts": {
    ...
    "build": "next build && cp -r .next/static .next/standalone/.next/ && cp -r public .next/standalone/"
    ...
  }
  ...
}

Configurar o roteamento e o middleware do Next.js para implantação nos Aplicativos Web Estáticos do Azure

Seu projeto Next.js pode ser configurado para ter manipulação personalizada de rotas com redirecionamentos, regravações e middleware. Esses manipuladores são comumente usados para autenticação, personalização, roteamento e internacionalização. A manipulação personalizada afeta o roteamento padrão do seu site Next.js e a configuração deve ser compatível com a hospedagem em Static Web Apps.

Os Aplicativos Web estáticos validam que seu site Next.js foi implantado com êxito adicionando uma página ao seu site no momento da compilação. A página é denominada public/.swa/health.html, e Static Web Apps verifica a inicialização e a implantação bem-sucedidas do seu site navegando até uma /.swa/health.html resposta bem-sucedida e verificando-a. O middleware e o roteamento personalizado, que incluem redirecionamentos e regravações, podem afetar o acesso ao caminho, o que pode impedir a /.swa/health.html validação da implantação dos Static Web Apps. Para configurar o middleware e o roteamento para uma implantação bem-sucedida em aplicativos Web estáticos, siga estas etapas:

  1. Exclua rotas começando com .swa no arquivo middleware.ts (ou .js) na configuração do middleware.

    export const config = {
      matcher: [
        /*
         * Match all request paths except for the ones starting with:
         * - .swa (Azure Static Web Apps)
         */
        '/((?!.swa).*)',
      ],
    }
    
  2. Configure seus redirecionamentos para next.config.js excluir rotas começando com .swa

    module.exports = {
        async redirects() {
            return [
              {
                source: '/((?!.swa).*)<YOUR MATCHING RULE>',
                destination: '<YOUR REDIRECT RULE>', 
                permanent: false,
              },
            ]
        },
    };
    
  3. Configure suas regravações para next.config.js excluir rotas começando com .swa

    module.exports = {
        async rewrites() {
            return {
                beforeFiles: [
                    {
                        source: '/((?!.swa).*)<YOUR MATCHING RULE>',
                        destination: '<YOUR REWRITE RULE>', 
                    }
                ]
            }
        },
    };
    

Esses trechos de código excluem caminhos que começam por .swa serem manipulados pelo seu middleware ou roteamento personalizado. Essas regras garantem que os caminhos sejam resolvidos conforme o esperado durante a validação da implantação.

Habilitar o registro em log para Next.js

Seguindo as práticas recomendadas para Next.js solução de problemas da API do servidor, adicione o log à API para detetar esses erros. O logon no Azure usa o Application Insights. Para pré-carregar este SDK, você precisa criar um script de inicialização personalizado. Para saber mais:

Clean up resources (Limpar recursos)

Se não pretender continuar a utilizar esta aplicação, pode eliminar a instância das Aplicações Web Estáticas do Azure através dos seguintes passos:

  1. Abra o portal do Azure.
  2. Pesquise my-first-web-static-app na barra de pesquisa superior.
  3. Selecione o nome do aplicativo.
  4. Selecione Eliminar.
  5. Selecione Sim para confirmar a ação de exclusão (essa ação pode levar alguns minutos para ser concluída).

Próximos passos