Skapa en statisk webbapp med ett serverlöst API

Lär dig hur du kör lokalt och sedan distribuerar en statisk webbapp med ett serverlöst API till Azure. I den här självstudien används förhandsversionen av den senaste Azure Functions Node.js-programmeringsmodellen. Eftersom den här artikeln använder en förhandsversion av Azure Functions distribueras den som en separat app från den statiska webbappen.

Lär dig att:

  • Kör en statisk webbapp (SWA) lokalt med en Azure-funktionsapp
  • Lokalt proxy-klientdelsbegäranden till det lokala serverdels-API:et med hjälp av SWA CLI.
  • Distribuera och kör samma kod via fjärranslutning.

Proxyn mellan klientdelen och backend-endis som tillhandahålls av static-webbappen CLI tillhandahåller:

  • URL:en i React anger /api/todointe server- eller portnumret för API:et. Begäranden som använder den här URL:en lyckas lokalt eftersom SWA CLI hanterar proxyn åt dig.
  • En lokal autentiseringsemulator vid åtkomst /.auth/login/<provider>
  • Väghantering och auktorisering

Autentisering i det här exemplet

Autentiseringen i det här exemplet tillhandahålls för klientdelsanvändare från Azure Static Web Apps-tjänsten:

  • Logga in/logga ut
  • Offentligt och privat innehåll

Källkod i det här exemplet

Källkoden i det här exemplet är avsedd att lära dig hur du skapar och distribuerar en statisk webbapp med ett serverlöst API. Koden är inte avsedd för produktion.

Du hittar flera platser i koden som inte följer bästa säkerhetsmetoder. Koden används console.log till exempel för att skriva till webbläsarkonsolen.

När du flyttar till en produktionsmiljö bör du granska och ta bort all kod, vilket strider mot bästa praxis för din organisation.

1. Förbered utvecklingsmiljön

Skapa följande konton:

Installera följande på din lokala utvecklingsdator:

2. Förgrena exempellagringsplatsen på GitHub

Du måste ha en egen förgrening av exempellagringsplatsen för att slutföra distributionen från GitHub. Under förgreningsprocessen behöver du bara kopiera grenen main .

Förgrena exempellagringsplatsen: https://github.com/Azure-Samples/azure-typescript-e2e-apps.

3. Klona den förgrenade exempellagringsplatsen

  1. Klona den förgrenade lagringsplatsen till den lokala datorn i en bash-terminal. Klona inte den ursprungliga exempellagringsplatsen. En exempel-URL är https://github.com/YOUR-ACCOUNT-NAME/azure-typescript-e2e-apps

    git clone YOUR-FORKED-REPO-URL
    
  2. Installera beroenden för den lokala klientdelsappen:

    cd app-react-vite && npm install 
    
  3. Installera beroenden för den lokala serverdelsappen:

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

4. Valfritt, skapa och köra lokal app

