svelteKit(TypeScript) & fastAPI(Python) & Dockerで開発環境構築　~svelteKit編~

今回はローカルのDocker環境でsvelteKitとfastAPIを使用し、
Webアプリをデプロイするまでの手順を投稿します。
この方法以外にもやり方は、いろいろあると思いますが、
検証済みの方法なので参考にして下さい。

今回はFE（フロントエンド）のsvelteKit編です。
## 前提
以下の項目に関しては、インストール済みorある程度の知識があるものとして進めます。
<ul>
    <li>node.js バージョン(22.2.0) - ローカルにインストール済み</li>
    <li>Docker Desktop - インストール済み</li>
</ul>

## 目標
今回、FE部分のみを作成し、BEとの連携部分いついては別記事で投稿することとします。
また、UIライブラリとして『Skelton』を使用してみようと思います。

<ol>
    <li>svelteKit(Typescript)でプロジェクトを作成</li>
    <li>UIライブラリ『Skeleton』の導入
    <li>Dokcer環境構築</li>
    <li>Docker(Nodeコンテナ)にデプロイ</li>
</ol>

それでは、環境構築スタート！
## 1. svelteKit(Typescript)でプロジェクトを作成
この辺の手順は、記事がたくさんあると思うので、簡単にいきたいと思います。
また、svelteは公式サイトの分かりやすさが、私の一番のお気に入りポイントです。
皆さんも迷ったら公式をまず見ることをお勧めします。

https://kit.svelte.jp/

### 公式と同じ手順を実行
```
npm create svelte@latest my-app
cd my-app
npm install
npm run dev
```
:::note info
コマンドを実行したディレクトリ直下に"my-app"というプロジェクトを作成します
:::
npm createを実行するとオプションを聞かれますが、基本的には"y"かEnterを押して、デフォルトで進めて問題ないです。
今回は、以下のように選択しました。
<ul>
    <li>template - skelton</li>
    <li>type checking - Yes</li>
    <li>additional options
</ul>

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/08ca15c5-62a7-09ee-413c-e0bab29180f0.png)

npm run devを実行して、以下のURLでプロジェクトが表示できていたら、成功です。
http://localhost:5173/
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/98d74ef9-7595-61a1-3ccb-5e984ab89c08.png)

## UIライブラリ『Skeleton』の導入
続いてSkeltonを導入していきます。
こちらも迷ったら、公式を参照して下さい。

https://www.skeleton.dev/

### skeletonパッケージと Skeleton Tailwind pluginのインストール
```
npm i -D @skeletonlabs/skeleton @skeletonlabs/tw-plugin
```
### TailWindのインストール
```
npx svelte-add@latest tailwindcss
npm install
```
:::note
TailWindとは？
CSSフレームワークで開発者がクラスを使って直接要素のスタイリングを行うことで、迅速かつ効率的にカスタマイズ可能なデザインを構築できます。
https://tailwindcss.com/
:::
tailwindcssをインストールすると、typography pluginを使用するかと聞かれます。
これもどっちでもいいのですが、私はYesにしました。
※Typography pluginは、リッチテキストコンテンツ（ブログ記事、Markdownなどのコンテンツ）のスタイリングを簡単にするためのユーティリティを提供してくれます。今回は特に触れません。

### 標準ノード型定義をインストール
```
npm add -D @types/node
```
### Tailwind configurationのセットアップ
tailwind.config.ts
```diff_typescript
+import { join } from 'path';
import type { Config } from 'tailwindcss';
+import { skeleton } from '@skeletonlabs/tw-plugin';

export default {
+	darkMode: 'class',
	content: [
		'./src/**/*.{html,js,svelte,ts}',
+		join(require.resolve(
+			'@skeletonlabs/skeleton'),
+			'../**/*.{html,js,svelte,ts}'
		)
	],
	theme: {
		extend: {}
	},

	plugins: [
		require('@tailwindcss/typography'),
+		skeleton
	]
} as Config;
```
### テーマを追加
先ほど編集したtailwind.config.tsをさらに編集します。
```diff_typescript
import { join } from 'path';
import type { Config } from 'tailwindcss';
import { skeleton } from '@skeletonlabs/tw-plugin';

export default {
	darkMode: 'class',
	content: [
		'./src/**/*.{html,js,svelte,ts}',
		join(require.resolve(
			'@skeletonlabs/skeleton'),
			'../**/*.{html,js,svelte,ts}'
		)
	],
	theme: {
		extend: {}
	},

	plugins: [
		require('@tailwindcss/typography'),
		skeleton({
+++			themes: { preset: [ "vintage" ] }
		})
	]
} as Config;
```
テーマは公式サイトにある一覧から"vintage" を選択しました。
理由はなんとなくです。後からいくらでも追加変更できます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/09f35fc8-c442-bd33-bce2-725ea39ee38c.png)

