はじめに
Svelte4も出てきたし、SvelteKit adapter for Azure Static Web Appsなるアダプターもあるし、SveltKitでSSRなWebアプリをAzure StaticWebApps で構築するための手順をまとめました。
嵌ったのは以下の点です。特に2点目は途方にくれました。(Special Thanks to Ota-san)
- APIフォルダを、SSR用のAPIと同居させる設定
- Azure StaticWebApps のAPIをPOSTコールしたら404になる問題
というわけで以下が、これから試される方、いずれ忘れるであろう私向けの手順です。
1. 環境準備
久々のSWA開発だったので、ここでもこの問題にはまりました。
Microsoft .NET SDKと、Azure Functions Core Toolsは最新を入れなおしておいたほうがいいかもです。
あとはNodejs, gitとか、そのあたりも入ってる前提です
2. SveletKitのプロジェクト作成
SvelteKitの公式手順をもとにプロジェクトを作成します。
npm create svelte@latest フォルダ名
cd フォルダ名
pnpm install
# 動作確認
npm run dev -- --open
これでSvelteの動作確認ができました。
3. Azure SWAのアダプターを設定する
このままだと、SSRができないので、SvelteKit adapter for Azure Static Web Appsの設定をいれていきます。また今回は自前のAPI(GET&POST)も追加したいので、その設定も必要です。
公式の手順をもとに実施します。
まずはadapterのインストールをします。
pnpm install -D svelte-adapter-azure-swa
これだけで動作確認するとモジュールが足りないと怒られるので(2023/7/6現在)、怒られたモジュールも追加します。
pnpm install -D set-cookie-parser
あとは設定を追加します。svelte.config.js
を以下のように書き換えます。
ポイントは以下です。
- 自前関数も用意したいので、apiDirに、'custom/api'フォルダを指定
- customStaticWebAppConfigに、apiへのルートを追加
※重要!この設定をいれないとSSR用のレンダーAPIにPOSTリクエストが吸収されてPOST呼び出しの時に、404が出ます!(PUTとかも必要あれば追加します)※
//importするアダプターを変更
import azure from 'svelte-adapter-azure-swa';
/** @type {import('@sveltejs/kit').Config} */
const config = {
kit: {
adapter: azure({
//大事な設定たちを追加
apiDir: 'custom/api',
customStaticWebAppConfig: {
routes: [
{
"route": '/api/*',
"methods": [
"GET",
"POST",
],
}
],
}
})
}
};
export default config;
あとは公式の通り、src/app.d.ts
の1行目に以下を追加します。
/// <reference types="svelte-adapter-azure-swa" />
ここで一回buildをかけます。
pnpm run build
そうするとcustom/apiフォルダにsk_renderなるものが追加されていると思います。このsk_renderのAPIがSSRの本体です。中はいじりません(いじれません)
なお、この時点だとFunction用の設定は入っていませんので、custom/apiフォルダの直下にhost.json
,local.settings.json
,package.json
を自分で追加します。
アダプターの公式サイトにはここがガイドされてますが、今日時点だと以下ですね。
{
"version": "2.0",
"extensionBundle": {
"id": "Microsoft.Azure.Functions.ExtensionBundle",
"version": "[3.*, 4.0.0)"
}
}
{
"IsEncrypted": false,
"Values": {
"FUNCTIONS_WORKER_RUNTIME": "node"
}
}
{}
先にfunc initしちゃってもいいですが。
4.自前の関数を追加する
custom/apiフォルダで、functionを追加します。
func new --template "Http Trigger" --name nankanomethod
custom/api/nankanomethod/index.jsをちょっとだけ変えてJSONを返すようにします(これは必須ではないです。JSONで受けたかったので変えただけです。ここ変えない場合は、後続のsvelteのテスト用のコードも変えてくださいね)
module.exports = async function (context, req) {
context.log('JavaScript HTTP trigger function processed a request.');
const name = (req.query.name || (req.body && req.body.name));
const responseMessage = name
? "Hello, " + name + ". This HTTP triggered function executed successfully."
: "This HTTP triggered function executed successfully. Pass a name in the query string or in the request body for a personalized response.";
context.res = {
status: 200, /* Defaults to 200 */
body: {message: responseMessage},
headers: {
'Content-Type': 'application/json'
}
};
}
デフォルトだとGET,POSTに対応したnankanomethodができますね。一旦これでOKです。
あと折角追加したので、svelte側からコールできるようにしておきます。
src/routes/+page.svelte
を編集します。以下、テキトーな例です。
<script>
/**
* @type {string}
*/
let message ="first status"
async function callGET(){
message ="calling GET"
const response = await fetch('/api/nankanomethod')
const data = await response.json()
message = data.message
}
async function callPOST(){
message ="calling POST"
const response = await fetch("/api/nankanomethod", {
method: "post",
headers: {
"Content-Type": "application/json"
},
body: JSON.stringify({name:"Taro Yamada"})
});
const data = await response.json();
message = data.message
}
</script>
<h1>Welcome to SvelteKit</h1>
<p>Visit <a href="https://kit.svelte.dev">kit.svelte.dev</a> to read the documentation</p>
<div>
{message}
</div>
<button on:click={callGET}>GET</button>
<button on:click={callPOST}>POST</button>
ここまででコードは完成です。
5. GitHubにコードをあげる
GitHubでリポジトリ―作ってから、initしてadd remoteして、addしてcommitしてpush します。
6. Azure StaticWebApps のリソースを作成する
AzureポータルでStaticWebAppsを作成します。以下の設定だけ注意してください。
property | value |
---|---|
アプリの場所 | ./ |
APIの場所 | custom/api |
出力先 | build/static |
あとは5.でつくったリポジトリ―を指定しておけばOKです。
7. 動作確認
GitHub Actionsが終わったら、Azure StaticWebAppsのサイトをみにいってきちんと動けば完成です。
お疲れ様でした。
番外
開発環境向けにローカルでfunctionを実行してテストする場合は、プロキシー設定が必要です。'vite.config.js'にproxyを足します。
import { sveltekit } from '@sveltejs/kit/vite';
import { defineConfig } from 'vite';
export default defineConfig({
plugins: [sveltekit()],
//server部分を追加
server: {
proxy: {
'/api': {
'target': 'http://127.0.0.1:7071',
changeOrigin: true,
},
}
},
});