はじめに
先日からAzure Static Web Appsを使ってみています。単なるHTMLだけではなく、ReactやVueなどで作られたページもホスティングでき、APIとしてAzure Functionsも動かすことができるというものということで、実際に試してみています。
前回はReactのチュートリアルであった三目並べを動かしてみました。
今回はAzure Functionsとの連携を試してみたいと思います。
Azure Static Web AppsでのAzure Functions
Azure Static Web AppsでのAzure Functionsは、以下のドキュメントが示すように二種類の利用方法があります。
- マネージド関数
- 独自の関数の持ち込み
色々と自由度が高いのは「独自の関数の持ち込み」ですが、今回はお手軽に試すために「マネージド関数」を使って実装したいと思います。
なお2021年11月の時点で、マネージド関数のデプロイ先は以下の画像のように「Central US」「East US 2」「East Asia」「west Europe」「West US 2」の5つに限られていました。時が解決するとは思いますが、Japan Eastへのデプロイが必要な場合は「独自の関数の持ち込み」を利用する必要がありそうです。
マネージド関数を使ってAPIを実装する
マネージド関数を使ってAPIを実装します。以下のドキュメントにチュートリアルが書かれていますので、これを参考にして作っていきます。
module.exports = async function (context, req) { context.log('JavaScript HTTP trigger function processed a request.'); context.res = { headers: { "Content-Type": "application/json" }, body: [ {id: 1, title: "title1", body: "body1"}, {id: 2, title: "title2", body: "body2"}, {id: 3, title: "title3", body: "body3"}, ] } };
Reactアプリを作る
APIを呼び出すReactアプリを作ります。以下のサイトを参考に実装していきました。
CSSは私が慣れているReact Bootstrapを利用しました。
APIの呼び出し部分の実装は以下の通りです。APIは/api/post
としているので、このAPIをaxios
を使って呼び出します。
import React, {useEffect, useState} from 'react'; import Container from 'react-bootstrap/Container'; import Row from 'react-bootstrap/Row'; import Col from 'react-bootstrap/Col'; import BodyCard from './BodyCard'; import axios from 'axios'; function Content() { // Reactのステートフックを利用してstate変数であるpostを初期化し、 // 更新するsetPosts関数を取得する。 // ここでは、postを[]で初期化する const [post, setPosts] = useState([]) // useEffectを利用してJSONデータを取得してsetPostsでstate変数である // postを更新する useEffect(() => { axios.get('/api/post') .then(res => { setPosts(res.data) }) }, []) // 名前付き関数(アロー関数式を使った記述) const getCardContent = getObj => { return ( <Col key={getObj.id}> {/* スプレッド構文。getObjのすべての要素をBodyCardのproperty(props)に渡す */} <BodyCard {...getObj} /> </Col> ); }; return ( <Container> <Row xs={1} md={3} className="g-2"> {/* map() は与えられた関数を配列の全ての要素に対して呼び出し、 その結果からなる新しい配列を生成する */} {post.map(contentObj => getCardContent(contentObj))} </Row> </Container> ); } export default Content;
データ表示を行なっているBodyCard
は以下のような実装です。
import React from 'react'; import Card from 'react-bootstrap/Card'; function BodyCard(props) { // 分割代入。オブジェクト(props)の各プロパティに対応した // 変数に代入する。 // see. https://developer.mozilla.org/ja/docs/Web/JavaScript/Reference/Operators/Destructuring_assignment const { title, body } = props; return ( <Card> <Card.Body> <Card.Title>{title}</Card.Title> <Card.Text> {body} </Card.Text> </Card.Body> </Card> ); } export default BodyCard;
全体実装は、末尾に載せているGitHubのリポジトリを参照してください。
デプロイ
Azure Static Web AppsへのデプロイはGitHub ActionsかAzure DevOpsを利用する必要があります。前回はWebアプリだけをデプロイしましたが、そこからの差分はapi_location
を追加しただけです。以下のような実装になりました。
name: Azure Static Web Apps CI/CD on: push: branches: - main jobs: build_and_deploy_job: runs-on: ubuntu-latest name: Build and Deploy Job steps: - uses: actions/checkout@v2 - 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 }} repo_token: ${{ secrets.GITHUB_TOKEN }} action: "upload" app_location: "posts" api_location: "api" output_location: "build"
動作確認
デプロイした後にAzure Static Web AppsのURLにアクセスすると無事動いていることが確認できました。
Azure Portal上でAzure Static Web Appsの「設定」-「関数」をみると、今回デプロイした「post」が表示されていました。ただ、これは表示されているだけで、クリックしても何も動作しませんでした。