プロジェクトに設定されているStorybook v5.3をv6.0系にアップデートする


Storybookのバージョン6.0がリリースされたので現行で設定されているもの(v5.3)をv6.0向けに変更してみました。
変更した際の手順をまとめました。

# 前提
- vue-cliで作成したプロジェクト内に自動的に作成される、HelloWorld.vueを元にstory(サンドボックス環境)ファイルを作成します。
- HelloWorld.vueにはmsgと言うstring型のpropsを用意して、ヘッダーの文字列を親コンポーネントから設定出来る様にしています。(Vue.jsのイメージ画像も削除しました。)


# Storybook関係のパッケージのバージョン(変更前)
| 名前 | バージョン |
| :--- | :---: |
| @storybook/addon-a11y | 5.3.19 |
| @storybook/addon-actions | 5.3.19 |
| @storybook/addon-backgrounds | 5.3.19 |
| @storybook/addon-knobs | 5.3.19 |
| @storybook/addon-notes | 5.3.19 |
| @storybook/vue | 5.3.19 |


# Storybook関係のパッケージのバージョン(変更後)
| 名前 | バージョン |
| :--- | :---: |
| @storybook/addon-a11y | 6.0.16 |
| @storybook/addon-knobs | 6.0.16 |
| @storybook/addon-notes | 5.3.19 |
| @storybook/addon-essentials | 6.0.16 |
| @storybook/vue | 6.0.16 |


# 参考

