かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

Vite + React (TypeScript) のプロジェクトに ESLint と Prettier を導入する。

前回までのあらすじ

Vite で React (TypeScript) のプロジェクトを作ってパスエイリアスの設定をいい感じにしました
今回はいつもの ESLint と Prettier を導入します。(ホントいつもの…)
結論から言えば VIte だからという事は特になく、create-react-app で作成したプロジェクトと大差ありませんでした

ESLint

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

$ npm i -D eslint eslint-plugin-react-hooks

React のドキュメントに Hooks の呼び出し場所をコンポーネントとカスタムフック内に強制できる eslint-plugin-react-hooks について書かれていたので合わせて導入しました

ESLint の設定を作成

CLI で作成します

$ npx eslint --init
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · react
✔ Does your project use TypeScript? · Yes
✔ Where does your code run? · browser
✔ What format do you want your config file to be in? · JavaScript
The config that you've selected requires the following dependencies:

eslint-plugin-react@latest @typescript-eslint/eslint-plugin@latest @typescript-eslint/parser@latest
✔ Would you like to install them now with npm?   Yes
ESLint の module type を何にすべきか?
? What type of modules does your project use? (Use arrow keys)
❯ JavaScript modules (import/export)
  CommonJS (require/exports)
  None of these

ESLint でプロジェクトの使っている module タイプの指定があります。Vite で作成された tsconfig.jsontarget: "ESNext", "module": "ESNext" となっているので、JavaScript modules (ESM) か None of these か迷いました。

tsconfig の module と target
  • targetコンパイル時にどのバージョンの JavaScript で出力するか
  • module … 出力されるJavaScriptがどのようにモジュールを読み込むか

module
es2015, es2020, esnext 通称 esmodule と呼ばれるモジュール読み込みの解決方法です。フロントエンドで使われています。Node.jsは13.2.0でバックエンドでも同様にこのモジュール解決方法をサポートしましたが2020年現在は対応しているパッケージは少ないです。
cf. tsconfig.jsonを設定する | TypeScript入門『サバイバルTypeScript』

tsconfig の module の ESNextesmodule の方法だとあったので ESLInt の What type of modules does your project use? の質問は JavaScript modules (import/export) を選択しました。
少し自信がないので、間違っていたら指摘いただきたいです :pray:

eslint-plugin-react-hooks の設定を追加

.eslintrc.js

module.exports = {
  "plugins": [
    // ...
+   "react-hooks"
  ],
  "rules": {
    // ...
+   "react-hooks/rules-of-hooks": "error", // Checks rules of Hooks
+   "react-hooks/exhaustive-deps": "warn" // Checks effect dependencies
  }
}

import react from 'React' がない場合もエラーにならないルールを追加

React 17 から不要になっているが、ESLint がエラーになってしまうので

.eslintrc.js

module.exports = {
  // ...
  rules: {
    // ...
+   'react/react-in-jsx-scope': 'off',
  }
}

後はお好みでルールを追加すれば OK

Prettier

こちらも特に Vite だからという違いはなさそうです

$ npm i -D prettier eslint-config-prettier
# 設定ファイルの作成
$ touch .prettierrc.json

フォーマットの設定

.prettierrc.json

{
  "trailingComma": "all",
  "tabWidth": 2,
  "printWidth": 80,
  "singleQuote": true,
  "jsxSingleQuote": true,
  "arrowParens": "always",
  "bracketSpacing": true,
  "jsxBracketSameLine": false,
  "semi": true,
  "endOfLine": "lf"
}

※ お好みで

ESLint と連携

.eslintrc.js

{
  "extends": [
    //...
+   "prettier"
  ]
}

ESLint と Prettier 用の npm scripts を作成

package.json

{
  // ...
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build",
    "preview": "vite preview",
+   "lint": "eslint --ext .js,.jsx,.ts,.tsx src/",
+   "lint:fix": "npm run lint -- --fix",
+   "format": "npm run lint:fix && prettier --write 'src/**/*.{js,jsx,ts,tsx}'"
  },

使ってない import を自動で削除する

eslint-plugin-unused-imports

$ npm i -D eslint-plugin-unused-imports

.eslintrc.js

{
  "plugins": [
    "react",
    "@typescript-eslint",
+   "unused-imports"
  ],
  "rules": {
+   "@typescript-eslint/no-unused-vars": "off", // or "no-unused-vars": "off",
+   "unused-imports/no-unused-imports": "error",
+   "unused-imports/no-unused-vars": [
+     "warn",
+     { "vars": "all", "varsIgnorePattern": "^_", "args": "after-used", "argsIgnorePattern": "^_" }
+   ]
  }
}

