Compartilhar via


Criar um aplicativo Web estático com uma API sem servidor

Saiba como executar localmente e implantar um aplicativo Web estático com uma API sem servidor no Azure. Este tutorial usa a versão prévia do modelo de programação mais recente do Azure Functions Node.js. Como este artigo usa uma versão prévia do Azure Functions, ele é implantado como um aplicativo separado do aplicativo Web estático.

Saiba como:

  • Executar localmente um SWA (aplicativo Web estático) com um aplicativo de funções do Azure
  • Proxy local de solicitações de front-end para a API de back-end local usando a CLI do SWA.
  • Implante e execute o mesmo código remotamente.

O proxy entre o front-end e o back-endis fornecido pela CLI do aplicativo Web estático fornece:

  • A URL no React, /api/todo, não especifica o número do servidor ou da porta para a API. Solicitações que usam essa URL são bem-sucedidas localmente porque a CLI do SWA gerencia o proxy para você.
  • Um emulador de autenticação local ao acessar /.auth/login/<provider>
  • Gerenciamento de rotas e autorização

Autenticação neste exemplo

A autenticação neste exemplo é fornecida para usuários front-end do serviço de Aplicativos Web Estáticos do Azure:

  • Logon/Logoff
  • Conteúdo público e privado

Código-fonte neste exemplo

O código-fonte neste exemplo destina-se a aprender a criar e implantar um aplicativo Web estático com uma API sem servidor. O código não se destina à produção.

Você encontrará vários lugares no código que não seguem as práticas recomendadas de segurança. Por exemplo, o código usa console.log para gravar no console do navegador.

Ao migrar para um ambiente de produção, você deve revisar e remover qualquer código que viole as práticas recomendadas de segurança da sua organização.

1. Preparar o ambiente de desenvolvimento

Crie as seguintes contas:

Instale o seguinte em seu computador de desenvolvimento local:

  • Node.js v18+
  • VS Code (Visual Studio Code)
  • CLI dos Aplicativos Web Estáticos do Azure (SWA) instalada globalmente com -g sinalizador
  • Azure Functions Core Tools v4.0.5095+ (se estiver em execução localmente) instalado globalmente com -g sinalizador
  • TypeScript v4+

2. Bifurcar o repositório de exemplo no GitHub

Você precisa ter sua própria bifurcação do repositório de exemplo para concluir a implantação do GitHub. Durante o processo de bifurcação, você só precisa copiar a main ramificação.

Bifurque o repositório de exemplo: https://github.com/Azure-Samples/azure-typescript-e2e-apps.

3. Clone o repositório de amostra bifurcado

  1. Em um terminal bash, clone seu repositório bifurcado para o computador local. Não clone o repositório de exemplo original. Um exemplo de URL é https://github.com/YOUR-ACCOUNT-NAME/azure-typescript-e2e-apps

    git clone YOUR-FORKED-REPO-URL
    
  2. Instale dependências para o aplicativo front-end local:

    cd app-react-vite && npm install 
    
  3. Instale dependências para o aplicativo de back-end local:

    cd ../api-inmemory && npm install && cd ..
    

4. Opcional, crie e execute o aplicativo local

