22sook00 logo
SookDev

스토리북으로 공통컴포넌트 배포하기

tag
style
deploy
react
next.js
date
Jul 28, 2023

🌷 React + emotion

📢
Version storybook : “^7.0.17”, react : “^18.2.0”, react-hook-form": "^7.43.9", @emotion/react : "^11.10.5", @emotion/styled : "^11.10.5", @mui/material: "^5.13.2",

스토리북 설치

작업중이던 React 혹은 Next.js 로 프로젝트에 스토리북을 설치한다.
나같은 경우 빈 프로젝트에 스토리북을 바로 설치하여 추후 package.json 내부 script 에 리액트를 추가로 설정하였다.
//Add Storybook: npx storybook@latest init //스토리북에 적용할 addon 설치 yarn add -D @storybook/addon-styling @storybook/addon-actions @storybook/addon-knobs
notion image

main.js

stories : 스토리북이 보여질 경로를 설정한다. 나같은 경우 src 하위폴더에서 작업하여 src 를 추가했다.
addons : 설치한 addon 이 적용되기 위해 main.js 의 addons 배열안에 추가해야 한다.
framework : webpack 5 버전임을 명시하는 코드를 추가한다. storybook이 실행될때는 emotion을 찾을 수 없기때문에, webpack 설정을 반드시 같이 해줘야 한다.
/** @type { import('@storybook/react-webpack5').StorybookConfig } */ const config = { stories: ['../src/**/*.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', '@storybook/addon-interactions', '@storybook/addon-styling', '@storybook/addon-actions', '@storybook/addon-knobs', ], framework: { name: '@storybook/react-webpack5', options: {}, }, docs: { autodocs: 'tag', }, }; export default config;

preview.js

스토리북에서 볼 수 있는 폴더로, 보통 기본은 다음코드와 같이 이루어져 있으나,
이 부분에 GlobalStyle 을 적용해야 스토리북에 emotion 이 적용되어 보일 수 있다.
export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, controls: { expanded: true, matchers: { color: /(background|color)$/i, date: /Date$/, }, }, };
 
 

GlobalStyle 적용

전역으로 적용될 스타일을 적용하기 위해 preview.js 에 GlobalStyles 컴포넌트를 작성한 후
@storybook/addon-styling 에서 제공하는 withThemeFromJSXProvider 메소드로 감싸주어야 한다.
나같은 경우 코드가 길어지는것을 선호하지 않아 withTheme.decorator.js 파일을 생성하여 코드를 분리했다.
//preview.js import { withTheme } from './withTheme.decorator'; import { withThemeFromJSXProvider } from '@storybook/addon-styling'; export const parameters = { actions: { argTypesRegex: '^on[A-Z].*' }, controls: { expanded: true, matchers: { color: /(background|color)$/i, date: /Date$/, }, }, }; export const globalTypes = { theme: { name: 'Theme', description: 'Global theme for components', toolbar: { icon: 'paintbrush', items: [ { value: 'light', title: 'Light', left: '🌞' }, { value: 'dark', title: 'Dark', left: '🌛' }, ], // Change title based on selected value dynamicTitle: true, }, }, }; export const decorators = [withThemeFromJSXProvider(withTheme)];
//withTheme.decorator.js import { css, Global, ThemeProvider, useTheme } from '@emotion/react'; //light/dark 모드를 위한 테마 객체. import { lightTheme, darkTheme } from '../src/stories/theme'; const THEMES = { light: lightTheme, dark: darkTheme, }; // Sets the background based on theme const GlobalStyles = () => { const theme = useTheme(); return ( <Global styles={css` html, body { background-color: ${theme.colors.background}; color: ${theme.colors.text}; } `} /> ); }; export const withTheme = (Story, context) => { const { theme } = context.globals; return ( <ThemeProvider theme={THEMES[theme] || THEMES['light']}> <GlobalStyles /> <Story /> </ThemeProvider> ); };

chromatic 배포

 
배포 순서
  1. yarn add -D chromatic 설치
  1. git hub 레포지토리 연결
  1. chromatic 사이트에서 토큰 발급
  1. 터미널에 npx chromatic --project-token=발급토큰 입력
 
