Creare un'app Web statica con un'API serverless

Informazioni su come eseguire localmente e quindi distribuire un'app Web statica con un'API serverless in Azure. Questa esercitazione usa la versione di anteprima del modello di programmazione Node.js più recente Funzioni di Azure. Poiché questo articolo usa una versione di anteprima di Funzioni di Azure, viene distribuita come app separata dall'app Web statica.

Scopri come:

  • Eseguire localmente un'app Web statica con un'app per le funzioni di Azure
  • Richieste front-end proxy locali all'API back-end locale tramite l'interfaccia della riga di comando di SWA.
  • Distribuire ed eseguire lo stesso codice in remoto.

Il proxy tra il front-end e il back-end forniti dall'interfaccia della riga di comando dell'app Web statica fornisce:

  • L'URL in React, /api/todo, non specifica il server o il numero di porta per l'API. Le richieste che usano questo URL hanno esito positivo in locale perché l'interfaccia della riga di comando di SWA gestisce automaticamente il proxy.
  • Emulatore di autenticazione locale durante l'accesso /.auth/login/<provider>
  • Gestione e autorizzazione delle route

Autenticazione in questo esempio

L'autenticazione in questo esempio viene fornita per gli utenti front-end del servizio App Web statiche di Azure:

  • Accesso/disconnessione
  • Contenuto pubblico e privato

Codice sorgente in questo esempio

Il codice sorgente in questo esempio è progettato per informazioni su come compilare e distribuire un'app Web statica con un'API serverless. Il codice non è destinato all'ambiente di produzione.

Nel codice sono disponibili diverse posizioni che non seguono le procedure di sicurezza consigliate. Ad esempio, il codice usa console.log per scrivere nella console del browser.

Quando si passa a un ambiente di produzione, è necessario esaminare e rimuovere qualsiasi codice che viola le procedure consigliate per la sicurezza per l'organizzazione.

1. Preparare l'ambiente di sviluppo

Creare i seguenti account:

Installare quanto segue nel computer di sviluppo locale:

2. Creare una copia tramite fork del repository di esempio in GitHub

Per completare la distribuzione da GitHub, è necessario disporre di un fork del repository di esempio. Durante il processo di fork, è sufficiente copiare il main ramo.

Creare una copia tramite fork del repository di esempio: https://github.com/Azure-Samples/azure-typescript-e2e-apps.

3. Clonare il repository di esempio con fork

  1. In un terminale bash clonare il repository copiato tramite fork nel computer locale. Non clonare il repository di esempio originale. Un URL di esempio è https://github.com/YOUR-ACCOUNT-NAME/azure-typescript-e2e-apps

    git clone YOUR-FORKED-REPO-URL
    
  2. Installare le dipendenze per l'app front-end locale:

    cd app-react-vite && npm install 
    
  3. Installare le dipendenze per l'app back-end locale:

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

4. Facoltativo, compilare ed eseguire l'app locale