O repositório de exemplo tem várias versões dos aplicativos front-end e back-end. As etapas a seguir usam a versão React 18 (Vite) do front-end e a Função do Azure v4 com Node.js versão do back-end com as rotas de /status API e /todo .

  1. Na raiz do aplicativo de exemplo, use a CLI do SWA com o ./swa-cli.config.json arquivo para criar os aplicativos front-end e back-end:

    swa build
    

    Se surgirem erros, o que pode acontecer dependendo da versão de vários pacotes e de seu ambiente, corrija-os antes de continuar. É importante saber que seu projeto é compilado localmente com êxito antes de passar para a implantação nos Aplicativos Web Estáticos do Azure.

  2. Na raiz do aplicativo de exemplo, use a CLI do SWA para iniciar os aplicativos com um proxy.

    swa start
    
  3. Quando você vir as seguintes linhas no terminal bash, o projeto foi iniciado com êxito.

    [swa] Serving static content:
    [swa]   /workspaces/azure-typescript-e2e-apps/app-react-vite/dist
    [swa] 
    [swa] Serving API:
    [swa]   /workspaces/azure-typescript-e2e-apps/api-inmemory
    [swa] 
    [swa] Azure Static Web Apps emulator started at http://0.0.0.0:4280. Press CTRL+C to exit.
    
  4. Abra um navegador da Web para o URL com proxy, http://localhost:4280. Você deverá ver a página a seguir:

    Captura de tela do aplicativo React local antes da autenticação.

  5. Você pode fazer login usando a autenticação fornecida pela CLI do SWA. O processo simula a autenticação em aplicativos Web estáticos do Azure baseados em nuvem. O código de front-end usa o /.auth/me ponto de extremidade para obter a identidade do usuário. Digite qualquer nome de usuário falso e não altere o restante dos campos.

    Captura de tela do formulário de autenticação simulada do aplicativo React local.

  6. Depois que um usuário é autenticado, o front-end exibe informações privadas , como as variáveis de ambiente da API.

    Captura de tela do aplicativo React local com autenticação concluída.

    O código-fonte do aplicativo Azure Function v4 para essa API é:

    import { app, HttpRequest, HttpResponseInit, InvocationContext } from "@azure/functions";
    
    import { name, version } from '../../package.json';
    function isObject(v) {
        return '[object Object]' === Object.prototype.toString.call(v);
    };
    function sortJson(o){
        if (Array.isArray(o)) {
            return o.sort().map(sortJson);
        } else if (isObject(o)) {
            return Object
                .keys(o)
            .sort()
                .reduce(function(a, k) {
                    a[k] = sortJson(o[k]);
    
                    return a;
                }, {});
        }
        return o;
    }
    
    export async function status(request: HttpRequest, context: InvocationContext): Promise<HttpResponseInit> {
        context.log(`Http function processed request for url "${request.url}"`);
    
        const sortedEnv = sortJson(process.env);
    
        return { jsonBody: {
            name,
            version,
            env: sortedEnv,
            requestHeaders: request.headers 
        }};
    };
    
    app.http('status', {
        route: "status",
        methods: ['GET'],
        authLevel: 'anonymous',
        handler: status
    });
    
  7. Expanda as seções pública e privada para ver o conteúdo da API ser exibido.

5. Criar um novo aplicativo do Azure Functions

A seção anterior de execução do aplicativo Web estático com a API era opcional. As seções restantes do artigo são necessárias para implantar o aplicativo e a API na nuvem do Azure.