### app.htmlにテーマを追加
```diff_html
<!doctype html>
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" href="%sveltekit.assets%/favicon.png" />
		<meta name="viewport" content="width=device-width, initial-scale=1" />
		%sveltekit.head%
	</head>
+	<body data-sveltekit-preload-data="hover" data-theme="vintage">
		<div style="display: contents">%sveltekit.body%</div>
	</body>
</html>
```
### 動作確認
```
npm run dev
```
以下のようにテーマが反映されているのが確認出来たらOK！
　http://localhost:5174/
 ![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/e5133d40-e806-3e9b-1090-2b347d4e37c0.png)

### １つ簡単にできることをやってみました。
ダークモードの切り替えのボタンを実装してみます。
src/routes/+page.svelte でLightSwitchをインポートします。
```diff_svelte
<script>
	import '../app.css';
+	import { LightSwitch } from '@skeletonlabs/skeleton';
</script>
+<LightSwitch />
<slot></slot>
```
デフォルトはライトモードです。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/59d00ec9-484a-ce0d-71b9-22304db45b7c.png)
ボタンを押すと...
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/c8ffb167-f80d-c244-05ea-de673a6886ec.png)
ダークモードの切り替わりました！（...ニヤニヤ）
## Dokcer環境構築
いよいよデプロイへ向けたDokcer環境の構築手順です。
こちらの記事を参考に実施しましたのでこちらの記事にもいいねよろしくお願いします。

https://qiita.com/mkin/items/5b4fb2e61cf47fc5f904

まずは、nodeコンテナ上で動作するように、nodeアダプターをインストールします。
```
npm install @sveltejs/adapter-node -D
```
そして、adapterを変更します。
```diff_javascript
-import adapter from '@sveltejs/adapter-auto';
+import adapter from '@sveltejs/adapter-node';
```
:::note 
npm run devで正しく動作することを確認して下さい。
起動確認後、control + Cで停止しておきます。
:::

### Dockerfile作成
プロジェクトのルートにDockerfileを作成して以下のようにします。
```Dockerfile
# ビルド用
FROM node:22-slim as builder

WORKDIR /app

## パッケージをインストール
COPY package.json ./
COPY package-lock.json ./
COPY tsconfig.json ./
RUN npm ci

COPY . .

RUN npm run build

# 実行用
FROM node:22-slim

WORKDIR /app

## ビルド用のレイヤからコピーする
COPY --from=builder /app/build ./build
COPY --from=builder /app/package.json .
COPY --from=builder /app/node_modules ./node_modules

## Svelteが動く5173ポートを開けておく
EXPOSE 5173

CMD ["node", "./build"]
```
### docker-compose.yml作成
同じく、プロジェクトのルートにdocker-compose.ymlを作成します。
```docker-compose.yml
version: '3.8'

services:
  my-app:
    image: svelte-app
    build:
      context: .
      dockerfile: ./Dockerfile
    environment:
      - NODE_ENV=development
      - PORT=5173
    ports:
      - 5173:5173
    volumes:
      - ./src:/app/src
      - ./static:/app/static
      - ./vite.config.js:/app/vite.config.js
      - ./tsconfig.json:/app/tsconfig.json
      - ./svelte.config.js:/app/svelte.config.js
```
## Docker(Nodeコンテナ)にデプロイ
いよいよDockerコンテナで動かします！
```
docker-compose up --build
```
docker desktopで確認すると正常に動作していることがわかります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/ceefa8c4-7193-c9a5-f69b-04850249d00f.png)
実際にlocalhost:5173に接続してみます。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/19295a09-deaa-7ab4-0ea3-7377ddb45420.png)
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/3484672/b1178cfe-c8f7-78d4-9000-08dd0a10b0ae.png)
ダークモードへの切り替えも正常に行えているので良さそうですね！

## 終わりに
今回はとりあえず、Dockerで動作するところまで行うことができました。
次回はfastAPIをDockerで動作できるようにし、
今回作成した、svelteKitと連携できるようにしていこうと思います。
※よりわかりやすくこの記事は更新していけたらと思いますので、
よろしければ、いいねと保存おねがいします！:relaxed: