Azure Static Web Apps とは、静的サイトのホスティングとAzure Functions(AzureのFaaS)が組み合わさったサービスです。
コードはGitHubレポジトリに置き、GitHub Actionsを使ってビルドとデプロイを行います。
2021年3月現在にはプレビュー段階にあり、無料で試すことができます。(正式版リリース後もAzure Functionsと同様に無料枠内で利用できるかも?)
詳細は以下を確認してください。
この記事では、Azure Static Web Appsを使ってフロント・サーバーともにTypeScriptなNuxt.js+NestJSのサイトを公開する方法を紹介します。
せっかちな人向け
以下のGitHubレポジトリに最小限の構成のテンプレートを公開していますので、そこから編集していってください。
kniwase/static-web-apps-sample
前提条件
- Azure Functionsを利用できるAzureのサブスクリプションを持っていること
- もしなければここで作成できます
- TypeScript, NPM, Nuxt.js, NestJSの初歩的な知識があること
使うもの
環境構築
Azure FunctionsでNode.js用の開発をしたことがある方は、おそらく全てセットアップ済みかと思いますので、この項目は読み飛ばしてください。
Node.js LTS
もしなければ、公式サイト にある方法に従ってLTS(v14)をインストールしてください。
nest-cli
NestJSのプロジェクト作成や起動、パッケージ管理に使用します。
もしなければ、GitHubレポジトリの説明に従ってインストールしてください。
(たぶん npm install -g @nestjs/cli
で入ります)
VS Code
もしインストールされていなければ、公式サイトにある方法に従ってインストールしてください。
Azure Functions拡張機能
もしインストールされていなければ、拡張機能の検索バーで Azure Functions
を検索し、一番それっぽいやつをインストールしてください。
もしくはこちらから拡張機能へのリンクを開いてください。
Azure Functions Core Tools
もしインストールされていなければ、GitHubレポジトリにある方法に従ってインストールしてください。
プロジェクト骨格の構築
以下のGitHubレポジトリで公開しているサンプルと同じものを構築していきます。
kniwase/static-web-apps-sample
"setup-project"というブランチに上記サンプルを作成する過程のコミットがありますので、そちらもご参照ください。
Commits on "setup-project"
おおまかな構成
Nuxt.js のプロジェクトを先に作成し、その中に api というプロジェクト名で NestJS のプロジェクトを作成します。
パッケージはそれぞれで管理します。
Nuxt.jsプロジェクトの作成
static-web-apps-sample
という名前でNuxt.jsのプロジェクトを作成します。
npm init nuxt-app static-web-apps-sample
✨ Generating Nuxt.js project in static-web-apps-sample
? Project name: static-web-apps-sample
? Programming language: TypeScript
? Package manager: Npm
? UI framework: 今回は使用しない
? Nuxt.js modules: Axios - Promise based HTTP client
? Linting tools: 今回は何も使用しない
? Testing framework: 今回は使用しない
? Rendering mode: Universal (SSR / SSG)
? Deployment target: Static (Static/Jamstack hosting)
? Development tools: 今回は何も使用しない
? What is your GitHub username? Gitのユーザー名
? Version control system: Git
nuxt-property-decorator の導入
TypeScriptでの開発をしやすくするために nuxt-property-decorator を導入します。
npm i nuxt-property-decorator
API側コードの除外
ビルド時にAPI側のコードを無視するように設定ます。
tsconfig.json
の "exclude"
に "api"
を追加します。
"exclude": [
"node_modules",
".nuxt",
"dist",
"api"
]
ローカル起動時のAPIへのプロキシ設定
ローカルで起動した際に本番と同じパスでAPIにアクセスできるようにプロキシを設定ます。
まず proxy-module を導入します。
npm i @nuxtjs/proxy
続いてプロキシの設定を追加します。
# '@nuxtjs/proxy' を追加
modules: [
'@nuxtjs/axios',
'@nuxtjs/proxy'
],
# proxy を追加
proxy: {
'/api': { target: 'http://localhost:7071' }
},
デプロイ用の設定
Azure Static Web Apps で設定される Github Actions でのビルドでは npm run build
が実行されます。
しかしこのままでは Nuxt.js の静的サイト生成は行われないため、 npm run build
で実行されるコマンドを静的サイト生成のものに変更する必要があります。
また、先ほど設定したローカル用プロキシを無効化する必要があるため、 package.json
内の "build"
を "cross-env API_URL=/ nuxt generate"
に書き換えます。
cross-env API_URL=/
は axios が本番環境で相対パスを参照するように設定し、
nuxt generate
はビルド時にSSGとして動作するように設定します。
"scripts": {
"dev": "nuxt",
"build": "cross-env API_URL=/ nuxt generate",
"start": "nuxt start",
"generate": "nuxt generate"
}
cross-env が必要なので併せて導入します。
npm i --save-dev cross-env
NestJSプロジェクトの作成
先ほど作成したNuxt.jsのプロジェクトの中に api
という名前でNestJSのプロジェクトを作成します。
Gitのフォルダーが作成されますが、こちらのものは削除します。
cd static-web-apps-sample
nest new api -p npm
rm -rf api/.git
Azure Functions用に設定
Azure Functions対応には nestjs/azure-func-http を使用します。
以下のコマンドでAzure用のファイルがいくつか追加されます。
cd static-web-apps-sample/api
nest add @nestjs/azure-func-http
ここでVSCodeを一旦閉じて、再度 static-web-apps-sample
を開いてください。
そうすると、
Detected an Azure Functions Project in folder "static-web-apps-sample" that may have been created outside of VS Code. Initialize for optimal use with VS Code?
と右下に表示されるので、Yesを選択します。
これで .vscode の中に Azure Functions 用の設定が作成され、F5キーでデバッグを起動するなどの機能が使用できるようになります。
テスト用コードの追加
ここまでで基本的な骨格の作成は完了です。
続いてAPIにアクセスしてメッセージを取得、表示するだけの簡単なコードを追加していきます。
この工程はスキップしたり別のよりちゃんとしたコードを用意しても構いません。
NestJS
api/src/app.service.ts
と api/src/app.controller.ts
を以下のように書き換えます。
import { Injectable } from '@nestjs/common';
@Injectable()
export class AppService {
getHello(): object {
return { text: 'Hello World!' };
}
}
import { Controller, Get } from '@nestjs/common';
import { AppService } from './app.service';
@Controller()
export class AppController {
constructor(private readonly appService: AppService) { }
@Get("hello")
getHello(): object {
return this.appService.getHello();
}
}
F5キーでAzure Functionsのデバックを起動してから http://localhost:7071/api/hello にアクセスし、以下のJSONが取得できれば成功です。
{"message":"Hello World!"}
Nuxt.js
components
に HelloFromApi.vue
を追加し、下記の内容にします。
<template>
<div>
Message From Api: <strong>{{ message }}</strong>
</div>
</template>
<script lang="ts">
import { Component, Vue } from "nuxt-property-decorator";
import axios from "axios";
@Component
export default class HelloFromApi extends Vue {
message: string = "";
async mounted() {
this.message = await this.getMessage();
}
async getMessage(): Promise<string> {
try {
const res = await axios.get("/api/hello");
const message: string = res.data.text;
console.log(message);
return message;
} catch (error) {
console.error(error);
return "";
}
}
}
</script>
pages/index.vue
を編集し、下記の内容にします。
<template>
<div>
<HelloFromApi />
</div>
</template>
ローカルで動作検証
ローカルで起動し、動作検証を行います。
Nuxt.js の起動
通常通りのコマンドで起動します。
npm run dev
NestJS の起動
F5キーを押し、Azure Functionsの拡張機能で起動します。
確認
http://localhost:3000/ にアクセスし、Message From Api: Hello World! と表示されれば成功です。
GitHub にコードを上げる
ここまで編集してきたコードをまとめてコミットします。
git checkout -b main
git add --all
git commit -m "init project"
続いて Github で static-web-apps-sample という名前でレポジトリを作成します。
プライベートリポジトリで問題ありません。
作成したリモートレポジトリにローカルレポジトリの内容をプッシュします。
git remote add origin git@github.com:[ユーザー名]/static-web-apps-sample.git
git push -u origin main
Azure Static Web Apps の設定
Azure Portal で静的 Web アプリを開き、追加をクリックします。
設定画面が出てきますので、下記のように設定ます。
プロジェクトの詳細
- サブスクリプション
- 従量課金
- リソーグループ
- 任意のものを選ぶ、なければデフォルト設定で新規作成する
静的 Web アプリの詳細
- 名前
- static-web-apps-sample
- 地域
- East Asia
デプロイの詳細
(先ほどレポジトリを作成したGitHub アカウントでサインイン)
- 組織
- 先ほどレポジトリを作成したユーザーまたは組織
- レポジトリ
- static-web-apps-sample
- 分岐(ブランチのこと)
- main
ビルドの詳細
- ビルドのプリセット
- Vue.js
- アプリの場所
- /
- APIの場所
- api
- 出力先
- dist
設定が完了したら、確認および作成、続けて作成をクリック。
動作確認
新規作成されたリソースに移動後、GitHub アクションの実行 をクリックし、GitHub Actionsの実行ログを確認します。
ビルドとデプロイが完了したら、自動生成された URL にアクセスします。
ローカル実行時と同じページが見えることが確認出来たら完了です。