사실 크로마틱 배포는 공식문서에 나온 그대로 하면 전혀 어렵지가 않다.
하지만 나는 앞서 말했듯이 storybook init 부터 했기때문에 chromatic 배포 시 script 가 존재하지 않다고 에러 문구가 나왔다.
현재까지 작업한것이 물거품이 되나 싶어 순간 당황했지만, package.json에 react 혹은 next.js 설정만 넣어주고 yarn install 하면 끝이었다.
나같은 경우 굳이 next.js 까진 필요없을 것 같아 리액트로 재구축 하였다.
(지금 생각해보니 검색엔진이 내 스토리를 찾을 확장성까지 생각했다면 next.js 로 구축해도 좋았을 것 같다.)
//package.json "dependencies": { "@emotion/react": "^11.10.5", "@emotion/styled": "^11.10.5", ... "react": "^18.2.0", "react-dom": "^18.2.0", "react-scripts": "5.0.1", "web-vitals": "^2.1.4" }, "scripts": { "start": "react-scripts start", "build": "react-scripts build", "test": "react-scripts test", "eject": "react-scripts eject", "storybook": "storybook dev -p 6006", "build-storybook": "storybook build", },
script 내부 안에 리액트로 빌드한다고 명시한 후
npx chromatic --project-token=발급토큰 을 터미널에 다시 재 입력하면 5분 내외로 배포가 되는것을 확인할 수 있다.
notion image
notion image

배포 사이트

 

참조

 

🦋 Next.js + Tailwindcss

💡
사용스택 Next.js Typescript Tailwindcss + Chromatic 배포

폴더구조

// typescript, next 패키지 설치 npx create-next-app@latest --typescript // tailwindcss 설치 npm install -D tailwindcss postcss autoprefixer npx tailwindcss init -p
notion image

tailwind 설정

tailwind.config.js
src 디렉토리 생성하여 경로를 알맞게 설정해준다.
notion image
globals.css src / styles / globals.css
notion image

👇🏻 테일윈드에 대한 자세한 설명은
 
 

스토리북 설정

스토리북 설치
npm i storybook -g // 스토리북에 적용할 postcss를 위한 npm install npm i -D @storybook/addon-postcss
스토리북은 cra, cna 와 같은 패키지모듈로 설치했더라도 웹팩 설정을 해줘야 한다.
package.json 에 다음과 같이 webpack 5 버전임을 명시하는 코드를 작성한다
// package.json "resolutions": { "@storybook/{app}/webpack": "^5" }
웹팩5 를 이용하여 스토리북을 빌드하기 위해 다음과 같이 webpack5 빌더 설치하여 초기화
npx sb init --builder webpack5
 

 
스토리북 설정
.storybook / main.js
const path = require('path'); module.exports = { stories: ['../src/**/*.stories.mdx', '../src/**/*.stories.@(js|jsx|ts|tsx)'], /** Expose public folder to storybook as static */ staticDir: ['../public'], addons: [ '@storybook/addon-links', '@storybook/addon-essentials', { /** * Fix Storybook issue with PostCSS@8 * @see https://github.com/storybookjs/storybook/issues/12668#issuecomment-773958085 */ //postcss를 활용할 수 있도록 이 부분 추가. name: '@storybook/addon-postcss', options: { postcssLoaderOptions: { implementation: require('postcss'), }, }, }, ], // webpack5를 사용할 수 있도록 이 부분 추가 core: { builder: 'webpack5', }, //여기서부터는 기타 경로, alias 설정 webpackFinal: (config) => { /** * Add support for alias-imports * @see https://github.com/storybookjs/storybook/issues/11989#issuecomment-715524391 */ config.resolve.alias = { ...config.resolve?.alias, "@": [path.resolve(__dirname, "../src/"), path.resolve(__dirname, "../")], }; /** * Fixes font import with / * @see https://github.com/storybookjs/storybook/issues/12844#issuecomment-867544160 */ config.resolve.roots = [ path.resolve(__dirname, "../public"), "node_modules", ]; return config; }, }
 
.storybook / preview.js
꼭 스토리북에서 적용할 파일의 css 가 담긴 파일을 import 해주어야 한다.
import "../src/styles/globals.css"; import "../src/components/Buttons/Button.tsx" /* next에서 제공하는 <NextImage/> 를 가져오려면 주석처리 된 코드 입력 import * as NextImage from "next/image"; const OriginalNextImage = NextImage.default; Object.defineProperty(NextImage, "default", { configurable: true, value: (props) => <OriginalNextImage {...props} unoptimized />, }); */ export const parameters = { actions: { argTypesRegex: "^on[A-Z].*" }, controls: { matchers: { color: /(background|color)$/i, date: /Date$/, }, }, previewTabs: { "storybook/docs/panel": { index: -1 }, }, };
 

 
스토리북 실행
npm run storybook //or yarn storybook

스토리북 배포