nxのreact projectで利用するstorybookのbuilderを@storybook/builder-viteに変更する

## 背景

[nrwl blog](https://blog.nrwl.io/speed-up-storybook-with-vite-and-swc-with-the-help-of-nx-b1e4c488e0fd)からstorybookのbuilderをwebpack5からviteに変更ができるという記事がでたので、導入したらいろいろバグったのでその記録

### 環境

| package(or language) | version |
|:---|:---|
| node | v16.13.2 |
| @nrwl/cli | v14.4.3 |
| react | 18.2.0 |
| @emotion/react | v11.19.3 | 
| vite | v3.0.2 |
| @storybook/builder-vite | v0.2.0 |

```
バグではないですが、vite-buidler, webpack5 builderにて、別のlibaryを読み込んだ時に tsconfigのaliasが解決されないケースが発生している。(solutionは別口で提供されている)
[nrwl/nx/issues/2320](https://github.com/nrwl/nx/issues/2320)
[storybookjs/builder-vite/issues/85](https://github.com/storybookjs/builder-vite/issues/85)
```

## TL;DR

`@stroybook/builder-vite`を入れたあとに、webpack builder周りをpackageから削除を実施して、builder fileをviteのみにする。
`vite-builder`を有意義にするため、`preview.tsx`を作成して`story bookのdecorators`まわりでtheme-providerを有効化する。

## Table of Contents

```
0. nx, storybook周りまでの環境作成
1. vite, @storybook/builder-viteを入れる
2. Story Bookのbuilderを変更する
3. PreView周りを整える
```

## 0. 環境準備

### 0-a. nx reactの環境を作成する

対話式で丸っと環境が作成されるため、react@v18.2.0とemotion@11.9.3周りの環境を丸っと作成します。

```terminal
% npx create-nx-workspace@latest
Ok to proceed? (y) y
✔ Workspace name (e.g., org name)     · myorg
✔ What to create in the new workspace · react
✔ Application name                    · todos
✔ Default stylesheet format           · @emotion/styled
✔ Set up distributed caching using Nx Cloud (It's free and doesn't require registration.) · No
```

一応起動確認

```
% yarn nx serve todos
```

[http://localhost:4200/](http://localhost:4200/)で書きのように確認ができます。

![localhost3000.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/4df03350-5d98-387f-d2fd-e8e7c79d4d8b.png)


次にstorybookの環境を有効化します。

```terminal
% yarn add --dev @nrwl/storybook
% yarn nx g @nrwl/react:storybook-configuration todos
✔ Configure a cypress e2e app to run against the storybook instance? (Y/n) · true
✔ Automatically generate *.stories.ts files for components declared in this project? (Y/n) · true
✔ Automatically generate *.spec.ts files in the Cypress E2E app generated by the cypress-configure generator? (Y/n) · false
adding .storybook folder to the root directory
The root Storybook configuration is in JavaScript, 
        so Nx will generate JavaScript Storybook configuration files 
        in this project's .storybook folder as well.
adding .storybook folder to your application
```

`todosapp`のstorybookが有効かされるので、一応起動できるのかの確認を実施。

```terminal
% yarn nx storybook todos
╭────────────────────────────────────────────────╮
│                                                │
│   Storybook 6.5.9 for React started            │
│   15 s for manager and 20 s for preview        │
│                                                │
│    Local:            http://localhost:4400/    │
│    On your network:  http://localhost:4400/    │
│                                                │
╰────────────────────────────────────────────────╯
```

[http://localhost:4400/](http://localhost:4400/)で確認が取れれば起動終了です。

![storybook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/9910f15e-4a6f-3b13-0224-cd0ebb1b8bc9.png)

##  1. vite, @storybook/builder-viteを入れる

下準備が完了したので、viteと@storybook/builder-viteを有効化していきます。

```
% yarn add -D vite @storybook/builder-vite
```

webpack5 buildeをvite builderへの書き換えを実施していきます。

```apps/todos/.storybook/main.js
const rootMain = require('../../../.storybook/main');

module.exports = {
  ...rootMain,
  core: { ...rootMain.core, builder: ‘@storybook/builder-vite’ }, # builderの設定をbuilder-viteに変更
  stories: [
    ...rootMain.stories,
    '../src/app/**/*.stories.mdx',
    '../src/app/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
  webpackFinal: async (config, { configType }) => {
    // apply any global webpack configs that might have been specified in .storybook/main.js
    if (rootMain.webpackFinal) {
      config = await rootMain.webpackFinal(config, { configType });
    }
    // add your own webpack tweaks if needed
    return config;
  },
};
```

書き換えが完了したら起動の確認を実施します。

```terminal
% yarn nx storybook todos
╭────────────────────────────────────────────────╮
│                                                │
│   Storybook 6.5.9 for React started            │
│   19 s for manager and 11 s for preview        │
│                                                │
│    Local:            http://localhost:4400/    │
│    On your network:  http://localhost:4400/    │
│                                                │
╰────────────────────────────────────────────────╯
```

[http://localhost:4400/](http://localhost:4400/)で確認が取れれば起動終了です。

![storybook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/9910f15e-4a6f-3b13-0224-cd0ebb1b8bc9.png)


## 2. Story Bookのbuilderを変更する

1で対応したところがミニマムで次に不要になったファイルなどを整理していきます。

```terminal
% yarn remove @storybook/manager-webpack5
% yarn remove @storybook/builder-webpack5
```

```(旧)apps/todos/.storybook/main.js
const rootMain = require('../../../.storybook/main');

module.exports = {
  ...rootMain,
  core: { ...rootMain.core, builder: '@storybook/builder-vite' },
  stories: [
    ...rootMain.stories,
    '../src/app/**/*.stories.mdx',
    '../src/app/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
  // ここから webpack builderの整理なるため、したまで消す
  webpackFinal: async (config, { configType }) => {
    // apply any global webpack configs that might have been specified in .storybook/main.js
    if (rootMain.webpackFinal) {
      config = await rootMain.webpackFinal(config, { configType });
    }
    // add your own webpack tweaks if needed
    return config;
  },
  // [END] webpack builder setting
};
```
settingをしたに書き換えます。

```apps/todos/.storybook/main.js
const rootMain = require('../../../.storybook/main');
const { mergeConfig } = require('vite');

module.exports = {
  ...rootMain,
  core: { ...rootMain.core, builder: '@storybook/builder-vite' },
  stories: [
    ...rootMain.stories,
    '../src/app/**/*.stories.mdx',
    '../src/app/**/*.stories.@(js|jsx|ts|tsx)',
  ],
  addons: [...rootMain.addons, '@nrwl/react/plugins/storybook'],
  async viteFinal(config, { configType }) {
    // return the customized config
    return mergeConfig(config, {
      // customize the Vite config here
      resolve: {
        alias: { foo: 'bar' },
      },
    });
  },
};

```

```
% yarn nx storybook todos
╭────────────────────────────────────────────────╮
│                                                │
│   Storybook 6.5.9 for React started            │
│   17 s for manager and 10 s for preview        │
│                                                │
│    Local:            http://localhost:4400/    │
│    On your network:  http://localhost:4400/    │
│                                                │
╰────────────────────────────────────────────────╯
```

[http://localhost:4400/](http://localhost:4400/)で確認が取れれば起動終了です。

![storybook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/9910f15e-4a6f-3b13-0224-cd0ebb1b8bc9.png)

webpack周りや設定をちゃんといじらないと`.storybook/preview.js`を修正した際に、builder周りの読みこみが失敗してしまうため、記事にはないですが書き換えを実施しました。


## 3. PreView周りを整える

vite-builderを利用した恩恵として、`.storybook/preview.js`をそのまま`.storybook/preview.tsx`でDecoratorsにそのままThemeを突っ込みに行けます。

```.storybook/preview.tsx
import type { FC } from 'react';

export const decorators = [
  (Story: FC) => (
    <div style={{ margin: '3em' }}>
      Hello
      <Story />
    </div>
  ),
];

```

```.storybook/tsconfig.json
{
  "extends": "../tsconfig.json",
  "compilerOptions": {
    "emitDecoratorMetadata": true,
    "outDir": ""
  },
  "files": [
    ...
  ],

  "exclude": [
    ...
  ],
  "include": [
    ...,
    "preview.tsx"
  ]
}

```

雑に記載したのですが、以下のように`Hello`が下のように表示されます。

![App-Primary-⋅-Storybook.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/144543/50f9bfd8-a4e0-5952-e760-63d872ebf639.png)