Para usar a versão prévia do runtime do Azure Functions v4, você precisa criar um novo aplicativo do Azure Functions. Seu aplicativo Web estático também precisa ser recriado e reimplantado para usar o URI do aplicativo Azure Functions nas solicitações de busca para a API em vez de usar uma API gerenciada e com proxy.

  1. Em um navegador da Web, abra o portal do Azure para criar um novo aplicativo do Azure Functions: Criar novo aplicativo

  2. Use as seguintes informações para criar o Aplicativo de Funções::

    Guia:Configuração Valor
    Noções básicas: Assinatura Selecione a assinatura que deseja usar.
    Noções básicas: Grupo de recursos Crie um novo grupo de recursos, como first-static-web-app-with-apio . O nome não é usado na URL pública do aplicativo. Os grupos de recursos ajudam você a agrupar e gerenciar recursos relacionados do Azure.
    Noções básicas: detalhes da instância: nome do aplicativo de funções Insira um nome globalmente exclusivo, como swa-api com 3 caracteres aleatórios adicionados no final, como swa-api-123.
    Noções básicas: detalhes da instância: código ou contêiner Selecione Code.
    Noções básicas: Detalhes da instância: Pilha de tempo de execução Selecione Node.js.
    Noções básicas: Detalhes da instância: Pilha de tempo de execução Selecione 18LTS.
    Noções básicas: sistema operacional Selecione Linux.
    Noções básicas: hospedagem Selecione Consumption.
    Armazenamento: conta de armazenamento Não altere isso. Uma nova conta de Armazenamento do Azure é criada para ajudar com eventos de função.
    Rede Não mude nada.
    Monitoramento: Application Insights: Habilitar o Application Insights Selecione Yes. Não altere o nome padrão fornecido.
    Implantação: Configurações do GitHub Actions: implantação contínua Selecione Enable.
    Implantação: conta do GitHub Selecione sua conta do GitHub.
    Implantação: Organização Selecione sua conta do GitHub, que você usou quando bifurcou o repositório de exemplo.
    Implantação: Repositório Selecione o nome do repositório bifurcado, azure-typescript-e2e-apps.
    Implantação: Filial Selecione main.
    Marcações Não mude nada.
    Examinar + criar Selecione Create.

    A etapa adiciona um arquivo de fluxo de trabalho yaml do GitHub ao repositório bifurcado.

  3. Quando o recurso for criado, selecione o Go to resource botão.

  4. Selecione Configurações –> Configuração e adicione uma definição de configuração para o runtime do Azure Function Node.js v4 com nome AzureWebJobsFeatureFlags e valor EnableWorkerIndexing.

  5. Clique em Salvar para salvar a configuração.

  6. Em um terminal bash, use o git para extrair o novo arquivo de fluxo de trabalho yaml do repositório bifurcado do GitHub para o computador local.

    git pull origin main
    
  7. No Visual Studio Code, abra o novo arquivo de fluxo de trabalho yaml localizado em ./.github/workflows/.

  8. O arquivo de fluxo de trabalho padrão fornecido para você pressupõe que o código-fonte da função está na raiz do repositório e é o único aplicativo no repositório, mas esse não é o caso deste exemplo. Para corrigir isso, edite o arquivo. As linhas a serem editadas são destacadas no seguinte bloco yaml e explicadas abaixo:

    # Docs for the Azure Web Apps Deploy action: https://github.com/azure/functions-action
    # More GitHub Actions for Azure: https://github.com/Azure/actions
    
    # Deploy Azure Functions Node.js v4 runtime
    # with api-inmemory subdir
    
    name: Azure Function App - api-inmemory
    
    on:
      push:
        branches:
          - main
        paths:
          - 'api-inmemory/**'
      workflow_dispatch:
    
    env:
      AZURE_FUNCTIONAPP_PACKAGE_PATH: 'api-inmemory' # set this to the path to your web app project, defaults to the repository root
      NODE_VERSION: '18.x' # Azure Functions v4 runtime requires 18
      VERBOSE: true # For debugging
    
    jobs:
      build-and-deploy:
        runs-on: ubuntu-latest
        steps:
          - name: 'Checkout GitHub Action'
            uses: actions/checkout@v2
    
          - name: Setup Node ${{ env.NODE_VERSION }} Environment
            uses: actions/setup-node@v1
            with:
              node-version: ${{ env.NODE_VERSION }}
    
          - name: 'Resolve Project Dependencies Using Npm'
            shell: bash
            run: |
              pushd './${{ env.AZURE_FUNCTIONAPP_PACKAGE_PATH }}'
              npm install
              npm run build --if-present
              npm run test --if-present
              popd
          - name: 'Upload artifact for deployment job' # For debugging
            uses: actions/upload-artifact@v3
            with:
              name: azure-function-v4-app
              path: |
                ${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}
                !${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}/node_modules
                !${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}/dist          
          - name: 'Run Azure Functions Action'
            uses: Azure/functions-action@v1
            id: fa
            with:
              app-name: 'swa-api' # change this to your Azure Function app name
              slot-name: 'Production'
              package: ${{env.AZURE_FUNCTIONAPP_PACKAGE_PATH}}
              publish-profile: ${{ secrets.AZUREAPPSERVICE_PUBLISHPROFILE_123 }}
              scm-do-build-during-deployment: false
              enable-oryx-build: false
    
    Alteração da propriedade Finalidade
    name Encurte o nome para que você possa encontrá-lo facilmente na lista de ações do GitHub do seu fork.
    paths Adicione a seção paths para limitar a implantação a ser executada somente quando o código da API do Azure Functions for alterado. Ao editar o arquivo de fluxo de trabalho, você pode acionar a implantação manualmente.
    AZURE_FUNCTIONAPP_PACKAGE_PATH Ao usar uma subdireção para o código-fonte, isso precisa ser o caminho e o nome do subdiretório.
    VERBOSE Essa configuração é útil para depurar o processo de build e implantação.
    Etapa nomeada Upload artifact for deployment job Esta etapa cria um artefato para download. Isso é útil ao depurar exatamente quais arquivos são implantados em sua função do Azure.

    O Upload artifact for deployment job é opcional. Ele é usado para entender e depurar quais arquivos são implantados no Azure Functions ou para usar esses arquivos em um ambiente separado.

  9. Salve o arquivo, adicione, confirme e envie-o de volta para o GitHub com git:

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  10. Em um navegador, execute novamente o fluxo de trabalho no GitHub na área de ações da bifurcação.

    Captura de tela do repositório bifurcado do GitHub, mostrando como executar novamente uma ação do GitHub.

  11. Aguarde até que a ação seja concluída com êxito antes de continuar.

  12. Em um navegador da Web, use o ponto de extremidade de API externo do aplicativo de funções para verificar se o aplicativo implantado foi implantado com êxito.

    https://YOUR-FUNCTION-APP-NAME.azurewebsites.net/api/todo
    

    O resultado JSON retornado para os dados na memória é:

    {
        "1": "Say hello"
    }
    
  13. Anote o URL da sua função. Você precisa disso na próxima seção.

  14. Você sabe que seu aplicativo Azure Function está funcionando na nuvem. Agora você precisa criar seu aplicativo Web estático na nuvem para usar a API.

6. Criar um novo aplicativo Web estático do Azure

Esse processo de criação implanta o mesmo repositório de exemplo bifurcado do GitHub no Azure. Você configura a implantação para usar apenas o aplicativo front-end.

  1. Abra o portal do Azure e entre com sua conta do Azure: portal do Azure.

  2. Use as seguintes informações para concluir as etapas de criação:

    Prompt Configuração
    Subscription Selecione a assinatura que deseja usar.
    Grupo de recursos Selecione Create new e insira um novo para o grupo de recursos, como first-static-web-app. O nome não é usado na URL pública do aplicativo. Os grupos de recursos ajudam a agrupar os recursos usados para um único projeto.
    Tipo de plano de hospedagem Selecione Free
    Azure Functions e detalhes de preparo Não altere o padrão. Você não está implantando a API de Função no aplicativo Web estático.
    Detalhes da implantação – origem Selecione GitHub
    Detalhes da implantação - GitHub Entre no GitHub, se necessário.
    Detalhes da implantação - Organização Selecione sua conta do GitHub.
    Detalhes da implantação - Repositório Selecione o repositório bifurcado chamado azure-typescript-e2e-apps.
    Detalhes da implantação – Branch Selecione a main ramificação.
    Detalhes da compilação - Build Presents Selecione Custom.
    Detalhes da compilação – Localização do aplicativo Digite /app-react-vite.
    Detalhes da compilação – Local da API Deixar em branco
    Detalhes da compilação – Local de saída Insira o local do diretório de saída do front-end, dist.
  3. Selecione Examinar + criare Criar.

  4. Quando o recurso for criado, selecione o Go to resource botão.

  5. Na página Visão geral , anote a URL do aplicativo Web estático. Você precisará disso na próxima seção ao definir a configuração de CORS do Azure Function.

  6. O processo de criação cria um arquivo de fluxo de trabalho yaml do GitHub em seu repositório GitHub bifurcado. Puxe essa alteração para baixo com o seguinte comando:

    git pull origin main
    
  7. A ação do GitHub encontrada em ./.github/workflows/azure-static-web-apps-*.yml é responsável por criar e implantar o aplicativo front-end. Edite o arquivo para adicionar uma variável de ambiente para a URL da API de back-end baseada em nuvem. As linhas a serem editadas são destacadas no bloco yaml a seguir e explicadas abaixo do bloco yaml.

    name: Azure Static Web Apps CI/CD
    
    on:
      push:
        branches:
          - main
        paths:
          - 'app-react-vite/**'
      pull_request:
        types: [opened, synchronize, reopened, closed]
        branches:
          - main
        paths:
          - 'app-react-vite/**'      
      workflow_dispatch:
    
    jobs:
      build_and_deploy_job:
        if: github.event_name == 'push' || github.event_name == 'workflow_dispatch' || (github.event_name == 'pull_request' && github.event.action != 'closed')
        runs-on: ubuntu-latest
        name: Build and Deploy Job
        steps:
          - uses: actions/checkout@v2
            with:
              submodules: true
          - 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_ORANGE_DUNE_123 }}
              repo_token: ${{ secrets.GITHUB_TOKEN }} # Used for Github integrations (i.e. PR comments)
              action: "upload"
              ###### Repository/Build Configurations - These values can be configured to match your app requirements. ######
              # For more information regarding Static Web App workflow configurations, please visit: https://aka.ms/swaworkflowconfig
              app_location: "/app-react-vite" # App source code path
              api_location: "" # Api source code path - optional
              output_location: "dist" # Built app content directory - optional
              ###### End of Repository/Build Configurations ######
            env: 
              VITE_BACKEND_URI: https://swa-api-123.azurewebsites.net
              VITE_CLOUD_ENV: production
    
      close_pull_request_job:
        if: github.event_name == 'pull_request' && github.event.action == 'closed'
        runs-on: ubuntu-latest
        name: Close Pull Request Job
        steps:
          - name: Close Pull Request
            id: closepullrequest
            uses: Azure/static-web-apps-deploy@v1
            with:
              azure_static_web_apps_api_token: ${{ secrets.AZURE_STATIC_WEB_APPS_API_TOKEN_ORANGE_DUNE_123 }}
              action: "close"
    
    Alteração da propriedade Finalidade
    paths Adicione a seção paths para limitar a implantação a ser executada somente quando o código da API do Azure Functions for alterado. Ao editar o arquivo de fluxo de trabalho, você pode acionar a implantação manualmente.
    workflow_dispatch Adicione workflow_dispatch apenas enquanto aprende o processo de implantação e depura quaisquer problemas na compilação da Vite. Remova essa linha ao continuar com esse código-fonte além deste artigo.
    if ... || github.event_name == 'workflow_dispatch' Inclua o workflow_dispatch evento como permitido para gerar uma compilação apenas enquanto aprende o processo de implantação e depura quaisquer problemas na compilação da Vite.
    env Adicione as variáveis de ambiente necessárias para incluir a URL da API de Funções do Azure na compilação estática com a Vite. VITE_BACKEND_URL é a URL do seu aplicativo Azure Function. VITE_CLOUD_ENV é um parâmetro para indicar quando usar o URL VITE_BACKEND_URL. Não use NODE_ENV para este exemplo, pois ele tem efeitos colaterais não intencionais.
  8. Salve o arquivo, adicione, confirme e envie-o de volta para o GitHub com git:

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  9. Em um navegador, execute novamente o fluxo de trabalho no GitHub na área de ações da bifurcação para seu aplicativo Web estático.

  10. Seu aplicativo front-end é implantado no Azure. Agora você precisa configurar o aplicativo de funções do Azure para permitir solicitações CORS do seu aplicativo Web estático.

7. Configurar o CORS para seu aplicativo de funções do Azure

Ao usar um aplicativo de funções do Azure separado, em vez de um aplicativo de funções gerenciado, você precisa configurar o CORS para permitir solicitações de seu aplicativo Web estático.

  1. No portal do Azure, abra seu aplicativo Azure Function.
  2. Na seção API –> CORS, adicione a URL do aplicativo Web estático à lista de origens permitidas.

8. Testar seu aplicativo Web estático

  1. Em um navegador, abra seu aplicativo Web estático.
  2. Interaja com o aplicativo para entrar, exibir informações públicas e privadas e sair novamente.

9. Limpe todos os recursos usados nesta série de artigos

Limpe todos os recursos criados nesta série de artigos.

  1. No portal do Azure, exclua o grupo de recursos, que exclui o aplicativo Web estático e o aplicativo de funções.
  2. No portal do GitHub, exclua o repositório bifurcado.

Solução de problemas

Este exemplo mantém uma lista de problemas conhecidos e resoluções. Se o seu problema não estiver listado, abra um problema.

URLs públicas do aplicativo Web estático e do aplicativo de funções

Você sempre pode encontrar a URL do aplicativo Web estático e a URL do aplicativo de funções no portal do Azure, na página Visão geral de cada recurso. Esses URLs são públicos por padrão.

Próximas etapas