- 記事一覧 >
- ブログ記事
【swa】Azure Static Web Appsをローカル環境でデバッグ
はじめに
公式ドキュメント Azure Static Web Apps 用にローカル開発環境を設定する を参考に、Azure Static Web Apps をローカル環境でデバッグできるまでの手順をやってみましたので、以下にまとめます。
ローカル環境とは、インターネットに接続しないオフライン環境のことです。
Azure のアカウントを持っていなくても、動作確認できます。
以下の図のように、
フロントエンド:React & TypeScript
バックエンド:Python (Azure Functions)
の構成を前提とします。
バックエンドは、
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
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 拡張機能
をインストールします。
api/
ディレクトリを作成します。sample-project/api
です。
フォルダーを開く... → sample-project/api
を開きます。
sample-project
は、API のディレクトリでは無いため、sample-project/api
を 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 の + ボタンをクリックします。
Create Function をクリックします。
Yes をクリックします。
Python をクリックします。
Python3 3.8.10 をクリックします。
HTTP trigger をクリックします。
何がきっかけで起動する API なのかを選択します。今回、HTTP GET で起動する API を作成するため、HTTP trigger になります。
HttpTrigger1 を入力してエンターキーを押します。
Anonymous をクリックします。
【 承認レベルについて 】
Anonymous
以外を選択すると、API キーが必要になるのですが、Azure Static Web Apps に API キーを設定する方法が見つからなかったため、おそらく、Anonymous
にしないといけないと思われます。(API キーを設定する方法が有るかもしれませんが、とにかく今回は、必要無しとして進めます。)
__init__.py
他、基本的な Azure Function API の実装と設定が作成されます。
ここで、flake8 が venv にインストールされていないため、VS Code がインストールを促してきます。
インストールします。
また、__init__.py
を保存すると、black のインストールも促されるため、これもインストールします。
__init__.py
のままだと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.
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.
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?
ここで、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
を明示しています。
起動ヨシ!
API は、7071 ポートで起動しますが、以下の図のように 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
になります。
axios
をインストールして、App.tsx
を以下の内容に書き換えます。
$ npm install axios
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;
swa デバッグ
さて、いよいよ、swa で起動した状態でデバッグします。
フロントエンドを 3000 ポートで起動します。
$ cd ~/sample-project
$ npm start
バックエンドを 7071 ポートで起動します。
これは、API 単独でデバッグした時と同じく、__init__.py
を開いているところで、F5 キーを押します。
(注意:sample-project/api
を別のウィンドウで開いた状態です。)
sample-project
のウィンドウに戻って、(teraterm などでも良いですが。)別セッションで、swa を起動します。
$ cd ~/sample-project
$ swa start http://localhost:3000 --api-location http://localhost:7071
App.tsx
を開いているところで、F5 キーを押します。
デバッガー を Chrome とします。
ポートを 4280 にします。
フロントエンド側:ボタンクリック
バックエンド側:リクエスト受信
のところにブレークポイントを貼って止められるか、試します。
ヨシ!!
その他、宣伝、誹謗中傷等、当方が不適切と判断した書き込みは、理由の如何を問わず、投稿者に断りなく削除します。
書き込み内容について、一切の責任を負いません。
このコメント機能は、予告無く廃止する可能性があります。ご了承ください。
コメントの削除をご依頼の場合はTwitterのDM等でご連絡ください。