1. 記事一覧 >
  2. ブログ記事
Azure
category logo

【swa】Azure Static Web Appsをローカル環境でデバッグ

(更新) (公開)

はじめに

公式ドキュメント Azure Static Web Apps 用にローカル開発環境を設定する を参考に、Azure Static Web Apps をローカル環境でデバッグできるまでの手順をやってみましたので、以下にまとめます。
ローカル環境とは、インターネットに接続しないオフライン環境のことです。
Azure のアカウントを持っていなくても、動作確認できます。


以下の図のように、
フロントエンド:React & TypeScript
バックエンド:Python (Azure Functions)
の構成を前提とします。

swa 構成 図

バックエンドは、api/ ディレクトリに入れて、Azure Static Web Apps にデプロイすると、API として構築されます。個別に Azure Functions にデプロイするわけではありません。

承認と認証のエミュレーションは、今回実施していません。

インストール中は、インターネット接続が必要です。

【検証環境】

Ubuntu 20.04.2 LTS

 node 14.20.0

 npm 6.14.17

 React 18.2.0

 eslint 8.20.0

 prettier 2.7.1

 Python 3.8.10

 black 22.6.0

 flake8 4.0.1

Windows 10 Pro x64

 拡張機能 Azure Functions 1.7.4


基本環境

別記事
React TypeScript ESLint Prettier VSCode のプロジェクト作成
VS Code で Python のコードフォーマッター(black)、リンター(flake8)をセットアップ
を実施済みとします。


これにより、以下の環境をスタート地点とします。
・node, npm インストール済み
・Ubuntu - VS Code SSH 接続で開発中
sample-project という React & TypeScript のプロジェクトを作成済み
・ESLint Prettier をセットアップ済み
・python3, pip3 インストール済み
・VS Code の Python 拡張機能インストール済み
・VS Code で Python のコードフォーマッター(black)、リンター(flake8)をセットアップ済み
・Python(バックエンド)の実装は、まだ何もしていない

$ which black
/home/admin/.local/bin/black
$ which flake8
/home/admin/.local/bin/flake8

settings.json は、以下の状態とします。

$ cat .vscode-server/data/Machine/settings.json
{
  "editor.defaultFormatter": "esbenp.prettier-vscode",
  "editor.formatOnSave": true,
  "python.formatting.provider": "black",
  "python.linting.pylintEnabled": false,
  "python.linting.flake8Enabled": true,
  "python.linting.flake8Args": [
    "--max-line-length=88",
    "--ignore=E203,W503,W504"
  ]
}

$ cd sample-project
$ npm start

で、
何の変哲もないこの状態です。

React App プロジェクト作成直後


Functions API 作成

api/ にプログラムを作成すると、バックエンド側(API)になるのですが、ちゃんと動くようになるには、作法が有ります。


Microsoft 公式ドキュメント クイックスタート: Visual Studio Code と Python を使用して Azure に関数を作成する の手順で、その作法に従ったものが自動的に作成されますので、この手順でいきます。

公式ドキュメントは、Azure Functions のサーバーレス環境にデプロイしていますが、今回、その話では無いため、そこまでは実施しないです。

また、Azure Functions にデプロイして、Azure Static Web Apps に持ち込む話でもないです。


サーバーに Azure Functions Core Tools をインストールします。

$ cd ~
$ curl https://packages.microsoft.com/keys/microsoft.asc | gpg --dearmor > microsoft.gpg
$ sudo mv microsoft.gpg /etc/apt/trusted.gpg.d/microsoft.gpg
$ sudo sh -c 'echo "deb [arch=amd64] https://packages.microsoft.com/repos/microsoft-ubuntu-$(lsb_release -cs)-prod $(lsb_release -cs) main" > /etc/apt/sources.list.d/dotnetdev.list'
$ sudo apt update
$ sudo apt install azure-functions-core-tools-4

VS Code に
Azure Functions 拡張機能
をインストールします。

Azure Functions 拡張機能 インストール