import の順番を自動でいい感じにする

eslint-plugin-import

$ npm i -D eslint-plugin-import

.eslintrc.js

{
  "plugins": [
    "react",
    "@typescript-eslint",
    "unused-imports",
+   "import"
  ],
  "rules": {
    // … 
    // import の順番の設定
+   "import/order": []
  }
}

順番の指定方法は eslint-plugin-import の Wikiを参考に下記のようにしてみました。

{
  rules: {
    'import/order': [
      'error',
      {
        // グループの順番
        groups: [
          'builtin',
          'external',
          'internal',
          ['parent', 'sibling'],
          'object',
          'type',
          'index',
        ],
        // グループ感に空行追加しない
        'newlines-between': 'never',
        pathGroupsExcludedImportTypes: ['builtin'],
        // ABC 順。大文字小文字を区別しない
        alphabetize: { order: 'asc', caseInsensitive: true },
        pathGroups: [
          // react 関連を先頭に
          {
            pattern: 'react**',
            group: 'external',
            position: 'before',
          },
          {
            pattern: '{@/libs/**,@/features/**,@/app/**}',
            group: 'internal',
            position: 'before',
          },
          {
            pattern: '{@/components/**,@/pages/**}',
            group: 'internal',
            position: 'before',
          },
          // css modules は一番最後にする
          {
            pattern: './**.module.css',
            group: 'index',
            position: 'after',
          },
        ],
      },
    ]
  }
}

所感

ESLInt, Prettier 共に Vite だからという違いは特にありませんでした。
新しくプロジェクト作る度にこの辺り調べてやり直してる気がする…

今回はやっている中で npm install の際に --save-exact オプションを使うと ^10.0.0 のような 10.0.0 以上ではなく 10.0.0 とインスールするバージョンが完全に固定できるということを知りることができました! 毎回やってるけど何かしら発見あるからよし!(永遠の初心者)

おわり ₍ ᐢ. ̫ .ᐢ ₎


[参考]

O'Reillyの読んだらブルーベリー本買うんだ…

もうネタがプロジェクトキレイキレイしか思いつかねぇ…

Vite + React で path alias を使いたい!

前回までのあらすじ

npm create vite コマンドでサクッと Vite + React (TypeScript) のプロジェクトが作れました!
SPA はファイルがたくさんになるので import の際に ../../../ HELL になりがちです。これを回避するためにパスエイリアス(path alias)を設定しておきたいお気持ちに溢れます。

結論: vite-tsconfig-paths を使えば楽ちん

vite-tsconfig-pathsを使えば tsconfig.json にパスエイリアス設定を作成するだけで済む。

$ npm i -D vite-tsconfig-paths

vite.config.ts

import { defineConfig } from 'vite'
+ import tsconfigPaths from 'vite-tsconfig-paths'

export default defineConfig({
+ plugins: [tsconfigPaths()],
})

これで tsconfig.json に設定したパスエイリアスの設定が効くようになる


下記経緯

Vite の path alias の設定方法

cf. resolve.alias

  • vite.config.tsresolve.alias の項目を作成してパスエイリアスの設定を作成する
    • resolve.alias: Record<string, string> | Array<{ find: string | RegExp, replacement: string, customResolver?: ResolverFunction | ResolverObject }>
  • 設定は内部的に使われている @rollup/plugin-alias の書き方を参照する
  • TypeScript なプロジェクトの場合は tsconfig.json にも同様の設定をする必要がある

e.g. @/src/~/public/ にアクセスできるようにする

1. vite.config.tsresolve.alias を作成

vite.config.ts

+ import path from 'path';
import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';

export default defineConfig({
+ resolve: {
+   alias: {
+     '@/': `${__dirname}/src/`,
+     '~/': `${__dirname}/public/`
+   },
+ },
  plugins: [react()],
});

[{ find: 'エイリアス', replacement: '変換するパス' }] で書くなら下記のような感じ

export default defineConfig({
+ resolve: {
+   alias: [
+     { find: '@/', replacement: `${__dirname}/src/` },
+     { find: '~/', replacement: `${__dirname}/public/`},
+   ],
+ },
  plugins: [react()],
});
resolve.alias は変換するパスが / で終わってないと正しくエイリアスとして動作しない。
  • 🙅 NG `${__dirname}/src`, path.join(__dirname, 'src')
  • 🙆 OK `${__dirname}/src/`, path.join(__dirname, 'src/')

