Viteでvanilla-tsアプリを作成する

今回は今話題のViteを使って、vanilla-jsならぬvanilla-tsアプリを作成していきます。
※vanilla-js = 生JavaScript、vanilla-ts = 生TypeScript

# そもそもViteとは？
読み方はヴァイトと呼ばれることが多いですが、正しくは「ヴィート」（フランス語の「素早い」という意味の単語が由来）と読みます。
Vue.jsの開発者Evan You氏が開発したJavaScript/TypeScript（以下JS/TS）ビルドツールです。そのため元々はVue.js用に作られていたみたいですが、現在は他のフレームワークにも対応しています（詳しくは後述）。

先日発表された「[The State of JavaScript 2021](https://2021.stateofjs.com/en-US/)」のライブラリ満足度では97%となり、かなり評判の良いフレームワークであることがわかります（ちなみにViteは第2位のesbuildを使用して動作します）。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919803/84c8a58d-b0d1-1a74-d43a-5f9e817d7aac.png)
（引用：[The State of JavaScript 2021 - Libraries](https://2021.stateofjs.com/en-US/libraries)より）

# Viteの評判はなぜこんなに良いのか？

とにかくアプリケーションサイズがどんなに巨大になっても、超高速でビルドされることに尽きます。

これまでVue.jsでいう[Vue CLI](https://cli.vuejs.org/)を使った開発がそうだったように、アプリケーションのビルドではwebpackなどを使用したバンドルの手法が採られてきました。ただし、バンドルの開発はその仕様上アプリケーションサイズが大きくなければなるほどビルドが遅くなってしまうという問題を抱えていました。Viteではこのバンドル手法を採らないことでその問題を解消したというわけです。ただし、今回の記事では詳しい仕組みは説明しません。興味のある方は以下の公式ガイドを覗いてみてください。

https://ja.vitejs.dev/guide/why.html

https://ja.vitejs.dev/guide/comparisons.html

公式ページから一つ引用しておきます。
> 超高速な Vite を一度体験してしまうと、バンドルでの開発にまた耐えられるかはとても疑わしいです。

# Viteでvanilla-tsアプリを作ろう

Viteの特徴を簡単に紹介したので、本題。

## そもそもなんでvanilla-tsアプリにしたの？

Viteは[ここ](https://ja.vitejs.dev/guide/#vite-%E3%82%92%E3%82%AA%E3%83%B3%E3%83%A9%E3%82%A4%E3%83%B3%E3%81%A7%E8%A9%A6%E3%81%99)に載っているフレームワークに対応しており、ネットではVue.js時々Reactアプリを作ろう記事が多数ヒットします。そんな中でvanilla-tsを選んだ理由は以下の通りです。

- 手軽にTSを使ってvanilla-jsならぬvanilla-tsアプリを作成出来ること
- Vue.js/Reactなどのフレームワークを普段使わない人にも、手軽にTSを使ったアプリを作れることを強調したい
- vanilla-jsアプリだと色々設定するまでrequire文しか使えませんが、Viteを使えば簡単にimport文（↓のような文）がそのまま使えることを強調したい
  ```ts
  import { hoge } from 'hoge-library'
  ```

## 完成したアプリ

リポジトリ兼アプリURL
https://stackblitz.com/edit/vitejs-vite-e1xcjr?file=package.json&terminal=dev

## Viteアプリの初期生成

まず[ここのページ](https://ja.vitejs.dev/guide/#%E6%9C%80%E5%88%9D%E3%81%AE-vite-%E3%83%97%E3%83%AD%E3%82%B8%E3%82%A7%E3%82%AF%E3%83%88%E3%82%92%E7%94%9F%E6%88%90%E3%81%99%E3%82%8B)に従い、vanilla-ts用テンプレートを使ってViteアプリを生成します。npm/yarnコマンドを使うかでコマンド内容が変わってくるので注意が必要です。

コマンドを叩くと、vite-vanilla-tsフォルダにViteアプリが生成されます。

```bash
# npm 6.xを使う場合　
npm create vite@latest vite-vanilla-ts --template vanilla-ts

# npm 7+を使う場合（※ハイフン２つが入る）
npm create vite@latest vite-vanilla-ts -- --template vanilla-ts

# yarnを使う場合
$ yarn create vite vite-vanilla-ts --template vanilla-ts
```

そしてターミナルの案内に従い、以下コマンドを叩くとViteアプリが立ち上がります。

```bash
$ yarn # yarn install / npm installでも同じ
$ yarn dev # npm run devでも同じ
```

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919803/29044c31-6155-d536-6996-b1b8073b333d.png)

## アプリを作っていく

今回はベタですが、TODOアプリを作っていきます。
動作のロジック面はアプリURLの方を見ていただくとして、少し配慮が必要だった箇所の説明をします。

初期生成されたコードだと`id="app"`の`div`要素にすべての`html`要素を生成される前提になっていますが、React/Vue.jsなどのフレームワークを使っていないため、このままではTODOアプリを作るのは大変です。ですので、まずは以下の形に変更をかけました。

```diff_html:index.html
<body>
-     <div id="app"></div>
+     <div class="container">
+      <h1>Viteで作ったTODOアプリ</h1>
+      <ul id="taskList"></ul>
+      <form id="addTaskForm">
+        <input
+          type="text"
+          name="addTaskInput"
+          id="addTaskInput"
+          placeholder="ここにタスクを入力してください"
+          value=""
+        />
+        <button id="addTaskButton">+</button>
+      </form>
+    </div>
    ...
</body>
```

```diff_typescript:src/main.ts
- const app = document.querySelector<HTMLDivElement>('#app')!
- app.innerHTML = `
-   <h1>Hello Vite!</h1>
-   <a href="https://vitejs.dev/guide/features.html" target="_blank">Documentation</a>
- `

+ const addTaskForm = document.querySelector<HTMLFormElement>('#addTaskForm')!
+ const addTaskInput = document.querySelector<HTMLInputElement>('#addTaskInput')!
+ const taskList = document.querySelector<HTMLUListElement>('#taskList')!

+ addTaskForm.addEventListener('submit', (e) => {
+   e.preventDefault()
+   addTask(addTaskInput.value)
+   addTaskInput.value = ""
+ });
+ ...
```

また、tsファイルに他言語を使っている人には馴染みがないであろう謎の!（ビックリマーク）がありますが、これは以下の流れで記載しています。

1. TSにはDOM要素が`undefined`かは分からないので、「`undefined`かもよ」とエラーが出る
2. 開発者からすれば、対象DOM要素が間違いなくあることを知っている
3. ということでDOM要素が必ずある保証代わりにビックリマークをつけて、必ずHTML要素を返却するように変更

```ts
const addTaskForm = document.querySelector<HTMLFormElement>('#addTaskForm')!
const addTaskInput = document.querySelector<HTMLInputElement>('#addTaskInput')!
...
```

公式ドキュメントの説明はこちらです。

https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-0.html#non-null-assertion-operator

## 完成したアプリを見る

そんな感じでTODOアプリが完成しました！

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/919803/fdb067b0-07c9-c818-6ead-b1f4308b769e.png)

出来ること・出来ないことは以下のとおりです。

- 出来ること
  - タスクの追加
  - タスクに完了フラグをつける
  - タスクの削除
- 出来ないこと
  - タスク内容の修正
  - localStorageへタスク内容を保管する
    - →なのでページをリロードするとタスク一覧が吹き飛びます

今回はViteを使ってサンプルアプリを作る記事なので、この程度としました。

# まとめ
今回はViteでvanilla-tsアプリを作成してみました。フレームワークを使って開発をするのも良いですが、Viteを活用して手軽に生のJavaScript/TypeScriptの理解を深めてみるのもどうでしょうか？