概要
nextjsのプロジェクトにstorybookを導入します。
主な話題は詰まった点の対処方法についてです。
開発環境
OS:windows10
IDE:VSCode
├── @babel/core@7.20.7
├── @storybook/addon-actions@6.5.15
├── @storybook/addon-essentials@6.5.15
├── @storybook/addon-interactions@6.5.15
├── @storybook/addon-links@6.5.15
├── @storybook/addon-postcss@2.0.0
├── @storybook/builder-webpack4@6.5.15
├── @storybook/manager-webpack4@6.5.15
├── @storybook/react@6.5.15
├── @storybook/testing-library@0.0.13
├── @styled-jsx/plugin-sass@3.0.0
├── @styled/storybook-addon-jsx@7.4.2
├── @types/node@18.11.15
├── @types/react-dom@18.0.9
├── @types/react@18.0.26
├── axios@1.2.1
├── babel-loader@8.3.0
├── babel-plugin-react-require@3.1.3
├── eslint-config-next@13.0.6
├── eslint-plugin-storybook@0.6.8
├── eslint@8.29.0
├── next-auth@4.18.7
├── next@13.0.1
├── react-bootstrap@2.7.0
├── react-dom@18.2.0
├── react@18.2.0
├── sass@1.57.1
├── styled-components@5.3.6
├── styled-jsx@5.1.1
└── typescript@4.9.4
インストールと起動
以下コマンド実行
npx sb@latest init
npm run storybook
適当に作ったコンポーネントとストーリーを追加します。
コンポーネントには画像表示機能があり cssはstyled-jsx記法で書かれています。
import Image from 'next/image';
interface Props{
productName:string;
priceWithoutTax:number;
priceIncludingTax:string;
imageURL:string;
}
/**
*
* @param props 商品情報
* @returns 商品情報を表示するコンポーネント
*/
export default function ProductContent(props : Props){
return(
<>
<div className = 'ContentPadding ContentLayout'>
<Image src={props.imageURL}
width={160}
height={150}
alt='logo' />
<div>{props.productName}</div>
<div className='PriceWithoutTaxAndQuantityLayout'>
<div>{`税抜` + props.priceWithoutTax +`円`}</div>
<div>数量</div>
<div><select>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
<option value="5">5</option>
</select>
</div>
</div>
<div className='PriceIncludingTaxAndBuyButtonLayout'>
<div>{`税込` + props.priceIncludingTax +`円`}</div>
<button >購入</button>
</div>
</div>
<style jsx>{`
// 大枠の空白部分を担当
.ContentPadding{
padding: 20px;
border:1px solid black;
}
// 大枠のレイアウト(縦並び)
.ContentLayout{
position:relative;
flex:1;
width:200px;
}
// 税抜き価格と数量のレイアウト(横並び-等間隔)
.PriceWithoutTaxAndQuantityLayout{
display:flex;
justify-content:space-between;
}
// 税込み価格と購入ボタンのレイアウト(横並び-等間隔)
.PriceIncludingTaxAndBuyButtonLayout{
display:flex;
justify-content:space-between;
}
`}</style>
</>
)
}
import React from 'react';
import { ComponentStory, ComponentMeta } from '@storybook/react';
import ProductContent from '.././component/productContent';
import { jsxDecorator } from "@styled/storybook-addon-jsx";
export default{
title:'Example/pagination',
component:ProductContent,
} as ComponentMeta<typeof ProductContent>;
const Template: ComponentStory<typeof ProductContent> = (args) => <ProductContent {...args} />;
export const AAb = Template.bind({});
AAb.args = {
productName:'aaasaasasasas',
priceWithoutTax:200,
priceIncludingTax:'299',
// 画像ファイルたちはpublicフォルダにあることが前提
imageURL:"/sampleProduct1.jpg"
// imageURL:"/vercel.svg"
// imageURL:"/sample.png"
};
storybookを開けましたが、画像とcssの設定がうまくいきません。
詰まった点
1.画像(jpg)が表示されない
最初の症状
jpg,png画像が取得されない。
svgの画像も取得できない
(1) .storybook/main.jsの内容を編集して publicフォルダにアクセスできるようにする。
module.exports = {
"stories": [
"../stories/**/*.stories.mdx",
"../stories/**/*.stories.@(js|jsx|ts|tsx)"
],
"addons": [
"@storybook/addon-links",
"@storybook/addon-essentials",
"@storybook/addon-interactions",
"@styled/storybook-addon-jsx"
],
"framework": "@storybook/react",
+ "staticDirs": ["../public"],
"core": {
"builder": "webpack4"
},
}
変更後の結果は以下の様になります。
jpg,png画像が取得されない。
svgの画像は取得できる。
jpgの画像を使っているときの画像 右側のコンソールからデータの取得が失敗していることがわかります
svgの画像を使っているときの画像 右側のコンソールからデータの取得が成功していることがわかります。
(2) ./storybook/preview.js にコードを追加して、jpgファイルでも読み取れるようにする。
jpgファイルも表示できるように.storybook/preview.jsに以下コードを追加します。
import Image from 'next/image';
export const parameters = {
actions: { argTypesRegex: "^on[A-Z].*" },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/,
},
},
}
+Image.propTypes = {
+ unoptimized: null,
+ };
+ Image.defaultProps = {
+ unoptimized: true,
+ };
jpegファイルが表示されていることを確認できます。
2.styled-jsx形式のcssが無効になっている。
公式のgithubのリポジトリから各種設定を比較します。
参考にするリポジトリはvercelのnextjsのリポジトリです。
このリポジトリの良いところは簡単にデプロイができ、CodeSpacesで実物の動きを確認できることです。
参考にしたファイルはpackage.jsonと.babelrcの2点です。
以下設定
{
"presets": [
[
"next/babel",
{
"styled-jsx": {
"plugins": ["@styled-jsx/plugin-sass"]
}
}
]
]
}
{
"name": "ecshop_front",
"version": "0.1.0",
"private": true,
"scripts": {
"dev": "next dev",
"build": "next build",
"start": "next start",
"lint": "next lint",
"storybook": "start-storybook -p 6006",
"build-storybook": "build-storybook"
},
"dependencies": {
"@types/node": "18.11.15",
"@types/react": "18.0.26",
"@types/react-dom": "18.0.9",
"axios": "^1.2.1",
"babel-plugin-react-require": "^3.1.3",
"eslint": "8.29.0",
"eslint-config-next": "13.0.6",
"next": "13.0.1",
"next-auth": "^4.18.7",
"react": "18.2.0",
"react-bootstrap": "^2.7.0",
"react-dom": "18.2.0",
"styled-components": "^5.3.6",
"styled-jsx": "^5.1.0",
"typescript": "4.9.4",
+ "sass": "^1.49.0"
},
"devDependencies": {
"@babel/core": "^7.20.7",
"@storybook/addon-actions": "^6.5.15",
"@storybook/addon-essentials": "^6.5.15",
"@storybook/addon-interactions": "^6.5.15",
"@storybook/addon-links": "^6.5.15",
"@storybook/addon-postcss": "^2.0.0",
"@storybook/builder-webpack4": "^6.5.15",
"@storybook/manager-webpack4": "^6.5.15",
"@storybook/react": "^6.5.15",
"@storybook/testing-library": "^0.0.13",
"@styled/storybook-addon-jsx": "^7.4.2",
"babel-loader": "^8.3.0",
"eslint-plugin-storybook": "^0.6.8",
+ "@styled-jsx/plugin-sass": "^3.0.0"
}
}
参考
public フォルダの設定方法
jpegファイルを表示できるようにするpreview.jsの設定方法