api/ ディレクトリを作成します。sample-project/api です。

sample-project/api 作成


フォルダーを開く... → sample-project/api を開きます。

sample-project は、API のディレクトリでは無いため、sample-project/api を API のトップディレクトリとし、以降の作業に進めます。

フォルダーを開く...


sample-project/api を開く


python3.8-venv をインストールしておきます。

$ sudo apt install python3.8-venv

ここで、python3.8-venv をインストールしておかないと、この後の手順で以下のエラーになります。

9:35:13 PM: Running command: "python3 -m venv .venv"...
The virtual environment was not created successfully because ensurepip is not
available.  On Debian/Ubuntu systems, you need to install the python3-venv
package using the following command.

    apt install python3.8-venv

You may need to use sudo with that command.  After installing the python3-venv
package, recreate your virtual environment.

Failing command: ['/home/admin/sample-project/api/.venv/bin/python3', '-Im', 'ensurepip', '--upgrade', '--default-pip']

9:35:14 PM: Error: Failed to run "python3" command. Check output window for more details.

Azure マークが現れるので、クリックして、WORKSPACE Local の + ボタンをクリックします。

WORKSPACE + ボタンをクリック


Create Function をクリックします。

Create Function をクリック


Yes をクリックします。

Yes をクリック


Python をクリックします。

Python をクリック


Python3 3.8.10 をクリックします。

Python3 3.8.10 をクリック


HTTP trigger をクリックします。

HTTP trigger をクリック

何がきっかけで起動する API なのかを選択します。今回、HTTP GET で起動する API を作成するため、HTTP trigger になります。


HttpTrigger1 を入力してエンターキーを押します。

HttpTrigger1 を入力してエンターキー


Anonymous をクリックします。

Anonymous をクリック

【 承認レベルについて 】

Anonymous 以外を選択すると、API キーが必要になるのですが、Azure Static Web Apps に API キーを設定する方法が見つからなかったため、おそらく、Anonymous にしないといけないと思われます。(API キーを設定する方法が有るかもしれませんが、とにかく今回は、必要無しとして進めます。)


__init__.py 他、基本的な Azure Function API の実装と設定が作成されます。


ここで、flake8 が venv にインストールされていないため、VS Code がインストールを促してきます。
インストールします。

flake8 インストール


また、__init__.py を保存すると、black のインストールも促されるため、これもインストールします。

black インストール


__init__.py のままだと1行が長すぎてリンターに引っかかっていますので、修正します。

1行が長すぎてリンターエラー 修正前

1行が長すぎてリンターエラー 修正後


Functions API デバッグ

Functions API 単独でデバッグします。


__init__.py を開いているところで、F5 キーを押します。

Azure Functions Core Tools がインストールされていない場合、ここで以下のエラーになります。

You must have the Azure Functions Core Tools installed to debug your local functions.

Azure Functions Core Tools がインストールされていない場合 エラー

API が起動して、デバッグできる状態になりました。

API が起動して、デバッグできる状態


name パラメータ有り無しで、レスポンスが変わります。レスポンスはただの文字列です。

$ curl http://localhost:7071/api/HttpTrigger1
This HTTP triggered function executed successfully.Pass a name in the query string or in the request body for a personalized response.
$ curl http://localhost:7071/api/HttpTrigger1?name=John
Hello, John. This HTTP triggered function executed successfully.

ブレークポイントで止められます。 API ブレークポイント


swa インストール

Functions API 単独の動作確認が完了しましたので、上のディレクトリ sample-project を開きなおします。
以下の警告が有る場合、Don't warn again を選択します。
Detected an Azure Functions Project in folder "sample-project" that may have been created outside of VS Code.Initialize for optimal use with VS Code?

Don't warn again

ここで、Yes を選択すると、
sample-project/.venv/
sample-project/.vscode/
sample-project/.funcignore
が親フォルダにも反映されて、API 仕様の構成になります。


以下のようにして、swa コマンド(@azure/static-web-apps-cli)をインストールします。

