Vue3 + Typescript + bootstrap5をdocker-composeで始める [環境セットアップ編]

## 手順

- Dockerfile/docker-compose.yamlを用意
- vue cliでプロジェクトの雛形を作成
- bootstrap5のインストールと適用

## ディレクトリ構成

```
- project_root
  - docker-compose.yaml
  - Dockerfile
  - frontend <- Vueプロジェクト
    - node_modules
    - public
    - src
    - etc...
```

## Dockerfile/docker-compose.yamlを用意

### vue用コンテナのDockerfileを作成
- nodeは投稿時点でLTSの14を使用し、vue cliをインストール

```Dockerfile:Dockerfile
FROM node:14

WORKDIR /frontend

RUN apt update -y && \
    apt upgrade -y && \
    npm install -g @vue/cli @vue/cli-service-global
```

### docker-compose.yamlを作成

```yaml:docker-compose.yaml
version: '3'
services:
  frontend:
    build: .
    ports:
      - 8080:8080
    volumes:
      - ./frontend:/frontend
    command: npm run serve
```

## vue cliでプロジェクトの雛形を作成

### コンテナに接続

```
$ docker-compose build
$ docker-compose run frontend bash
```

### vue cliでプロジェクトの雛形を作成

- ローカルのfrontend直下にプロジェクトを作成したいのでディレクトリを1階層上にしています

```
$ cd ../
$ vue create frontend
```

- すでにディレクトリがある場合は上書きするかマージするか選択します。
- マージを選択します。

```
? Target directory /frontend already exists. Pick an action: (Use arrow keys)
  Overwrite 
❯ Merge 
  Cancel 
```

- オプションを選択していく

```
Vue CLI v4.5.13
? Please pick a preset:
  Default ([Vue 2] babel, eslint)
  Default (Vue 3) ([Vue 3] babel, eslint) 
❯ Manually select features
```

- `Manually select features`を選択


```
? Check the features needed for your project: 
 ◉ Choose Vue version
 ◉ Babel
 ◉ TypeScript
 ◯ Progressive Web App (PWA) Support
 ◉ Router
 ◉ Vuex
❯◉ CSS Pre-processors
 ◉ Linter / Formatter
 ◯ Unit Testing
 ◯ E2E Testing
```

- `Typescript`, `Router`, `Vuex`, `CSS Pre-processors`にチェックをつける

```
 ? Choose a version of Vue.js that you want to start the project with (Use arrow keys)     
  2.x
❯ 3.x
```

- Vueのバージョンは`3.x`を選択

```
? Use class-style component syntax? (y/N) N  
```

- 生成されるvueファイル(Home.vueなど)をclass-styleかobject-styleどちらにするかという問
- object-styleはdefineComponentを使ったVue3のスタンダード的な書き方なので、こちらでは`N`を選択
- `Y`を選択した場合でも自分でobject-styleに書き直すことは出来ます

```
? Use Babel alongside TypeScript (required for modern mode, auto-detected polyfills, transpiling JSX)? (Y/n) Y
```

- babel.config.jsを自動生成するか否か。
- 今回は生成して欲しいので`Y`を選択

```
Use history mode for router? (Requires proper server setup for index fallback in production) (Y/n) Y
```

- vue routerをhistory modeで使用するかの確認
- vue routerにはhistory modeとhash modeの2つがあるのですが、それらの違いについては下記の記事が参考になります。
- https://qiita.com/kozzzz/items/af9ad63fa70d4724cc2a
- 今回はhistory modeを使用するので`Y`を選択します

```
? Pick a CSS pre-processor (PostCSS, Autoprefixer and CSS Modules are supported by default):
❯ Sass/SCSS (with dart-sass)
  Sass/SCSS (with node-sass)
  Less
  Stylus
```

- CSS pre-processorに何を使用するかの確認
- Sass/SCSSの場合はdartが推奨されているのでそちらを選択します。
- 参考: https://sass-lang.com/blog/libsass-is-deprecated

```
? Pick a linter / formatter config:
  ESLint with error prevention only
  ESLint + Airbnb config
  ESLint + Standard config
❯ ESLint + Prettier
  TSLint (deprecated)
```

- linter/formatterの選択
- 今回は`ESLint + Prettier`を使用します
- linter/formatterについては下記の記事が参考になりました。
- https://reffect.co.jp/vue/eslint

```
? Pick additional lint features: (Press <space> to select, <a> to toggle all, <i> to invert selection)
❯◉ Lint on save
 ◯ Lint and fix on commit
```

- ESLintの実行タイミングを選択します
- 保存時に実行する`Lint on save`を選択します。
- 選択肢はどちらも選択することが出来ます

```
? Where do you prefer placing config for Babel, ESLint, etc.? (Use arrow keys)
❯ In dedicated config files
  In package.json
```

- babelやeslint等の設定をどのファイルに持つかという問
- 専用のファイル、package.jsonかどちらかを選択します
- 今回は`In dedicated config files`を選択

```
? Save this as a preset for future projects? (y/N) N
```

- 上記の設定内容をプリセットとして保存するかの問です。
- 今回は不要なので`N`を選択します

```
? Pick the package manager to use when installing dependencies: (Use arrow keys)
  Use Yarn
❯ Use NPM
```

- パッケージマネージャーにどちらも使用するかの問
- 今回はnpmを選択します
- この問を選択するとvueプロジェクトが作成されます。

### vue.config.jsの作成

- このままだとホットリロードが効かないので`/frontend/vue.config.js`を作成して設定します

```js:vue.config.js
module.exports = {
    configureWebpack: {
      devServer: {
        watchOptions: {
          poll: true
        }
      }
    }
  }
```

## bootstrap5のインストールと適用

### bootstrap5のインストール

- bootstrap-iconsが不要であれば削除してください

```shell:
$ cd frontend
$ npm install bootstrap@next @popperjs/core bootstrap-icons
```

### 適用

- frontend/src/main.tsでbootstrapをimport
- bootstrap-iconsが不要であれば削除してください

```js:main.ts
import { createApp } from "vue";
import App from "./App.vue";
import router from "./router";
import store from "./store";
import 'bootstrap'
import 'bootstrap/dist/css/bootstrap.css';
import 'bootstrap-icons/font/bootstrap-icons.css'
```

### 動作確認

- Home.vue等を修正してbootstrap5とbootstrap-iconsが導入されているか確認用のコードを追記します


```html:Home.vue
<template>
  <div class="home">
    <!-- Bootstrap 確認用 -->
    <button type="button" class="btn btn-primary">Primary</button>
    <!-- Bootstrap-icons 確認用 -->
    <i class="bi bi-file-bar-graph"></i>
    <img alt="Vue logo" src="../assets/logo.png" />
    <HelloWorld msg="Welcome to Your Vue.js + TypeScript App" />
  </div>
</template>

<script lang="ts">
import { defineComponent } from "vue";
import HelloWorld from "@/components/HelloWorld.vue"; // @ is an alias to /src

export default defineComponent({
  name: "Home",
  components: {
    HelloWorld,
  },
});
</script>
```

## 起動

- コンテナから抜けて、起動します

```
$ exit
$ docker-comopose up -d
```

- `localhost:8080`をブラウザで叩き無事表示出来たら終了です