Il repository di esempio include diverse versioni delle app front-end e back-end. I passaggi seguenti usano la versione React 18 (Vite) del front-end e della funzione di Azure v4 con la versione Node.js del back-end con le /status route API e /todo .

  1. Dalla radice dell'app di esempio usare l'interfaccia della riga di comando di SWA con il ./swa-cli.config.json file per compilare le app front-end e back-end:

    swa build
    

    Se si verificano errori, che possono verificarsi a seconda della versione di vari pacchetti e dell'ambiente in uso, correggere gli errori prima di continuare. È importante sapere che il progetto viene compilato correttamente in locale prima di passare alla distribuzione in App Web statiche di Azure.

  2. Dalla radice dell'app di esempio usare l'interfaccia della riga di comando di SWA per avviare le app con un proxy.

    swa start
    
  3. Quando nel terminale bash sono visualizzate le righe seguenti, il progetto è stato avviato correttamente.

    [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. Aprire un Web browser all'URL proxy, http://localhost:4280. Verrà visualizzata la pagina seguente:

    Screenshot of local React app prior to authentication.

  5. È possibile accedere usando l'autenticazione fornita dall'interfaccia della riga di comando di SWA. Il processo simula l'autenticazione nelle app Web statiche di Azure basate sul cloud. Il codice front-end usa l'endpoint /.auth/me per ottenere l'identità dell'utente. Immettere qualsiasi nome utente falso e non modificare il resto dei campi.

    Screenshot of local React app's mock authentication form.

  6. Dopo l'autenticazione di un utente, il front-end visualizza informazioni private , ad esempio le variabili di ambiente dell'API.

    Screenshot of local React app with authentication complete.

    Il codice sorgente dell'app Per le funzioni di Azure v4 per questa 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. Espandere le sezioni pubbliche e private per visualizzare il contenuto dell'API.

5. Creare una nuova app Funzioni di Azure

La sezione precedente dell'esecuzione dell'app Web statica con l'API era facoltativa. Le sezioni rimanenti dell'articolo sono necessarie per distribuire l'app e l'API nel cloud di Azure.

Per usare la versione di anteprima del runtime Funzioni di Azure v4, è necessario creare una nuova app Funzioni di Azure. L'app Web statica deve anche essere ricompilata e ridistribuito per usare l'URI dell'app Funzioni di Azure nelle richieste di recupero all'API anziché usare un'API gestita e proxy.

  1. In un Web browser aprire il portale di Azure per creare una nuova app Funzioni di Azure: Crea nuova app

  2. Usare le informazioni seguenti per creare l'app per le funzioni:

    Scheda:Impostazione Valore
    Nozioni di base: Sottoscrizione selezionare la sottoscrizione da usare.
    Nozioni di base: Gruppo di risorse Creare un nuovo gruppo di risorse, first-static-web-app-with-apiad esempio . Il nome non viene usato nell'URL pubblico dell'app. I gruppi di risorse consentono di raggruppare e gestire le risorse di Azure correlate.
    Informazioni di base: Dettagli istanza: Nome dell'app per le funzioni Immettere un nome univoco globale, ad swa-api esempio con 3 caratteri casuali aggiunti alla fine, ad esempio swa-api-123.
    Nozioni di base: dettagli dell'istanza: codice o contenitore Selezionare Code.
    Nozioni di base: Dettagli dell'istanza: Stack di runtime Selezionare Node.js.
    Nozioni di base: Dettagli dell'istanza: Stack di runtime Selezionare 18LTS.
    Nozioni di base: Sistema operativo Selezionare Linux.
    Nozioni di base: Hosting Selezionare Consumption.
    Archiviazione: account Archiviazione Non modificare questa impostazione. Viene creato un nuovo account Archiviazione di Azure per facilitare l'uso degli eventi di funzione.
    Rete Non cambiare nulla.
    Monitoraggio: Application Insights: Abilitare Application Insights Selezionare Yes. Non modificare il nome predefinito specificato.
    Distribuzione: GitHub Actions Impostazioni: Distribuzione continua Selezionare Enable.
    Distribuzione: account GitHub Selezionare l'account GitHub.
    Distribuzione: Organizzazione Selezionare l'account GitHub usato durante la copia tramite fork del repository di esempio.
    Distribuzione: Repository Selezionare il nome del repository con fork, azure-typescript-e2e-apps.
    Distribuzione: Branch Selezionare main.
    Tag Non cambiare nulla.
    Rivedi e crea Selezionare Create.

    Il passaggio aggiunge un file del flusso di lavoro yaml di GitHub al repository con fork.

  3. Al termine della creazione della risorsa, selezionare il Go to resource pulsante .

  4. Selezionare Impostazioni -> Configurazione e quindi aggiungere un'impostazione di configurazione per il runtime Node.js della funzione di Azure v4 con nome AzureWebJobsFeatureFlags e valore EnableWorkerIndexing.

  5. Selezionare Salva per salvare l'impostazione.

  6. In un terminale bash usare Git per eseguire il pull del nuovo file del flusso di lavoro yaml dal repository fork di GitHub al computer locale.

    git pull origin main
    
  7. In Visual Studio Code aprire il nuovo file del flusso di lavoro yaml disponibile in ./.github/workflows/.

  8. Il file del flusso di lavoro predefinito fornito presuppone che il codice sorgente della funzione si trovi nella radice del repository ed è l'unica app nel repository, ma che non è il caso di questo esempio. Per risolvere il problema, modificare il file. Le righe da modificare sono evidenziate nel blocco yaml seguente e illustrate di seguito:

    # 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
    
    Modifica proprietà Scopo
    name Abbreviare il nome in modo da poterlo trovare facilmente nell'elenco delle azioni GitHub del fork.
    paths Aggiungere la sezione percorsi per limitare l'esecuzione della distribuzione solo quando cambia il codice API Funzioni di Azure. Quando si modifica il file del flusso di lavoro, è possibile attivare la distribuzione manualmente.
    AZURE_FUNCTIONAPP_PACKAGE_PATH Quando si usa una sottodirectory per il codice sorgente, questo deve essere il percorso e il nome della sottodirectory.
    VERBOSE Questa impostazione è utile per il debug del processo di compilazione e distribuzione.
    passaggio denominato Upload artifact for deployment job Questo passaggio crea un artefatto scaricabile. Ciò è utile quando si esegue il debug esattamente dei file distribuiti nella funzione di Azure.

    è Upload artifact for deployment job facoltativo. Viene usato per comprendere ed eseguire il debug dei file distribuiti in Funzioni di Azure o per usare tali file in un ambiente separato.

  9. Salvare il file, quindi aggiungere, eseguire il commit ed eseguirne il push in GitHub con Git:

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  10. Da un browser eseguire di nuovo il flusso di lavoro in GitHub nell'area azioni del fork.

    Screenshot of GitHub forked repository, showing how to rerun a GitHub action.

  11. Attendere il completamento dell'azione prima di continuare.

  12. In un Web browser usare l'endpoint api esterno dell'app per le funzioni per verificare che l'app sia stata distribuita correttamente.

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

    Il risultato JSON restituito per i dati in memoria è:

    {
        "1": "Say hello"
    }
    
  13. Prendere nota dell'URL della funzione. È necessario nella sezione successiva.

  14. Si sa che l'app per le funzioni di Azure funziona nel cloud. A questo punto è necessario creare l'app Web statica nel cloud per usare l'API.

6. Creare una nuova app Web statica di Azure

Questo processo di creazione distribuisce lo stesso repository di esempio GitHub con fork in Azure. Configurare la distribuzione in modo da usare solo l'app front-end.

  1. Aprire il portale di Azure e accedere con l'account Azure: portale di Azure.

  2. Usare le informazioni seguenti per completare i passaggi di creazione:

    Richiesta Impostazione
    Abbonamento selezionare la sottoscrizione da usare.
    Gruppo di risorse Selezionare Create new e immettere un nuovo per il gruppo di risorse, first-static-web-appad esempio . Il nome non viene usato nell'URL pubblico dell'app. I gruppi di risorse consentono di raggruppare le risorse usate per un singolo progetto.
    Tipo di piano di hosting Selezionare Free
    Dettagli di Funzioni di Azure e della gestione temporanea Non modificare il valore predefinito. Non si distribuisce l'API funzione all'interno dell'app Web statica.
    Dettagli della distribuzione - origine Selezionare GitHub
    Dettagli della distribuzione - GitHub Accedere a GitHub, se necessario.
    Dettagli distribuzione - Organizzazione Selezionare l'account GitHub.
    Dettagli distribuzione - Repository Selezionare il repository con fork denominato azure-typescript-e2e-apps.
    Dettagli distribuzione - Ramo Selezionare il main ramo .
    Dettagli della compilazione - Presentazione della compilazione Selezionare Custom.
    Dettagli della compilazione - Percorso app Immetti /app-react-vite.
    Dettagli della compilazione - Percorso API Lasciare vuoto
    Dettagli della compilazione - Percorso di output Immettere il percorso della directory di output del front-end, dist.
  3. Selezionare Rivedi e crea e quindi Crea.

  4. Al termine della creazione della risorsa, selezionare il Go to resource pulsante .

  5. Nella pagina Panoramica prendere nota dell'URL dell'app Web statica. È necessario nella sezione successiva quando si imposta l'impostazione CORS della funzione di Azure.

  6. Il processo di creazione crea un file del flusso di lavoro yaml di GitHub nel repository GitHub con fork. Eseguire il pull verso il basso con il comando seguente:

    git pull origin main
    
  7. L'azione GitHub disponibile in ./.github/workflows/azure-static-web-apps-*.yml è responsabile della compilazione e della distribuzione dell'app front-end. Modificare il file per aggiungere una variabile di ambiente per l'URL dell'API back-end basato sul cloud. Le righe da modificare sono evidenziate nel blocco yaml seguente e illustrate sotto il blocco 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"
    
    Modifica proprietà Scopo
    paths Aggiungere la sezione percorsi per limitare l'esecuzione della distribuzione solo quando cambia il codice API Funzioni di Azure. Quando si modifica il file del flusso di lavoro, è possibile attivare la distribuzione manualmente.
    workflow_dispatch Aggiungere workflow_dispatchsolo durante l'apprendimento del processo di distribuzione e il debug di eventuali problemi nella compilazione Vite. Rimuovere questa riga quando si continua con questo codice sorgente oltre questo articolo.
    if ... || github.event_name == 'workflow_dispatch' Includere l'evento workflow_dispatch come consentito per generare una compilazione solo durante l'apprendimento del processo di distribuzione e il debug di eventuali problemi nella compilazione Vite.
    env Aggiungere le variabili di ambiente necessarie per includere l'URL dell'API funzione di Azure nella compilazione statica con Vite. VITE_BACKEND_URL è l'URL dell'app per le funzioni di Azure. VITE_CLOUD_ENV è un parametro che indica quando usare l'URL di VITE_BACKEND_URL. Non usare NODE_ENV per questo esempio perché ha effetti collaterali imprevisti.
  8. Salvare il file, quindi aggiungere, eseguire il commit ed eseguirne il push in GitHub con Git:

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  9. Da un browser eseguire di nuovo il flusso di lavoro in GitHub nell'area azioni del fork per l'app Web statica.

  10. L'app front-end viene distribuita in Azure. È ora necessario configurare l'app per le funzioni di Azure per consentire le richieste CORS dall'app Web statica.

7. Configurare CORS per l'app per le funzioni di Azure

Quando si usa un'app per le funzioni di Azure separata, anziché un'app per le funzioni gestite, è necessario configurare CORS per consentire le richieste dall'app Web statica.

  1. Nella portale di Azure aprire l'app per le funzioni di Azure.
  2. Nella sezione API -> CORS aggiungere l'URL dell'app Web statica all'elenco delle origini consentite.

8. Testare l'app Web statica

  1. In un browser aprire l'app Web statica.
  2. Interagire con l'app per accedere, visualizzare informazioni pubbliche e private e disconnettersi di nuovo.

9. Pulire tutte le risorse usate in questa serie di articoli

Pulire tutte le risorse create in questa serie di articoli.

  1. Nella portale di Azure eliminare il gruppo di risorse, che elimina l'app Web statica e l'app per le funzioni.
  2. Nel portale GitHub eliminare il repository con fork.

Risoluzione dei problemi

In questo esempio viene mantenuto un elenco di problemi noti e soluzioni. Se il problema non è elencato, aprire un problema.

URL pubblici dell'app Web statica e dell'app per le funzioni

È sempre possibile trovare l'URL dell'app Web statica e l'URL dell'app per le funzioni nella portale di Azure, nella pagina Panoramica di ogni risorsa. Questi URL sono pubblici per impostazione predefinita.

Passaggi successivi