$ sudo npm install -g @azure/static-web-apps-cli --unsafe-perm
$ npm run build
$ swa start

prebuild-install warn install EACCES: permission denied, access '/root/.npm'

のエラーになったため、--unsafe-perm オプションを付けました。

MS公式ドキュメントの場合、azure-functions-core-tools もインストールしていますが、

既にインストール済みのため、スキップしています。


ビルドして、起動してみます。

$ npm run build
$ swa start ./build --api-location ./api

npm run build でビルドすると、index.html./build にできるため、./build を明示しています。

swa start ./build --api-location ./api


起動ヨシ!


API は、7071 ポートで起動しますが、以下の図のように 4280 ポートで起動できます。

4280 ポートで起動 図

$ curl http://localhost:7071/api/HttpTrigger1
This HTTP triggered function executed successfully.Pass a name in the query string or in the request body for a personalized response.
$ curl http://localhost:4280/api/HttpTrigger1
This HTTP triggered function executed successfully.Pass a name in the query string or in the request body for a personalized response.

API 呼び出しボタン追加

画面から API を呼び出すボタンを追加します。
URL は、自分の API のため、/api/HttpTrigger1 になります。

画面から API を呼び出すボタンを追加


axios をインストールして、App.tsx を以下の内容に書き換えます。

$ npm install axios
App.tsx
import React, { useRef, useState } from 'react';
import axios, { AxiosRequestConfig, AxiosResponse, AxiosError } from 'axios';
import logo from './logo.svg';
import './App.css';

const options: AxiosRequestConfig = {
  url: `/api/HttpTrigger1`,
  method: 'GET',
};
function App() {
  const inputRef = useRef<HTMLInputElement>(null);
  const [response, setResponse] = useState('');
  const handleAPIGet = () => {
    axios({
      ...options,
      params: {
        name: inputRef.current?.value || '',
      },
    })
      .then((res: AxiosResponse<string>) => {
        const { data } = res;
        setResponse(data);
      })
      .catch((e: AxiosError<{ error: string }>) => {
        console.log(e.message); // eslint-disable-line no-console
      });
  };
  return (
    <div className="App">
      <header className="App-header">
        <img src={logo} className="App-logo" alt="logo" />
        <p>
          Edit <code>src/App.tsx</code> and save to reload.
        </p>
        <a
          className="App-link"
          href="https://reactjs.org"
          target="_blank"
          rel="noopener noreferrer"
        >
          Learn React
        </a>
        <div>
          <input ref={inputRef} type="text" name="name" />
          <button type="submit" onClick={handleAPIGet}>
            API Get!
          </button>
          <p>Response : {response}</p>
        </div>
      </header>
    </div>
  );
}

export default App;

ソースコード diff


swa デバッグ

さて、いよいよ、swa で起動した状態でデバッグします。
フロントエンドを 3000 ポートで起動します。

$ cd ~/sample-project
$ npm start

フロントエンドを 3000 ポートで起動


バックエンドを 7071 ポートで起動します。
これは、API 単独でデバッグした時と同じく、
__init__.py を開いているところで、F5 キーを押します。
注意:sample-project/api を別のウィンドウで開いた状態です。

バックエンドを 7071 ポートで起動


sample-project のウィンドウに戻って、(teraterm などでも良いですが。)別セッションで、swa を起動します。

別セッションで、swa を起動

$ cd ~/sample-project
$ swa start http://localhost:3000 --api-location http://localhost:7071

swa起動1


swa起動2


App.tsx を開いているところで、F5 キーを押します。

デバッガー を Chrome とします。

デバッガー を Chrome


ポートを 4280 にします。

ポートを 4280


フロントエンド側:ボタンクリック
バックエンド側:リクエスト受信
のところにブレークポイントを貼って止められるか、試します。

フロントエンド バックエンド ブレークポイント1


フロントエンド バックエンド ブレークポイント2


フロントエンド バックエンド ブレークポイント3


ヨシ!!

loading...