SolidJS + TypeScript + Vite 環境作ってみた

# はじめに
最近`svelte`にドはまりしていましたが、
`SolidJS`も触ってみたいな～と思い、話題の`Vite`で環境を作った時のメモです。

## 実行環境

* docker 
    * 20.10.14
* docker-compose
    * 1.29.2

## docker-compose.yml

imageには`node`、commandには`vite`の実行コマンドにしておきました。

```yaml
version: '3'

services:
  app:
    image: node:18-alpine3.15
    working_dir: /app
    ports:
      - "8080:8080"
    volumes:
      - "./src:/app"
    tty: true
    command: npm run dev
```

## いざ環境構築

### コンテナ内へ～

```bash
$ docker-compose build
$ docker-compose run app sh
```

以降コンテナ内操作です

### SolidJS・TypeScript・Vite・Viteプラグインをインストールする

```
# npm
/app # npm install solid-js
/app # npm install -D typescript vite vite-plugin-solid
```

### package.jsonの修正

`tsc`を実行できるように

```json
{
  "scripts": {      // 追加
    "tsc": "tsc",   // 追加
  },                // 追加
  "dependencies": {
    "solid-js": "^1.6.4"
  },
  "devDependencies": {
    "typescript": "^4.9.4",
    "vite": "^4.0.0",
    "vite-plugin-solid": "^2.5.0"
  }
}

```

### TypeScriptの初期設定

```
/app # npm run tsc -- --init
```

tsconfig.jsonが作られたはずなので、↓をコピペ

```json
{
  "compilerOptions": {
    "baseUrl": ".",
    "target": "es5",
    "module": "ESNext",
    "lib": ["ESNext", "DOM", "DOM.Iterable"],
    "esModuleInterop": true,
    "isolatedModules": true,
    "jsx": "preserve",
    "jsxImportSource": "solid-js",
    "moduleResolution": "node",
    "newLine": "lf",
    "noEmit": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true,
    "resolveJsonModule": true,
    "types": ["vite/client"],
    "skipLibCheck": true,
    "strict": true
  },
  "include": ["**/*.ts", "**/*.tsx"],
  "exclude": ["node_modules"]
}
```

`jsx`、`jsxImportSource`以外の個所は自分好みに調整してください

### Vite初期設定

プロジェクトルートに`vite.config.ts`を作成

```
/app # touch vite.config.ts
```

以下をコピペ

```typescript
import { defineConfig } from 'vite'
import solidPlugin from 'vite-plugin-solid'

export default defineConfig({
  plugins: [solidPlugin()],
  server: {
    host: true,
    port: 8080
  }
})
```

※ `port`を変えたいときは`docker-compose.yml`のportも一緒に変えてね！

### index.htmlの作成

こちらもプロジェクトルートに`index.html`を作成

```
/app # touch index.html
```

そして以下をコピペ

```html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1" />
    <meta name="theme-color" content="#000000" />
    <link rel="shortcut icon" type="image/ico" href="/src/assets/favicon.ico" />
    <title>Solid App</title>
  </head>
  <body>
    <noscript>You need to enable JavaScript to run this app.</noscript>
    <div id="root"></div>

    <script src="/src/main.tsx" type="module"></script>
  </body>
</html>
```

### src/main.tsxを作成

```
/app # mkdir src
/app # touch src/main/tsx
```

そして以下をコピペ

```tsx
// main.tsx

import { createSignal } from 'solid-js'
import { render } from 'solid-js/web'

const CountingComponent = () => {
  const createDate = (date: Date) => {
    const Year = date.getFullYear();
    const Month = date.getMonth()+1;
    const Date = date.getDate();
    const Hour = date.getHours();
    const Min = date.getMinutes();
    const Sec = date.getSeconds();

    return `${Year}年${Month}月${Date}日 ${Hour}:${Min}:${Sec}`
  }

  const [time, setCount] = createSignal(createDate(new Date()))
  setInterval(() => setCount(() => {
    return createDate(new Date())
  }), 1000)

  return (
    <div>Time is {time()}</div>
  )
}

render(() => <CountingComponent />, document.getElementById('root'))
```

### サーバー起動！

```
/app # npm run dev
```

[localhost:8080](http://localhost:8080)で開けたら成功

![time.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/2985550/6890b879-2946-314a-a38a-646d6c6ca024.gif)