Nuxt.js + Storybook 통합하기

Storybook 공식홈페이지에는 Storybook에 Vue를 통합을 위한 가이드가 있습니다. 같은 Vue.js 기반의 Nuxt.js는 vue-cli 프로젝트와 다르게, 프로그램 시작점인 main.js를 사용자에게 제공하지 않기 때문에…

Nuxt.js + Storybook 통합하기

Storybook 공식홈페이지에는 Storybook에 Vue를 통합을 위한 가이드가 있습니다. 같은 Vue.js 기반의 Nuxt.js는 vue-cli 프로젝트와 다르게, 프로그램 시작점인 main.js를 사용자에게 제공하지 않기 때문에 Storybook을 설정하기가 쉽지 않습니다.

위 이유 때문에 다른 CSS프레임워크를 사용하고 있는 경우 .storybookconfig.js 파일을 Vue 프로젝트의 main.js 라고 간주하여 설정을 하여야 합니다.

이번 글에서는 Tailwindcss를 사용하는 Nuxt.js 프로젝트에 Storybook을 추가하는 방법을 안내합니다.

Tailwindcss는 PostCSS를 이용하는 라이브러리입니다. Nuxt.js는 webpack을 번들러로 사용하므로 postcss-loader를 이용해 tailwindcss를 번들링합니다.

npx create-nuxt-app my-app

터미널에서 위 명령어를 이용해 Nuxt.js 앱을 만듭니다. CSS 프레임워크 / 라이브러리를 고를 때 꼭 Tailwindcss를 선택해주세요

npm install --save-dev @storybook/vue babel-core

위 명령어를 입력하면 Vue를 위한 Storybook을 프로젝트 의존성 목록에 추가합니다. 다음 명령어로 Storybook에 필요한 파일들을 만듭니다.

mkdir .storybook 
touch config.js 
touch webpack.config.js 
cp postcss.config.js ./.storybook

첫번째로 config.js 폴더에서 프로젝트를 구성합니다.

// config.js 
import { configure } from '@storybook/vue'; 
import 'tailwindcss/dist/tailwind.min.css' 
import '../assets/css/tailwind.css'
import Vue from 'vue'; 
// import Vuex from 'vuex'; // Vue plugins
const req = require.context('../components', true, /\.story\.js$/)
function loadStories() { 
  req.keys().forEach((filename) => req(filename)) 
}
configure(loadStories, module);

앞서 말한 것 처럼 Vue.js 프로젝트의 main.js 파일로 간주하여 유사하게 프로젝트를 셋팅하면됩니다.

// postcss.config.js 
const join = require('path').join 
const tailwindJS = join(__dirname, '..', 'tailwind.js')
console.log('tailwindJS => ', tailwindJS) 
module.exports = { 
  plugins: [ 
    require('tailwindcss')(tailwindJS), 
    require('autoprefixer') 
  ] 
}

복사한 postcss.config.js 파일에서 TailwindJS 경로에 '..' 만 추가합니다. 이제 Storybook에서 webpack 설정을 하면 마무리됩니다.

// webpack.config.js 
const path = require('path');
module.exports = async ({ config, mode }) => { 
  config.module.rules.push({ 
    test: /\.scss$/, 
    loaders: ['style-loader', 'css-loader', 'sass-loader', 'postcss-loader'], 
    include: path.resolve(__dirname, '../'), 
  }); 
  return config; 
};

webpack 설정까지 마쳤습니다. 첫번째 Storybook의 story를 만들어봅니다. config.js 파일에서 각 컴포넌트와 같은 경로에 story를 위치하도록 하였습니다.

touch ./components/Logo.story.js

위 파일을 열고 아래의 내용으로 채워줍니다.

import { storiesOf } from '@storybook/vue';
import Logo from './Logo.vue'
storiesOf('Logo', module) 
  .add('Logo Component', () => ({ 
    components: { Logo }, 
    template: '<logo />', 
  }));

Logo.vue 컴포넌트를 열어 불러오는 것만으로 한개의 story를 만들었습니다. 자세한 내용은 Storybook의 문서를 보고 시도해보세요.

마지막으로 Storybook을 실행합니다. package.json 을 열어 아래 스크립트를 추가합니다.

{ 
  "scripts": { 
    // ... 
    "storybook": "start-storybook -p 6006 -c .storybook" 
    /... 
}

쉘을 열어 npm run storybook 명령어를 실행해 로고 컴포넌트가 Storybook에 정상적으로 등록되었는지 확인하세요.

Tailwindcss는 엘리먼트의 class 속성에 인라인 스타일을 넣는 것 과 유사한 방식으로 사용합니다.

<template> 
  <div class="bg-white mx-auto max-w-sm shadow-lg rounded-lg overflow-hidden"> 
    <div class="sm:flex sm:items-center px-6 py-4"> 
      <img class="block h-16 sm:h-24 rounded-full mx-auto mb-4 sm:mb-0 sm:mr-4 sm:ml-0" src="https://avatars2.githubusercontent.com/u/4323180?s=400&u=4962a4441fae9fba5f0f86456c6c506a21ffca4f&v=4" alt=""> 
      <div class="text-center sm:text-left sm:flex-grow"> 
        <div class="mb-4"> 
          <p class="text-xl leading-tight">Adam Wathan</p> 
          <p class="text-sm leading-tight text-grey-dark">Developer at NothingWorks Inc.</p> 
        </div> 
        <div> 
          <button class="text-xs font-semibold rounded-full px-4 py-1 leading-normal bg-white border border-purple text-purple hover:bg-purple hover:text-white">Message</button> 
        </div> 
      </div> 
    </div> 
  </div> 
</template>

위 컴포넌트를 만들고 Storybook에서 확인해보세요. Tailwindcss에서 사용하는 class를 Storybook에서도 사용할 수 있습니다.

Bootstrap, Foundation등의 CSS프레임워크는 PostCSS를 사용하지 않기 때문에 webpack이나 PostCSS설정을 추가로 할 필요는 없을 것 입니다. 만약 추가적으로 jQuery등의 설정을 한다면 이 문서의 webpack 설정 부분에서 해주시면됩니다.

Storybook webpack 설정 : https://storybook.js.org/docs/configurations/custom-webpack-config/

Subscribe to Half-Built Life

Don’t miss out on the latest issues. Sign up now to get access to the library of members-only issues.
jamie@example.com
Subscribe