この記事の概要
Storybookを使っているプロジェクトがあるのですが、ビルダーをwebpackからViteに乗り換えたかったので調べてみました。
React + Emotionの環境です。
環境
モジュール | バージョン |
---|---|
@emotion/react | 11.9.0 |
@storybook/react | 6.5.5 |
react | 18.1.0 |
typescript | 4.7.2 |
vite(今回追加) | 4.0.0 |
やったこと
まずは以下のドキュメントの通りに進めました。
必要な依存関係をインストールします。
@storybook/builder-vite
だけでは駄目で、自分でViteを入れる必要があります。
yarn add --dev vite @storybook/builder-vite
.storybook/main.js
を更新します。
Emotionを使っている関係でbabelの設定も入っています。
module.exports = {
stories: ['../src'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
+ core: {
+ builder: '@storybook/builder-vite',
+ },
framework: '@storybook/react',
babel: async (options) => ({
...options,
presets: [...options.presets, '@emotion/babel-preset-css-prop'],
}),
}
一度コマンドを叩いてみました。
yarn storybook
エラーが出ています。
.storybook/preview.js
の中でJSXの構文を使っているため、拡張子を.jsx
にするように言われています。
Failed to parse source for import analysis because the content contains invalid JS syntax. If you are using JSX, make sure to name the file with the .jsx or .tsx extension.
[vite] Internal server error: Failed to parse source for import analysis because the content contains invalid JS syntax. If you are using JSX, make sure to name the file with the .jsx or .tsx extension.
変更して再度Storybookを立ち上げました。
すると今度は立ち上がったものの、スタイルが当たっていません。
jsx pragmaを忘れたときと同じエラーが出ています。
<div css="
You have tried to stringify object returned from `css` function.
It isn't supposed to be used directly (e.g. as value of the `className` prop), but rather handed to emotion so it can handle it (e.g. as value of `css` prop).
"></div>
色々調べているうちに以下のIssueにたどり着きました。
自分の環境だと@emotion/babel-plugin
ではなく、まだ@emotion/babel-preset-css-prop
を使っていたのでそれを変更しています。
あとexclude
にはデフォルトでnode_modulesが指定されているのもあり、若干怪しいです。
一応現段階だと、この指定を消しても動いているように見えています。
const path = require('path')
+ const react = require('@vitejs/plugin-react')
module.exports = {
stories: ['../src'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
core: {
builder: '@storybook/builder-vite',
},
framework: '@storybook/react',
babel: async (options) => ({
...options,
presets: [...options.presets, '@emotion/babel-preset-css-prop'],
}),
+ async viteFinal(config) {
+ config.plugins = config.plugins.filter(
+ (plugin) =>
+ !(Array.isArray(plugin) && plugin[0]?.name.includes('vite:react')),
+ )
+ config.plugins.push(
+ react({
+ exclude: [/\.stories\.(t|j)sx?$/, /node_modules/],
+ jsxImportSource: '@emotion/react',
+ babel: {
+ presets: ['@emotion/babel-preset-css-prop'],
+ },
+ }),
+ )
+ return config
+ },
}
上記の設定で無事に動いたので、不要な設定を消します。
const path = require('path')
const react = require('@vitejs/plugin-react')
module.exports = {
stories: ['../src'],
addons: ['@storybook/addon-links', '@storybook/addon-essentials'],
core: {
builder: '@storybook/builder-vite',
},
framework: '@storybook/react',
- babel: async (options) => ({
- ...options,
- presets: [...options.presets, '@emotion/babel-preset-css-prop'],
- }),
async viteFinal(config) {
config.plugins = config.plugins.filter(
(plugin) =>
!(Array.isArray(plugin) && plugin[0]?.name.includes('vite:react')),
)
config.plugins.push(
react({
exclude: [/\.stories\.(t|j)sx?$/, /node_modules/],
jsxImportSource: '@emotion/react',
babel: {
presets: ['@emotion/babel-preset-css-prop'],
},
}),
)
return config
},
}
最後に
Storybook自体というより、Emotionの設定に苦戦した感があります。
しかしこれでスピードも上がるしモダンな設定にもなるしで良かったです。
Storybookを使っているプロジェクトは多いと思うので、マイグレーションの参考になれば幸いです。
最後まで読んでくださってありがとうございます!
Twitterでも情報を発信しているので、良かったらフォローお願いします!
Devトークでのお話してくださる方も募集中です!