viteでreact(or preact)+typescript(+tailwindcss)な開発環境を構築

2021.08.01

吉川@広島です。

最近viteが非常に快適でハマって(良い意味の方)おり、ReactとPreactの環境構築を試してみたので備忘録がてら紹介します。

Getting Started | Vite

viteには

npm init vite@latest my-vue-app -- --template vue

のように自分で設定することなくscaffoldする機能があるのですが、今回はこれを使わずに構築する手順を共有したいと思います。

環境

  • node 15.11.0
  • yarn 1.22.10
  • npm 7.18.1
  • vite 2.4.4

プロジェクト作成

ディレクトリを作って入ります。

mkdir my-app
cd my-app

必要パッケージのインストール

  • react, react-dom (or preact)
  • vite (+ @vitejs/plugin-react-refresh or @prefresh/vite)
  • typescript
  • @tsconfig/recommended
  • @types/node

を入れていきます。viteプラグインとして、reactの場合は@vitejs/plugin-react-refresh、preactの場合は@prefresh/viteを入れます。@tsconfig/recommendedはtsconfigの設定を省力化するために採用します。@types/nodeはvite.config.tsのために入れています。

Reactの場合

yarn add react react-dom
yarn add -D vite @vitejs/plugin-react-refresh typescript @types/react @types/react-dom @tsconfig/recommended @types/node

Preactの場合

yarn add preact
yarn add -D vite @prefresh/vite typescript @tsconfig/recommended @types/node

configファイル作成

tsconfig.json

ts.config.jsonを作成します。

touch tsconfig.json

Reactの場合

@tsconfig/recommendedのおかげで随分楽に記述できました。

{
  "extends": "@tsconfig/recommended/tsconfig.json",
  "compilerOptions": {
    "jsx": "react",
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

pathsの設定は好みですが、個人的に import { MyComponent } from @/components/my-component のように絶対パスでimportできるようにしたいのでこのように設定しています。

Preactの場合

Reactの設定に "jsxFactory": "h" を加えます。

{
  "extends": "@tsconfig/recommended/tsconfig.json",
  "compilerOptions": {
    "jsx": "react",
+   "jsxFactory": "h",
    "baseUrl": "./",
    "paths": {
      "@/*": ["src/*"]
    }
  }
}

vite.config.ts

vite.config.tsを作成します。

touch vite.config.ts

Reactの場合

import { defineConfig } from 'vite'
import reactRefresh from '@vitejs/plugin-react-refresh'
import path from 'path'

export default defineConfig({
  root: './',
  plugins: [reactRefresh()],
  resolve: {
    alias: {
      '@/': path.join(__dirname, './src/'),
    },
  },
})

Preactの場合

  • @vitejs/plugin-react-refreshの代わりに@prefresh/viteを使う
  • jsxFactory: 'h' を定義する必要がある

がReactの場合との差分です。

jsxFactoryの対処を行わない場合、実行時に Uncaught ReferenceError: React is not defined のエラーが発生します。

import { defineConfig } from 'vite'
-import reactRefresh from '@vitejs/plugin-react-refresh'
+import preactRefresh from '@prefresh/vite'
import path from 'path'

export default defineConfig({
  root: './',
- plugins: [reactRefresh()],
+ plugins: [preactRefresh()],
+ esbuild: {
+   jsxFactory: 'h',
+ },
  resolve: {
    alias: {
      '@/': path.join(__dirname, './src/'),
    },
  },
})

entrypointとなるindex.htmlとtsxファイルを作成

index.html

touch index.html
<!DOCTYPE html>
<html lang="ja">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  </head>
  <body>
    <div id="root"></div>
    <script type="module" src="/src/index.tsx"></script>
  </body>
</html>

ここまで来たらあとはtsxを書くだけです。

index.tsx

mkdir src
touch src/index.tsx

Reactの場合

import React from 'react'
import ReactDOM from 'react-dom'

ReactDOM.render(<div>Hello World</div>, document.querySelector('#root'))

Preactの場合

import { h, render } from 'preact'

render(<div>Hello World</div>, document.querySelector('#root')!)

Preactの場合、renderの第2引数はnullableな値が許されないため ! が必要です(もしくは、ちゃんとnullチェック処理をする)。

ローカルサーバ起動

ローカルサーバを起動し、ブラウザで動作確認をします。

yarn vite

お疲れさまでした。

[Optional] tailwindcss

以下はさらにtailwindcssを導入したい場合の手順です。

上記を参考に進めました。

環境

  • tailwindcss 2.2.6
  • autoprefixer 10.3.1
  • postcss 8.3.6

必要パッケージをインストール

yarn add -D tailwindcss@latest postcss@latest autoprefixer@latest

tailwind.config.jsとpostcss.config.jsを作成

viteプロジェクト作成ではしませんでしたが、tailwindに関してはsccafoldさせて頂きます。

tailwindcss init -p

これで

  • tailwind.config.js
  • postcss.config.js

が生成されます。

tailwind.config.jsのpurgeを次のように書き換えます。

module.exports = {
- purge: [],
+ purge: ['./index.html', './src/**/*.{js,ts,jsx,tsx}'],
  darkMode: false, // or 'media' or 'class'
  theme: {
    extend: {},
  },
  variants: {
    extend: {},
  },
  plugins: [],
}

この設定をすることで実際に使われているCSSのみバンドルに含めることになり、バンドルサイズ削減に繋がります。

Tailwind CSS の Purge でビルドサイズを縮小する

試しに、手元のサンプルプロジェクトでpurgeの設定ありなしでCSSのバンドルサイズを比較してみました。

まず、purgeを提示したようにちゃんと指定した場合。

yarn vite build

...

dist/assets/index.3d16e845.css   4.16kb / brotli: 1.26kb

次に、 purge: [] のままビルドした場合。

yarn vite build

...

dist/assets/index.bf59349f.css   3166.01kb / brotli: skipped (large chunk)

絶対にpurgeは設定すべきということが分かりました。

index.cssを作成し、index.tsxで読み込む

次のようなindex.cssを作成します。

touch src/index.css
@import 'tailwindcss/base';
@import 'tailwindcss/components';
@import 'tailwindcss/utilities';

あとは、このindex.cssをindex.tsxでimportすれば導入完了です。

import React from 'react'
import ReactDOM from 'react-dom'
+import './index.css'

ReactDOM.render(<div>Hello World</div>, document.querySelector('#root'))

参考