Exempellagringsplatsen har flera versioner av klientdels- och serverdelsapparna. Följande steg använder React 18-versionen (Vite) av klientdelen och Azure Function v4 med Node.js-versionen av serverdelen med /status api-vägarna och /todo .

  1. Från roten i exempelappen använder du SWA CLI med ./swa-cli.config.json filen för att skapa klientdels- och serverdelsapparna:

    swa build
    

    Om du stöter på fel, vilket kan inträffa beroende på vilken version av olika paket och din miljö du har, kan du åtgärda felen innan du fortsätter. Det är viktigt att veta att projektet har skapats lokalt innan du går vidare till distributionen till Azure Static Web Apps.

  2. Från roten i exempelappen använder du SWA CLI för att starta apparna med en proxy.

    swa start
    
  3. När du ser följande rader i bash-terminalen har projektet startats.

    [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. Öppna en webbläsare till den proxierade URL:en, http://localhost:4280. Du bör se följande sida:

    Screenshot of local React app prior to authentication.

  5. Du kan logga in med hjälp av autentisering som tillhandahålls av SWA CLI. Processen simulerar autentisering i molnbaserade Azure Static-webbappar. Klientdelskoden använder /.auth/me slutpunkten för att hämta användarens identitet. Ange ett falskt användarnamn och ändra inte resten av fälten.

    Screenshot of local React app's mock authentication form.

  6. När en användare har autentiserats visar klientdelen privat information, till exempel API:ets miljövariabler.

    Screenshot of local React app with authentication complete.

    Azure Function v4-appens källkod för det här API:et är:

    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. Expandera de offentliga och privata avsnitten för att se att innehållet från API:et visas.

5. Skapa en ny Azure Functions-app

Föregående avsnitt i körningen av den statiska webbappen med API:et var valfritt. De återstående avsnitten i artikeln krävs för att distribuera appen och API:et till Azure-molnet.

Om du vill använda förhandsversionen av Azure Functions v4-körningen måste du skapa en ny Azure Functions-app. Din statiska webbapp måste också återskapas och distribueras om för att använda Azure Functions-app-URI:n i Hämta begäranden till API:et i stället för att använda ett proxierat och hanterat API.

  1. I en webbläsare öppnar du Azure-portalen för att skapa en ny Azure Functions-app: Skapa ny app

  2. Använd följande information för att skapa funktionsappen::

    Tabb:Inställning Värde
    Grunderna: Prenumeration Välj den prenumeration som du vill använda.
    Grunderna: Resursgrupp Skapa en ny resursgrupp, till exempel first-static-web-app-with-api. Namnet används inte i appens offentliga URL. Resursgrupper hjälper dig att gruppera och hantera relaterade Azure-resurser.
    Grunderna: Instansinformation: Funktionsappens namn Ange ett globalt unikt namn, till exempel swa-api med tre slumpmässiga tecken som har lagts till i slutet, till exempel swa-api-123.
    Grunderna: Instansinformation: Kod eller container Välj Code.
    Grunderna: Instansinformation: Körningsstack Välj Node.js.
    Grunderna: Instansinformation: Körningsstack Välj 18LTS.
    Grunderna: Operativsystem Välj Linux.
    Grunderna: Värd Välj Consumption.
    Lagring: Lagringskonto Ändra inte detta. Ett nytt Azure Storage-konto skapas för att hjälpa till med funktionshändelser.
    Nätverk Ändra ingenting.
    Övervakning: Application Insights: Aktivera Application Insights Välj Yes. Ändra inte det angivna standardnamnet.
    Distribution: GitHub Actions Inställningar: Kontinuerlig distribution Välj Enable.
    Distribution: GitHub-konto Välj ditt GitHub-konto.
    Distribution: Organisation Välj ditt GitHub-konto som du använde när du förgrenade exempellagringsplatsen.
    Distribution: Lagringsplats Välj namnet på den förgrenade lagringsplatsen, azure-typescript-e2e-apps.
    Distribution: Gren Välj main.
    Taggar Ändra ingenting.
    Granska + skapa Välj Create.

    Steget lägger till en GitHub yaml-arbetsflödesfil till din förgrenade lagringsplats.

  3. När resursen har skapats väljer du Go to resource knappen .

  4. Välj Inställningar –> Konfiguration och lägg sedan till en konfigurationsinställning för Azure Function Node.js v4-körningen med namn AzureWebJobsFeatureFlags och värde EnableWorkerIndexing.

  5. Spara inställningen genom att välja Spara.

  6. I en bash-terminal använder du git för att hämta den nya yaml-arbetsflödesfilen från din GitHub-förgrenade lagringsplats till din lokala dator.

    git pull origin main
    
  7. I Visual Studio Code öppnar du den nya yaml-arbetsflödesfilen som finns på ./.github/workflows/.

  8. Standardarbetsflödesfilen som tillhandahålls för dig förutsätter att funktionens källkod finns i roten på lagringsplatsen och är den enda appen på lagringsplatsen, men så är inte fallet med det här exemplet. Du kan åtgärda det genom att redigera filen. Raderna som ska redigeras är markerade i följande yaml-block och förklaras nedan:

    # 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
    
    Egenskapsändring Syfte
    name Förkorta namnet så att du enkelt kan hitta det i din förgrenings GitHub-åtgärdslista.
    paths Lägg till avsnittet sökvägar för att begränsa distributionen så att den endast körs när Azure Functions API-koden ändras. När du redigerar arbetsflödesfilen kan du utlösa distributionen manuellt.
    AZURE_FUNCTIONAPP_PACKAGE_PATH När du använder en underkatalog för källkod måste detta vara underkatalogsökvägen och namnet.
    VERBOSE Den här inställningen är användbar för att felsöka bygg- och distributionsprocessen.
    steg med namnet Upload artifact for deployment job Det här steget skapar en nedladdningsbar artefakt. Det här är användbart när du felsöker exakt vilka filer som distribueras till din Azure-funktion.

    Är Upload artifact for deployment job valfritt. Den används för att förstå och felsöka vilka filer som distribueras till Azure Functions eller för att använda filerna i en separat miljö.

  9. Spara filen och lägg sedan till, checka in och skicka tillbaka den till GitHub med git:

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  10. Kör arbetsflödet på GitHub igen i din förgrenings åtgärdsområde från en webbläsare.

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

  11. Vänta tills åtgärden har slutförts innan du fortsätter.

  12. I en webbläsare använder du funktionsappens externa API-slutpunkt för att verifiera att appen har distribuerats.

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

    JSON-resultatet som returneras för minnesintern data är:

    {
        "1": "Say hello"
    }
    
  13. Anteckna funktionens URL. Du behöver det i nästa avsnitt.

  14. Du vet att din Azure-funktionsapp fungerar i molnet. Nu måste du skapa din statiska webbapp i molnet för att använda API:et.

6. Skapa en ny Azure Static-webbapp

Den här skapandeprocessen distribuerar samma förgrenade GitHub-exempellagringsplats till Azure. Du konfigurerar distributionen så att den endast använder klientdelsappen.

  1. Öppna Azure-portalen och logga in med ditt Azure-konto: Azure-portalen.

  2. Använd följande information för att slutföra stegen för att skapa:

    Prompt Inställning
    Prenumeration Välj den prenumeration som du vill använda.
    Resursgrupp Välj Create new och ange en ny för resursgruppen, till exempel first-static-web-app. Namnet används inte i appens offentliga URL. Resursgrupper hjälper dig att gruppera resurser som används för ett enskilt projekt.
    Typ av värdplan Välj Free
    Information om Azure Functions och mellanlagring Ändra inte standardinställningen. Du distribuerar inte funktions-API:et i den statiska webbappen.
    Distributionsinformation – källa Välj GitHub
    Distributionsinformation – GitHub Logga in på GitHub om det behövs.
    Distributionsinformation – Organisation Välj ditt GitHub-konto.
    Distributionsinformation – lagringsplats Välj den förgrenade lagringsplatsen med namnet azure-typescript-e2e-apps.
    Distributionsinformation – gren Välj grenen main .
    Bygginformation – Skapa presenter Välj Custom.
    Skapa information – appplats Ange /app-react-vite.
    Bygginformation – API-plats Lämna tom
    Bygginformation – Utdataplats Ange platsen för klientdelens utdatakatalog, dist.
  3. Välj Granska + skapa och välj sedan Skapa.

  4. När resursen har skapats väljer du Go to resource knappen .

  5. På sidan Översikt antecknar du url:en för den statiska webbappen. Du behöver det i nästa avsnitt när du anger CORS-inställningen för Azure-funktionen.

  6. Skapandeprocessen skapar en GitHub yaml-arbetsflödesfil i din förgrenade GitHub-lagringsplats. Dra ned ändringen med följande kommando:

    git pull origin main
    
  7. GitHub-åtgärden som hittas på ./.github/workflows/azure-static-web-apps-*.yml ansvarar för att skapa och distribuera klientdelsappen. Redigera filen för att lägga till en miljövariabel för den molnbaserade URL:en för serverdelens API. Raderna som ska redigeras är markerade i följande yaml-block och förklaras under yaml-blocket.

    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"
    
    Egenskapsändring Syfte
    paths Lägg till avsnittet sökvägar för att begränsa distributionen så att den endast körs när Azure Functions API-koden ändras. När du redigerar arbetsflödesfilen kan du utlösa distributionen manuellt.
    workflow_dispatch Lägg bara till workflow_dispatchnär du lär dig distributionsprocessen och felsöker eventuella problem i Vite-versionen. Ta bort den här raden när du fortsätter med den här källkoden utöver den här artikeln.
    if ... || github.event_name == 'workflow_dispatch' Inkludera händelsen workflow_dispatch som tillåten att generera en version endast när du lär dig distributionsprocessen och felsöker eventuella problem i Vite-versionen.
    env Lägg till de miljövariabler som krävs för att inkludera URL:en för Azure-funktions-API:et i den statiska versionen med Vite. VITE_BACKEND_URL är URL:en för din Azure-funktionsapp. VITE_CLOUD_ENV är en parameter som anger när VITE_BACKEND_URL URL ska användas. Använd inte NODE_ENV för det här exemplet eftersom det har oavsiktliga sidoeffekter.
  8. Spara filen och lägg sedan till, checka in och skicka tillbaka den till GitHub med git:

    git add .
    git commit -m "fix the workflow for a subdir"
    git push origin main
    
  9. Kör arbetsflödet på GitHub igen i din förgrenings åtgärdsområde för din statiska webbapp.

  10. Klientdelsappen distribueras till Azure. Nu måste du konfigurera Azure-funktionsappen för att tillåta CORS-begäranden från din statiska webbapp.

7. Konfigurera CORS för din Azure-funktionsapp

När du använder en separat Azure-funktionsapp, i stället för en hanterad funktionsapp, måste du konfigurera CORS för att tillåta begäranden från din statiska webbapp.

  1. Öppna azure-funktionsappen i Azure-portalen.
  2. I avsnittet API –> CORS lägger du till url:en för den statiska webbappen i listan över tillåtna ursprung.

8. Testa din statiska webbapp

  1. Öppna din statiska webbapp i en webbläsare.
  2. Interagera med appen för att logga in, visa offentlig och privat information och logga ut igen.

9. Rensa alla resurser som används i den här artikelserien

Rensa alla resurser som skapats i den här artikelserien.

  1. I Azure-portalen tar du bort resursgruppen, som tar bort den statiska webbappen och funktionsappen.
  2. Ta bort den förgrenade lagringsplatsen i GitHub-portalen.

Felsökning

Det här exemplet innehåller en lista över kända problem och lösningar. Om problemet inte visas öppnar du ett problem.

Offentliga URL:er för statisk webbapp och funktionsapp

Du hittar alltid din statiska webbapps URL och funktionsappens URL i Azure-portalen på varje resurss översiktssida. Dessa URL:er är offentliga som standard.

Nästa steg