[StorybookリポジトリのMIGRATION.md](https://github.com/storybookjs/storybook/blob/next/MIGRATION.md#from-version-53x-to-60x)


# Storybookのアップグレード

下記のコマンドでバージョンが更新されているパッケージの一覧が表示されるので「@storybook」の文言が入っているパッケージを全て選択します。

＊`addon-notes`はバージョンが5.3.19のままです。

```shell-session
$ yarn upgrade-interactive --latest
yarn upgrade-interactive v1.22.4
info Color legend : 
 "<red>"    : Major Update backward-incompatible updates 
 "<yellow>" : Minor Update backward-compatible features 
 "<green>"  : Patch Update backward-compatible bug fixes
? Choose which packages to update. 
```


アップグレード後、`yarn storybook`コマンドで下記のエラーが発生した場合は`style-loader`をインストールしてください。

```shell-session
Module not found: Error: Can't resolve 'style-loader' in
```

```shell-session
$ yarn add --dev style-loader
```

上記の内容で、とりあえずv5.3系の設定を変更せずそのまま使うことが出来ます。(StoriesOfAPIも使えます。)

一方でコマンド実行した際に、下記の様なメッセージが表示されます。
このワーニングを削除する為に設定ファイルを修正します。

```shell-session
node:5664) DeprecationWarning: Configuration files such as "config", "presets" and "addons" are deprecated and will be removed in Storybook 7.0.
Read more about it in the migration guide: https://github.com/storybookjs/storybook/blob/master/MIGRATION.md
```

# main.tsの作成

`.storybook`ディレクトリ内には、addons.jsやconfig.jsなどを作成していましたが、これらを削除して新規にmain.js(ts)を作成します。

main.jsの記載内容は下記の通りです。
config.jsに記載していたstoryファイルの格納場所や拡張子の設定を記載します。

また、addons.jsに記載していたaddon設定もmain.jsに記載します。

[Zero-config Storybook](https://medium.com/storybookjs/zero-config-storybook-66e7c4798e5d)に記載されている様に、下記のaddonは`addon-essentials`で一括で設定出来る様になりました。

- Docs
- Controls
- Actions
- Viewport
- Backgrouds
- Toolbars

```TypeScript
module.exports = {
  stories: ['../src/stories/**/*.story.@(ts|js)'],
  addons: ['@storybook/addon-essentials', '@storybook/addon-knobs/preset'],
};
```


# storyファイルの修正

続いて、storyファイルを修正します。

[前提](#前提)で記載したHelloWorld.story.js(ts)の内容は下記の様になっています。

```TypeScript
import { addDecorator, storiesOf } from '@storybook/vue'
import { withKnobs, text } from '@storybook/addon-knobs'
import HelloWorld from '../components/HelloWorld.vue'

addDecorator(withKnobs)

storiesOf('HelloWorld', module).add(
  'helloWorld',
  () => ({
    components: { HelloWorld },
    template: `
      <div>
        <HelloWorld
          :msg="msg"
        />
      </div>
    `,
    props: {
      msg: {
        type: String,
        default: text('msg', 'default text')
      }
    },
    data() {
      return {}
    },
    methods: {}
  }),
  {
    notes: `test note text.`
  }
)
```

後々使えなくなる予定の非推奨の設定もある為、HelloWorld.story.jsを下記の観点から修正をかけます。

1. addDecoratorの削除
2. withKnobsの設定の削除
3. (画面上の)notesタブの削除し、Docsタブ内にnotesの設定を表示させる。
4. storiesOfからCSF(Component Story Format)への書き換え
5. (画面上で)センタリングをかける。

修正した結果は次の様になりました。

```TypeScript
import { text } from '@storybook/addon-knobs'
import HelloWorld from '../components/HelloWorld.vue'
import markdown from './notes/sample.md'

export default {
  title: 'Test/HelloTest',
  parameters: {
    layout: 'centered',
    docs: {
      extractComponentDescription: (component, { notes }) => {
        if (notes) {
          return notes.markdown
        }
        return null
      }
    },
    notes: { markdown }
  }
}

export const HelloTest = () => ({
  components: { HelloWorld },
  template: `
    <div>
       <HelloWorld :msg="msg" />
    </div>
  `,
  props: {
    msg: {
      type: String,
      default: text('msg', 'default text')
    }
  },
  data() {
    return {}
  },
  methods: {}
})
```

### 1. addDecoratorの削除

main.jsにて、`@storybook/addon-knobs/preset`を設定していれば各storyファイル内で設定をする必要が無くなりました。
よって、非推奨となっている`addDecorator`は削除出来ます。

### 2. withKnobsの設定の削除
同上です。
text型のpropsを設定する為に`@storybook/addon-knobs` の設定はそのまま必要です。


### 3. (画面上の)notesタブの削除し、Docsタブ内にnotesの設定を表示させる。
notesに設定していたテキストはmarkdownファイルとしてimportする形式にしました。
直接記述すると、囲っているアポストロフィーにまでマークダウンが適用させる様になった為です。
export default内にて`parameters`としてdocsとnotesの設定を記述すると、画面上の`Docs`タブに表示される様になります。

### 4. storiesOfからCSF(Component Story Format)への書き換え

storiesOfで記載した内容を分割するイメージです。
export default内にてパラメーター等の設定をして、export constでtemplateやpropsの設定を記述します。


### 5. (画面上で)センタリングをかける。
従来は`@storybook/addon-centered`をインストールして設定していましたが、その必要は無くなりました。
`parameters`内に、「layout: 'centered'」と記述すればセンタリングされる様になりました。


上記を全て対応した上で`yarn storybook`コマンドを実行したらエラー無く画面を開くことが出来ました。


![スクリーンショット 2020-08-23 17.14.00.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/238861/dcb5aa70-58e3-fad3-6131-4a0521c8e53b.png)


これでいつも通りにStorybookを使えます。


ちなみに、v6.0に上げた後のaddon等のアップデートは下記の通りです。

```shell-session
$ npx sb@next upgrade 
```

他にもv6.0.0以降で出来る様になった機能があるので試して行きたいと思います。




# 補足: Vuetifyを使う場合
2020/08/30 追記

`Vuetify`を使う場合は、これまではconfig.jsに設定を記載していたと思います。
v6.0系からは`.storybook`ディレクトリに`preview.js(ts)`を作成して、下記の通りに記述する必要があります。


```TypeScript
import Vue from 'vue'
import Vuetify from 'vuetify'
import 'vuetify/dist/vuetify.css'
import colors from 'vuetify/es5/util/colors'

const vuetifyOptions = {}

Vue.use(Vuetify, {
  // customVariables: ['../src/assets/variables.scss'], // 必要な場合
  theme: {
    dark: false,
    themes: {
      dark: {
        primary: colors.blue.darken2,
        accent: colors.grey.darken3,
        secondary: colors.amber.darken3,
        info: colors.teal.lighten1,
        warning: colors.amber.base,
        error: colors.deepOrange.accent4,
        success: colors.green.accent3
      }
    }
  }
})

export const parameters = {
  backgrounds: {
    value: [
      { name: 'Sample BG 1', value: '#CCCCCC', default: true },
      { name: 'Sample BG 2', value: '#000000' },
    ],
  },
}

export const decorators = [
  () => {
    return (
    { vuetify: new Vuetify(vuetifyOptions), template: '<v-app><story/></v-app>' }
  )}
]
```