最後が / で終わってないと次のようなエラーになる
Failed to resolve import "@/App.module.css" from "src/App.tsx". Does the file exist?
パス末の / が原因だと分からなくて時間とかした… (ᐡ •̥ ̫ •̥ ᐡ)

cf. <2022/02更新>vite+TypeScriptでalias pathを~に設定する

2. __dirname が TS のエラー Cannot find name '__dirname'.ts(2304) になるので修正する

node の型が入ってないのが原因。Vite で作ったプロジェクトにはデフォルトでは含まれてないっぽい。

$ npm i -D @types/node

tsconfig.json

{
  "compilerOptions": {
+   "types": ["node"],
    // …

cf. node.js - TSC cannot find name of Global Object - Stack Overflow

3. tsconfig.json にパスエイリアスの設定を追加

tsconfig.json

{
  "compilerOptions": {
    // …
+   "baseUrl": "./",
+   "paths": {
+     "@/*": ["src/*"],
+     "~/*": ["public/*"]
+   },
    // …

これで tsx 内の import を @/~/ に変更して npm run dev をして問題なく動作していれば OK ₍ ᐢ. ̫ .ᐢ ₎👌

🌟 vite-tsconfig-paths を使う方法 (個人的オススメ!)

vite-tsconfig-pathsを使えば vite.config.ts に alias の設定を書く必要がなくなりパスエイリアスの設定を tsconfig.json に一元化できる! (@types/node のインストールも不要になる)

インストール

$ npm i -D vite-tsconfig-paths

vite.config.ts

import react from '@vitejs/plugin-react';
import { defineConfig } from 'vite';
+ import tsconfigPaths from 'vite-tsconfig-paths';

// https://vitejs.dev/config/
export default defineConfig({
  server: {
    open: true,
  },
- plugins: [react()],
+ plugins: [react(), tsconfigPaths()],
});

tsconfig.json

{
  "compilerOptions": {
    // ...
+   "baseUrl": "./",
+   "paths": {
+     "@/*": ["src/*"],
+     "~/*": ["public/*"]
+   },
    // …

₍ᐢ •̥ ̫ •̥ ᐢ₎‪ できた!!!!
TSのエラーと戦う必要もなく、パスエイリアスの設定も一元管理できるので vite-tsconfig-paths プラグイン使ってしまうのが良さそうです。


VSCode でパスエイリアスの補完が効くようにする

いつもの。cf. GitHub - KiKiKi-KiKi/ts-react-app: React with TypeScript app template
path-autocomplete.pathMappings に補完させたいパスエイリアスを設定できる。

$ mkdir .vscode
$ touch .vscode/settings.json

今回は @//src 配下のファイルを、~//public 配下のファイルを補完させたいので下記のように設定を追加すればOK

.vscode/settings.json

{
  "path-autocomplete.pathMappings": {
    "@": "${folder}/src",
    "~": "${folder}/public"
  }
}

VSCode@/, ~/ と打った時にパスの保管がサジェストされるようになっていればOK

cf.

所感

随分大きなエントリーになってしまったけど、プラグインを使えば簡単に path alias が設定できました !! チョロいから Vite 好きになってきちゃったな… ぽわぽわ…
おわり ₍ ᐢ. ̫ .ᐢ ₎


[参考]

[asin:B07X3HFJ9Q:detail]

全然関係ないけど、SPY×FAMILY めちゃ好〜!! 原作の表紙がミッドセンチュリーなチェアで統一されてるのもとても良… 原作買うか!? (本棚の空き場所無いぞ…)

今更の Vite で React + TypeScript のプロジェクト作ってみた

ちょっぱやだと噂の Vite で React のプロジェクトを作ってみた素振りのメモ

Vite とゎ?

昨今の巨大な JavaScript のプロジェクトはモジュールバンドルのパフォーマンスがボトルネックになってきていた。
従来のものは更新頻度の少ないファイルも全てバンドルして提供していた。
開発サーバーでは10倍から100倍高速である esbuild を用いて依存関係を事前にバンドルし、 native ESM を利用することで頻繁に更新されるファイルを Dynamic import するようにして高速化させている。
Production ではコード分割やCSSの処理が成熟している Rollup を使ってビルドを行う。ESM はまだブラウザのサポートが弱く、バンドルされてない ESM は非効率なためビルドを行う設計にしている。将来的に esbuild の機能が安定してきたら Rollup から esbuild を用いたビルドに変更する可能性がある。

Why Vite をざっくりまとめるとこんな感じでしょうか (解釈間違いあれば教えて下さい)
パフォーマンスの良いバンドラーとブラウザの ESM の仕組みを利用して従来のものより効率的かつ高速に動作するようにしたよ!って印象です。

Vite で React のプロジェクトを作成する

$ npm create vite@latest <project name>
# package json に記載されるパッケージ名
? Package name: ›
# react を選択
? Select a framework: › - Use arrow-keys. Return to submit.
    vanilla
    vue
❯   react
    preact
    lit
    svelte
# TypeScript を使う場合は react-ts を選択
? Select a variant: › - Use arrow-keys. Return to submit.
    react
❯   react-ts

Scaffolding project in /Users/kikiki/<project name>

Done. Now run:

  npm install
  npm run dev

Scaffolding project Done. のメッセージが表示され新規ディレクトリが作成されていればOK

/project name
  |- .gitignore
  |- index.html … エントリーポイント
  |- /src … react のソースコード
  |- tsconfig.json
  |- tsconfig.node.json
  |- vite.config.ts … vite の設定ファイル
note.

調べた blog に載っていた npm init vite でも同じ手順でプロジェクトが作成できました。 ドキュメントに見当たらなかったので旧バージョンのコマンドなのかもしれませんが、深くは調べていません。

プロジェクトディレクトリを作成せず、現在の場所に展開したい場合

<project name> を指定せず . にすれば OK
<project name> が空の時は Package name と同じ名称のディレクトリが作成される

$ npm create vite@lastest .
# ディレクトリ内にファイルが存在する場合は既存のファイルを削除しても構わないか聴かれる
# .git など vite が作成しないファイルやディレクトリも消されてしまうっぽので注意が必要
? Current directory is not empty. Remove existing files and continue? › (y/N)

React project の起動

メッセージにあったようにプロジェクトディレクトリに移動して、npm install して npm run dev すればOK

$ npm install
$ npm run dev
 vite v2.9.9 dev server running at:

  > Local: http://localhost:3000/
  > Network: use `--host` to expose

  ready in 1954ms.

localhost:3000/ にアクセスして React のロゴがクルクル回る初期画面が表示されていればOK
npx create react-app と異なり自動でブラウザでアプリを開いてくれないので自分で localhost:3000/ にアクセスする必要がある
dev モードでは HMR (Hot Module Replacement) = コードが変更されると自動的に再描画する 仕組みが入っているので、このまますぐに開発ができそうです!

その他のコマンド
  • プロジェクトのビルド … npm run build
  • ビルドした状態のプレビュー … npm run preview

vite は dev の時は esbuild でビルド時は Rollup なのでビルド時のプレヴューができるようになってるっぽいです

起動時に自動でブラウザを開くようにする

create-react-app と同じように実行時に自動的にブラウザが開くようにする
vite.config.ts に下記オプションを追加すればOK

vite.config.ts

export default defineConfig({
+  server: {
+    open: true,
+  },
  plugins: [react(), tsconfigPaths()],
});

既に localhost がブラウザで開いている場合は別のタブが開くのではなく既に開いているタブが再起動するので無駄にタブが増えず良きです

cf. Configuring Vite | Vite

static なファイルの置き場所

vite では JS ファイルで import した画像などは自動的にハッシュ化されたパスに変換してくれるようです
JS でバンドルするまでもない static な CSS や画像は /public というフォルダを作成しそこに配置すればOK
⚠ デフォルトでは public フォルダがが存在しないので作成する必要がある
/public ディレクトリ内に置かれたファイルは JS から / でアクセスが可能になります

/project name
  |- index.html
  |- /public
  |    |- /images
  |        |- sample.jpg 
  |- /src

/src/App.tsx

function App() {
  return (
    {/* /public/images/sample.jpg は /images/sample.jpg でアクセスできる */}
    <img src="/images/sample.jpg" alt="" />
  )
}

cf. Configuring Vite | Vite

所管

CLI が用意されているので、簡単に React + vite なプロジェクトを作成することができました!
体感として webpack な create-react-app より npm run dev した際の起動時間が超速って感じです。追って ESLint + Prettier などの設定もしてみたいと思います。
おわり ₍ ᐢ. ̫ .ᐢ ₎


続き


[参考]

これは Vita 。