Vue / Reactで使えるフロントエンド開発ツール３選

普段開発しているフロントエンドの開発環境でサクッと入れられて少しでも便利になるものがないか調べてみました。
雑誌や他の方の記事などを読み漁り取り急ぎ試しに入れてみたものをいくつかご紹介します。

# [Storybook addons](https://storybook.js.org/addons/)
普段Storybookを使っていてあまりちゃんと便利アドオンを調べたりしてこなかったので良さそうなものを厳選して使ってみました。

## [@storybook/addon-viewport](https://storybook.js.org/docs/react/essentials/viewport)
このaddonは[essentials](https://storybook.js.org/addons/tag/essentials/)に含まれてるので基本的にはStorybookが入っていれば標準で使える機能ですが下記の設定を追加するとデバイスの種類が増えてより使い勝手の良いものになります。

```javascript
// .storybook/preview.js
import { INITIAL_VIEWPORTS } from '@storybook/addon-viewport';

export const parameters = {
  viewport: {
    viewports: INITIAL_VIEWPORTS,
  },
};
```
（このコードは[公式ドキュメント](https://storybook.js.org/docs/react/essentials/viewport)から引用）


このアイコンをクリックすると
![Screen Shot 2022-09-13 at 21.19.57.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47977/f8cee8b7-512b-117a-7d91-bf804a99e10d.png)

デバイスの種類を選択できて
![Screen Shot 2022-09-13 at 21.20.47.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47977/99ed514c-21e7-4fc7-1d24-17b90bc521fb.png)

viewportが変更されて表示が切り替わります
![Screen Shot 2022-09-13 at 21.21.39.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47977/c8ed4f67-c9b0-6c0c-0732-1a53aed78eb3.png)

これを入れるまではブラウザのインスペクターでいちいち切り替えてましたがクリック一回で切り替えられるので便利でした。

## [@storybook/addon-a11y](https://storybook.js.org/addons/@storybook/addon-a11y/)
W3Cが推奨しているアクセシビリティに関するガイドライン([WCAG2](https://www.w3.org/WAI/standards-guidelines/wcag/))に沿ってコンポーネントをチェックできるaddonです。
※WCAG2に関する情報は公式サイトをご確認ください。

```shell
$ yarn add @storybook/addon-a11y -D
```

```javascript
// .storybook/main.js
module.exports = {
  addons: [
    "@storybook/addon-links",
    "@storybook/addon-essentials",
    "@storybook/addon-interactions",
    "@storybook/addon-a11y", // 追加
  ],
```

Storybook下部にAccessibilityタブが表示される
![Screen Shot 2022-09-13 at 21.22.43.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47977/3dfb96ac-eb7c-f8e1-9ea6-1476ab63c278.png)

アクセシビリティに違反している項目があると内容が表示される
![Screen Shot 2022-09-13 at 21.23.36.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47977/d0e2f2ec-b5e0-5d19-dc67-7080d256aa14.png)

全てクリアしている場合はPassesのみ内容が表示される
![Screen Shot 2022-09-13 at 21.24.16.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/47977/aebfa536-3de4-f856-8ecc-818c51851fc8.png)

コンポーネント実装の段階でアクセシビリティのチェックがされて指摘については議論したり修正できるので便利でした。

# [scaffdog](https://github.com/scaffdog/scaffdog)
scaffdogは簡単に言うと[rails generate](https://railsguides.jp/command_line.html#bin-rails-generate)をフロントエンド環境でも使いたい場合に便利なscaffoldingツールです。

例えばReactでコンポーネントを作っていく際にこのような構成だと
```shell
components/
└ Example/
 ├ __tests__/
 │ └ index.test.tsx
 ├ index.tsx
 └ index.stories.tsx
```
１つのコンポーネントを実装する度に３つのファイル作っていかないといけないですよね。
- `Example/__tests__/index.test.tsx`
- `Example/index.tsx`
- `Example/index.stories.ts`

少量のコンポーネントを実装するぐらいなら地道にコピペしても良さそうですが開発初期などで作らないといけないコンポーネントが多い場合、この作業も鬱陶しく感じてしまうかもしれません。
そんな時にscaffdogが導入されていると効率よくコンポーネントを作れます。

__インストール__
```shell
$ yarn add -D scaffdog
```

__初期設定__
```shell
$ yarn scaffdog init
```
`init`すると作成するドキュメントの名称を求められるので入力します。
今回はcomponent作成のための設定になるので`component`と入力します。

```shell
? Please enter a document name. component
                                                                                                                                                                                                                    
Setup of scaffdog 🐶 is complete!                                                                                                                                                                                   

  ✔ .scaffdog/config.js
  ✔ .scaffdog/component.md

Now you can do scaffold by running `$ scaffdog generate`.

Please refer to the following documents and customize it.
https://scaff.dog/docs/templates
                                                                                                                                                                                                                    
✨  Done in 13.12s.
```

`init`が完了するとテンプレートのmarkdownファイルと設定のjavascriptファイルが生成されます。
~~~markdown
<!-- .scaffdog/component.md  --> 

---
name: 'component'
root: '.'
output: '**/*'
ignore: []
questions:
  value: 'Please enter any text.'
---

# `{{ inputs.value }}.md`

```markdown
Let's make a document!
See scaffdog documentation for details.
https://scaff.dog/docs/templates
```
~~~
```javascript
// .scaffdog/config.js 
export default {
  files: ['./*'],
};
```
この`.scaffdog/component.md`を修正してコンポーネント実装に必要なファイル群を作成できるようにしてみようと思います。
`.scaffdog/component.md`を下記のように修正して
~~~markdown
---
name: "component"
root: "src/components"
output: "*"
ignore: []
questions:
  component: "Please enter a component name."
---

# `{{ inputs.component }}/index.tsx`

```typescript
const {{ inputs.component }} = () => {
  return <div>Example Text</div>
}
export default {{ inputs.component }}
```

# `{{ inputs.component }}/index.stories.tsx`

```typescript
import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'
import {{ inputs.component }} from '.'
export default {
  title: '{{ inputs.component }}',
  component: {{ inputs.component }},
} as ComponentMeta<typeof {{ inputs.component }}>
export const {{ inputs.component }}Story: ComponentStory<typeof {{ inputs.component }}> = () => {
  return <{{ inputs.component }} />
}
```

# `{{ inputs.component }}/__tests__/index.test.tsx`

```typescript
import { render } from '@testing-library/react'
import {{ inputs.component }} from '..'
describe('{{ inputs.component }}', () => {
  it('renders {{ inputs.component }} unchanged', () => {
    const { getByText } = render(<{{ inputs.component }} />)
    expect(getByText("Example Text")).toBeTruthy();
  })
})
```

```markdown
Let's make a document!
See scaffdog documentation for details.
https://scaff.dog/docs/templates
```
~~~

generateコマンドで作成していきます。

```shell
$ yarn scaffdog generate
```

ドキュメントを選択します。
先ほど作成した`component`のドキュメントを選択します。
```shell
? Please select a document. (Use arrow keys)
❯ component 
```

次に作成するコンポーネントの名称を入力します。
```
ℹ Output destination directory: "src/components"                                                                                                                                                                    
? Please enter a component name. 
```

`Example`と入力してみます。

```
? Please enter a component name. Example
                                                                                                                                                                                                                    
🐶 Generated 3 files!                                                                                                                                                                                               
                                                                                                                                                                                                                    
     ✔ src/components/Example/index.tsx                                                                                                                                                                             
     ✔ src/components/Example/index.stories.tsx                                                                                                                                                                     
     ✔ src/components/Example/__tests__/index.test.tsx                                                                                                                                                              
                                                                                                                                                                                                                    
✨  Done in 232.90s.

```

すると無事に３つのファイルが作成されました。
実際に作成されたファイルを見てみると

```tsx
// src/components/Example/index.tsx
const Example = () => {
  return <div>Example Text</div>
}
export default Example
```

```tsx
// src/components/Example/index.stories.tsx
import React from 'react'
import { ComponentStory, ComponentMeta } from '@storybook/react'
import Example from '.'
export default {
  title: 'Example',
  component: Example,
} as ComponentMeta<typeof Example>
export const ExampleStory: ComponentStory<typeof Example> = () => {
  return <Example />
```

```tsx
// src/components/Example/__tests__/index.test.tsx
import { render } from '@testing-library/react'
import Example from '..'
describe('Example', () => {
  it('renders Example unchanged', () => {
    const { getByText } = render(<Example />)
    expect(getByText("Example Text")).toBeTruthy();
  })
})
```
入力したコンポーネント名が埋め込まれています。
markdownのテンプレートファイルをブラッシュアップして最初からlintやspecが通るようにしておくとさらに効率よくコンポーネント実装できました。


今後も定期的に開発環境を見直してより効率の良いフロントエンド開発環境の構築を目指していきたいと思います！