GitHub Actionsを使ってGithub PagesにStorybookのドキュメントをWebpack5を使って公開したメモ

## 概要
[前回](https://qiita.com/hibohiboo/items/a1568d9ecaf9ebb25e11)はOpenAPIを公開したので、今回はStoryBookを公開してみる。
Next.jsをWebpack5で使用しているため、StoryBookも同様にWebpack5で利用したかった。
いろいろハマったので備忘録。

できたもの。

https://hibohiboo.github.io/kotatool/publish/component-catalog/?path=/story/welcome--to-storybook



[ソース](https://github.com/hibohiboo/kotatool/tree/dd75a8ba2d9a66e443ee7d65697712c698d1df56)


## ハマリ１ StoryBookでWebpack5が使えない。

2021/03/03時点でbetaの6.2.0から対応の模様。


<details><summary>npmインストールについて</summary>
<div>
nodeをDocker上で利用している。Dockerfileは以下のような感じ。

```Dockerfile:Dockerfile
FROM node:14.16.0

WORKDIR /app/internals/component-catalog
RUN npm install -g npm@7.6.0

COPY package.json /app/internals/component-catalog/package.json
COPY package-lock.json /app/internals/component-catalog/package-lock.json
RUN npm ci

# Story Book
RUN npm i -D @storybook/cli@next
RUN npx --force sb init --type react --builder webpack5
RUN npm i --no-optional -D babel-preset-react-app
RUN npm i --no-optional -D @storybook/addon-knobs@next
RUN npm i --no-optional -D @storybook/addon-storysource@next
RUN npm i --no-optional -D @storybook/addon-viewport@next
RUN npm i --no-optional -D @storybook/addon-backgrounds@next
RUN npm i --no-optional -D @storybook/builder-webpack5@next
RUN npm i --no-optional -D @storybook/addon-console

# storybookのwebpackでローダーを使えるようにする
RUN npm i --no-optional -D css-loader style-loader
RUN npm i --no-optional -D precss autoprefixer postcss

RUN npm i --no-optional -D sass-loader
RUN npm i --no-optional -D fibers
RUN npm i --no-optional -D postcss-loader@5

RUN npm i --no-optional -D html-webpack-plugin@5 --force

WORKDIR /app
RUN npm i --no-optional -D bootstrap@next

```

jsonはnext.jsのプロジェクトのものをそのまま。

```json:package.json
{
  "name": "app",
  "version": "0.0.1",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "next start",
    "build": "next build",
    "dev": "next dev",
    "lint": "eslint --ext .ts,.tsx --ignore-path .gitignore .",
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "keywords": [],
  "author": "hibohiboo <hibohiboo66+github@gmail.com>",
  "license": "MIT",
  "dependencies": {
    "date-fns": "^2.18.0",
    "date-fns-tz": "^1.1.3",
    "firebase": "^8.2.9",
    "isomorphic-unfetch": "^3.1.0",
    "next": "^10.0.7",
    "react": "^17.0.1",
    "react-dom": "^17.0.1"
  },
  "devDependencies": {
    "@types/node": "^14.14.31",
    "@types/react": "^17.0.2",
    "@types/react-dom": "^17.0.1",
    "@typescript-eslint/eslint-plugin": "^4.16.1",
    "@typescript-eslint/parser": "^4.16.1",
    "bootstrap": "^5.0.0-beta2",
    "classnames": "^2.2.6",
    "encoding": "^0.1.13",
    "eslint": "^7.21.0",
    "eslint-config-prettier": "^8.1.0",
    "eslint-plugin-prettier": "^3.3.1",
    "eslint-plugin-react": "^7.22.0",
    "eslint-plugin-react-hooks": "^4.2.0",
    "next-pwa": "^4.0.0-beta.0",
    "postcss-flexbugs-fixes": "^5.0.2",
    "postcss-preset-env": "^6.7.0",
    "prettier": "^2.2.1",
    "sanitize.css": "^12.0.1",
    "sass": "^1.32.8",
    "sharp": "^0.26.3",
    "styled-components": "^5.2.1",
    "styled-media-query": "^2.1.2",
    "stylelint": "^13.11.0",
    "stylelint-config-prettier": "^8.0.2",
    "stylelint-config-recess-order": "^2.3.0",
    "stylelint-config-recommended-scss": "^4.2.0",
    "stylelint-config-standard": "^20.0.0",
    "stylelint-declaration-block-no-ignored-properties": "^2.3.0",
    "stylelint-declaration-use-variable": "^1.7.2",
    "stylelint-no-unsupported-browser-features": "^4.1.4",
    "stylelint-prettier": "^1.2.0",
    "stylelint-scss": "^3.19.0",
    "typescript": "^4.2.2",
    "webpack": "^5.24.2"
  }
}

```
</div>
</details>


webpack5をインストールするだけではダメ。設定に、`builder:'webpack5'`と明示してやる必要がある。

```js:.storybook/main.js
const { resolve } = require('path')

module.exports = {
  core: {
    builder: 'webpack5',
  },
  stories: ['../stories/**/*.stories.tsx'],
}
```

## ハマリ2 `React is not defined `
これはNext.jsでReactはimportしなくても使えるのが原因だった。
1行追加してやることで解決。

[StorybookのFAQ](https://storybook.js.org/docs/react/workflows/faq)にあったのでハマる人は多い模様。

```diff
+ import React from 'react'
import styles from '../styles/Count.module.scss'

const Count: React.FC<{ num: string }> = ({ num }) => {
  return <span className={styles.kotaFrame}>{num}</span>
}
export default Count
```

### ハマリ3 `@import '~bootstrap/scss/functions';`が解決できない
[sass-loaderでは~でnode_modulesを示す](https://github.com/webpack-contrib/sass-loader#resolving-import-at-rules)のだが、
今回storybookをsrcとは別の深い階層にインストールしていたのが問題だったもよう。

```
- internal
  - component-catalog
    - .storybook
    - node_modules <- ここにbootstrapを入れても`で解釈されない
      - bootstrap
- node_modules <- ここのnode_modulesが~で解釈される
  - bootstrap
- src
  - styles
    - mybootstrap.scss <- ここで~bootstrapをインポートしている
```
   
なので、それに合わせて.github/workflows/gh-pages.ymlも更新

```diff
name: github pages

on:
  push:
    branches:
      - docs  # Set a branch name to trigger deployment

jobs:
  deploy:
    runs-on: ubuntu-20.04
    steps:
      - uses: actions/checkout@v2

      - name: Setup Node
        uses: actions/setup-node@v2
        with:
          node-version: '14'

      - name: StoryBook Setup
        run: npm ci
        working-directory: ./internals/component-catalog


+      - name: StoryBook Setup for ~bootstrap.scss
+        run: npm i bootstrap@next

      - name: StoryBook Make
        run: npx build-storybook -c ./.storybook -o ./component-catalog --no-dll
        working-directory: ./internals/component-catalog

      - name: StoryBook Move files
        run: |
          mkdir -p ./docs/publish/component-catalog
          mv ./internals/component-catalog/component-catalog ./docs/publish/

      - name: Deploy
        uses: peaceiris/actions-gh-pages@v3
        with:
          github_token: ${{ secrets.GITHUB_TOKEN }}
          publish_dir: ./docs
```

### ハマリ4 `Error from chokidar`
これは、公開ではなく手元で動かそうとしたときに発生したエラー。
エラーは出るが、手元でStoryBookのページは問題なく見ることができた。謎。

以下のように、chokidarがnode_modules配下のファイルを監視しようとして、監視対象がlinuxの設定上限を超えるため発生するエラーの模様。


```
Error from chokidar (/app/internals/component-catalog/node_modules/@storybook/components/node_modules/core-js/modules): Error: ENOSPC: System limit for number of file watchers reached, watch '/app/internals/component-catalog/node_modules/@storybook/components/node_modules/core-js/modules/esnext.iterator.reduce.js'
```

addonsを指定するとエラーが発生する挙動であった。

```diff

module.exports = {
  core: {
    builder: 'webpack5',
  },
  stories: ['../stories/**/*.stories.tsx'],
+  addons: ['@storybook/addon-knobs/register',],
}
```

なお、見るフォルダを指定するオプションがあるaddonだと、このエラーは起きなかった。

```diff
const { resolve } = require('path')

module.exports = {
  core: {
    builder: 'webpack5',
  },
  // ディレクトリと拡張子の変更
  stories: ['../stories/**/*.stories.tsx'],
  addons: [
+    {
+      name: '@storybook/addon-storysource',
+      options: {
+        rule: {
+          test: [/\.stories\.tsx?$/],
+          include: [resolve(__dirname, '../stories')], // You can specify directories
+        },
+      },
    },
  ],
}
```

`node_modules`の監視をignoreできるオプションがないか探したけれど見つからず。

 https://yatta47.hateblo.jp/entry/2020/11/21/213106 を参考に、`sudo sysctl fs.inotify.max_user_watches=24288`を行って設定上限をあげたところ発生はなくなった。