Storybook v6.x を v7.x に移行して Next.js v14 で使えるようにするスレ
背景
Next.js のバージョンを v12 から v13 に上げたタイミングで、それまで動いていた(いろいろ問題ありながら) Storybook v6.5 が動かなくなった。
なんとか Storybook なしで進めてきたが、いつの間にか Next.js も v13 から v14 に上がってしまった。
さすがに辛くなってきたので Storybook を使えるようにしたい。
バージョンとか
以前(動いていた)
- Next.js
v12.3.4
- Storybook
v6.5.16
目標地点
- Next.js
v14.0.4
- Storybook
v7.4.5
( 今となってはちょっと古くなってしまったが、まずはこのバージョンで... )
関連 Scrap
@storybook/addon-storysource のエラー
node_modules/@storybook/addon-storysource/preset.js:1
import './dist/preset';
^^^^^^
SyntaxError: Cannot use import statement outside a module
関係しそうな Issue は以下
storysource それほど重要でもなくなんとなく使ってただけなので、深追いはせず外すことにした。
addon-storysource
を外すことでエラーは解消した。
TypeError: docsParameter.renderer is not a function
というエラー
以下、関係していそうな箇所
@storybook/addon-docs
を main.ts
に追加したらエラーは解消した
addons: [
...
'@storybook/addon-controls',
+ '@storybook/addon-docs',
'storybook-react-i18next'
],
package.json には @storybook/addon-docs
が無かったが、 @storybook/addon-essentials
に含まれていた。
( addon-essentials
に含まれる addon )
"@storybook/addon-actions" "7.4.5"
"@storybook/addon-backgrounds" "7.4.5"
"@storybook/addon-controls" "7.4.5"
"@storybook/addon-docs" "7.4.5"
"@storybook/addon-highlight" "7.4.5"
"@storybook/addon-measure" "7.4.5"
"@storybook/addon-outline" "7.4.5"
"@storybook/addon-toolbars" "7.4.5"
"@storybook/addon-viewport" "7.4.5"
TypeError: _addons.default.getChannel is not a function
のエラー
スタックトレースから MUI およびその Theme 関連が関係してそうだったので、以下の記事を確認
main.ts に @storybook/addon-themes
を追加し、 storybook-addon-material-ui5
を外した
@@ -49,6 +49,7 @@
"@storybook/addon-backgrounds": "7.4.5",
"@storybook/addon-controls": "7.4.5",
"@storybook/addon-links": "7.4.5",
+ "@storybook/addon-themes": "7.4.5",
"@storybook/addons": "7.4.5",
"@storybook/nextjs": "7.4.5",
"@storybook/react": "7.4.5",
@@ -57,7 +58,6 @@
"@types/papaparse": "5.3.14",
"@types/react": "18.2.45",
"@types/react-dom": "18.2.17",
- "storybook-addon-material-ui5": "1.0.0",
"ts-prune": "0.10.3"
}
addons: [
...
'@storybook/addon-docs',
+ '@storybook/addon-themes',
'storybook-react-i18next'
],
font の bundle については一旦スキップ
preview.tsx で theme と global CSS を設定することでエラーは解消した
@@ -1,9 +1,11 @@
import React from 'react'
-import { muiTheme } from 'storybook-addon-material-ui5'
+import { CssBaseline, ThemeProvider } from '@mui/material'
+import { withThemeFromJSXProvider } from '@storybook/addon-themes'
import { theme } from '../src/styles/theme'
@@ -19,19 +21,31 @@
const preview: Preview = {
+ decorators: [
+ withThemeFromJSXProvider({
+ themes: {
+ default: theme
+ },
+ defaultTheme: 'default',
+ Provider: ThemeProvider,
+ GlobalStyles: CssBaseline
+ })
+ ]
}
TypeError: Cannot redefine property: default
というエラー
かつて next/image に対処するため、以下のようなコードを preview.js に記述していたのが原因
import * as nextFutureImage from 'next/image'
Object.defineProperty(nextFutureImage, 'default', {
configurable: true,
value: props => <img {...props} />
})
@storybook/nextjs
によって、このような hack は不要になったので削除した。
Image with src "https://hogehoge... " is missing required "width" property
というエラー
以前は width
/ height
の省略を許していたみたいだけど、それが許されなくなったっぽいので story でそれらを利用する箇所に width
, height
を追加する。 ( これは Storybook というより Next.js のコンポーネントの利用方法の問題 )
以前は width / height の省略を許していたみたい
この認識は誤りで、 preview.js での以下の hack で next/image
の Image
コンポーネントがネイティブの img
タグに置き換わっていたため、 width / height の省略が許されていただけだった。
Object.defineProperty(nextFutureImage, 'default', {
configurable: true,
value: props => <img {...props} />
})
MUI: Can not find the date and time pickers localization context
というエラー
It looks like you forgot to wrap your component in LocalizationProvider.
This can also happen if you are bundling multiple versions of the `@mui/x-date-pickers` package
こちらも Storybook v7 の問題というより、利用しているコンポーネントの設定問題
以下のように decorators に LocalizationProvider
を追加することで解決した。
-import { Preview } from '@storybook/react'
+import { DecoratorFunction } from '@storybook/types'
+import { Preview, ReactRenderer } from '@storybook/react'
+import { LocalizationProvider } from '@mui/x-date-pickers'
+import { AdapterDateFns } from '@mui/x-date-pickers/AdapterDateFns'
+const withLocalizationProvider: DecoratorFunction<ReactRenderer> = Story => (
+ <LocalizationProvider dateAdapter={AdapterDateFns}>
+ <Story />
+ </LocalizationProvider>
+)
const preview: Preview = {
parameters: {
backgrounds: {
@@ -39,7 +48,8 @@ const preview: Preview = {
Provider: ThemeProvider,
GlobalStyles: CssBaseline
}),
- withRecoil
+ withRecoil,
+ withLocalizationProvider
]
}
ModuleDependencyWarning: Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
というエラーで失敗する
smoke test が ブラウザの console とかにも出てたけど warning だったのでスルーしてた...
関係しそうな Issue
@storybook/nextjs
のコードで発生しているように見える
この PR で直したっぽい?
Storybook v7.4.5 にもその修正は入っている
ちゃんとメッセージ読むか...
../../node_modules/@storybook/nextjs/dist/chunk-FFRTCGB4.mjs 1:224-231Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
../../node_modules/@storybook/nextjs/dist/chunk-FFRTCGB4.mjs 1:353-360Critical dependency: require function is used in a way in which dependencies cannot be statically extracted
このメッセージ自体は webpack が出しているっぽい?
ダメ元で node_modules
や yarn.lock
消して、 yarn install
し直してみる。
https://github.com/webpack/webpack/discussions/17819#discussioncomment-7654867
When I installed the old package again, this error persisted.
So I also restored the package-lock.json file.
After running the npm install command, the problem was solved.
変わらなかった
Warning が出るものの、とりあえず動いてはいるので一旦無視してみる
@@ -25,6 +25,13 @@ const config: StorybookConfig = {
}
})
config.resolve!.extensions!.push('.ts', '.tsx')
+ config.ignoreWarnings = [
+ {
+ message:
+ /Critical dependency: require function is used in a way in which dependencies cannot be statically extracted/
+ }
+ ]
return config
},
Storybook 7.6.0 でこの問題に対応されていた
Duplicate stories with id: xxx-xxx-xxx
というエラーが Storybook サーバ側に出ていた
12% building 0/2 entries 125/213 dependencies 3/69 modulesWARN 🚨 Unable to index files:
WARN - ./src/components/molecules/Hoge/index.stories.tsx,./src/components/molecules/Fuga/index.stories.tsx: Duplicate stories with id: molecules-xxxx--default
WARN - ./src/components/molecules/Hoge/index.stories.tsx,./src/components/molecules/Fuga/index.stories.tsx: Duplicate stories with id: molecules-xxxx--less-texts
stories の export default
オブジェクトで設定している title
プロパティが Hoge
と Fuga
で重複していたのが原因だった。
title にセットする値をユニークな名前にしたらエラーは解消した
export default {
component: Hoge,
title: 'molecules/xxxx' // <-- ここが重複してた
}
prettier.resolveConfig is not a function
が出るようになってしまった
これまで出なかったのが出るようになってしまった ...
eslint-plugin-prettier
の問題っぽい?
TypeError: (0 , next_font_google__WEBPACK_IMPORTED_MODULE_0__.Noto_Sans_JP) is not a function
というエラーがページに出る
next/font/google はサポートしているはずだが... ?
You don't have to do anything. next/font/google is supported out of the box.
https://www.npmjs.com/package/@storybook/nextjs#nextjs-font-optimization
エラーは以下の箇所で発生している
"use strict";
__webpack_require__.r(__webpack_exports__);
/* harmony export */ __webpack_require__.d(__webpack_exports__, {
/* harmony export */ exo: () => (/* binding */ exo),
/* harmony export */ notoSansJP: () => (/* binding */ notoSansJP),
/* harmony export */ });
/* harmony import */ var next_font_google__WEBPACK_IMPORTED_MODULE_0__ = __webpack_require__(/*! next/font/google */ "../../node_modules/next/font/google/index.js");
/* harmony import */ var next_font_google__WEBPACK_IMPORTED_MODULE_0___default = /*#__PURE__*/__webpack_require__.n(next_font_google__WEBPACK_IMPORTED_MODULE_0__);
var notoSansJP = (0,next_font_google__WEBPACK_IMPORTED_MODULE_0__.Noto_Sans_JP)({
weight: ['400', '500', '700'],
preload: false
});
以下が怪しいが...
v7.1.0
以降には適用されているはず...
切り分けのために、Noto Sans JP を Exo などに置き換えてみる.
置き換えた font が読み込めていないので next/font
がうまく動いてなさそう。
TypeError: (0 , next_font_google__WEBPACK_IMPORTED_MODULE_0__.Exo) is not a function
code/frameworks/nextjs/src/font/webpack/loader/storybook-nextjs-font-loader.ts
このあたりで読み込んでいるはず?
next/font のサポートが入った最初の PR
いったん、next/font/google
を使わない方向に切り替えてみて、あとで対処する。
その後以下の調査で、 Babel と Webpack の動作が鍵になりそうだと判明し、 .storybook/main.ts
に使っているのかよくわからない babel
の設定があったので削ったら動くようになった
@@ -5,10 +5,7 @@ import { StorybookConfig } from '@storybook/nextjs'
// Export a function. Accept the base config as the only param.
const config: StorybookConfig = {
stories: ['../src/components/**/*.stories.tsx'],
- babel: { /* ... babel config ... */ },
-
docs: {
autodocs: true
}
Cannot read properties of undefined (reading 'white')
というエラーがページに出る
どうも theme の設定ができてなさそう?
エラー出しているのは以下の箇所
const body = theme => (0,_babel_runtime_helpers_esm_extends__WEBPACK_IMPORTED_MODULE_2__["default"])({
color: (theme.vars || theme).palette.text.primary
}, theme.typography.body1, {
backgroundColor: (theme.vars || theme).palette.background.default,
'@media print': {
// Save printer ink.
backgroundColor: (theme.vars || theme).palette.common.white
}
});
break point 仕込んでみた感じ theme.palette.common.white
を参照しようとしてるが、common
が無さそう。
見た感じ MUI の CssBaseline
のコードっぽい
今使っているバージョン
"@mui/material": "5.15.1",
同じバージョン使ってて動いているものもあるので、theme についてそれとの差分を調べる。
themeDecorator
で themes.default
に対して、createTheme(appTheme)
から返却されたオブジェクトを使うべきところ、 その元となる appTheme
のほうを渡していたからだった...
以下のように createTheme()
の結果を渡すように修正したらエラーは解消した
const themeDecorator: DecoratorFunction<ReactRenderer> = withThemeFromJSXProvider({
themes: {
- default: getTheme('light', 'ja')
+ default: createTheme(getTheme('light', 'ja'))
},
defaultTheme: 'default',
Provider: ThemeProvider,
GlobalStyles: CssBaseline
})
あとは next/font/google
の問題 がどうにかなれば...
Occasionally fetching fonts from Google may fail as part of your Storybook build step. It is highly recommended to mock these requests, as those failures can cause your pipeline to fail as well. Next.js supports mocking fonts via a JavaScript module located where the env var NEXT_FONT_GOOGLE_MOCKED_RESPONSES references
Storybook のバージョン上げれば(今は 7.4.5) Google Fonts からの font ファイルダウンロードを mock する機能がある。
試してみる価値はありそう。
Storybook の機能というより Next.js の機能だった
ここまでで、ほとんどのコンポーネントが Storybook で動くようになったので一旦クローズする
後は気が向いたときに対応する。