Nuxt + TypeScript + DockerのプロジェクトでStorybookの代わりを考える - inokawablog

Nuxt + TypeScript + DockerのプロジェクトでStorybookの代わりを考える

Storybookとはコンポーネントがどのような挙動をするのかテストできたり、コンポーネントを一覧でみることのできるカタログのようなものです。

とても便利なStorybookですが、Nuxt + TypeScriptのプロジェクトに対して相性が悪く、導入しづらい部分があります。

さらにStorybook独自の書き方で記述しなければいけないので、しっかりと管理する体制が整っていれば良いのですが、そうではない場合に形骸化しやすいものでもあります。

なので今回は、Storybookを使用せずにNuxt + TypeScriptのプロジェクトでUIコンポーネントのカタログを作成したいと思います。

導入方法

ディレクトリは以下のようになっています。src/にディレクトリをまとめています。

root
├── README.md
├── src
│   ├── pages
│   ├── plugins
│   ├── static
│   ├── store
│ ├── layouts
│ ├── components
│ └── assets
│    └── sass
│    └── main.scss
├── test
├── Dockerfile
├── docker-compose.yml
├── middleware
├── node_modules
├── nuxt.config.ts
├── package.json
├── stylelint.config.js
├── tsconfig.json
└── yarn.lock

Dockerfile,docker-compose.ymlは以下

Dockerfile

# イメージ指定
FROM node:12.13.0-alpine

WORKDIR /app

# コマンド実行
RUN apk update && \
    apk add git && \
    npm install -g @vue/cli nuxt create-nuxt-app

EXPOSE 5000

docker-compose.yml

version: '3'
services:
  nuxt:
    build: .
    stdin_open: true
    tty: true
    volumes:
      - ./:/app:delegated
    ports:
      - 5000:5000
    environment:
      - HOST=0.0.0.0
      # Docker用にpollingの設定。ファイルを書き換えた時のブラウザ自動更新を有効化
      - CHOKIDAR_USEPOLLING=true
    command: yarn run dev

カタログ用のディレクトリ作成

カタログ用のディレクトリを作成します。

rootのしたにdoc/を作成します。

$ mkdir doc

doc/にnuxt.config.tsを作成します。

$ cd doc

$ touch nuxt.config.ts

内容を以下のようにしてください。

import nuxtMainConfig from '../nuxt.config'

// ルートを変更
nuxtMainConfig.srcDir = 'doc/src/'
// ミドルウェアがかからないようにする
nuxtMainConfig.router.middleware = []

module.exports = nuxtMainConfig

doc/にもsrcを作成してルートディレクトリ以下のsrcと同じような構成にしておきます。

$ mkdir src src/pages src/layouts

index.vueを作成しておきます。

$ touch pages/index.vue

index.vue

<template>
  <div class="container">
      <h1>docページ</h1>
  </div>
</template>

<script lang="ts">
import Vue from 'vue'

export default Vue.extend({})
</script>

次にpackage.jsonにカタログを起動するためのコマンドを追加します。

{
  ...
  "scripts": {
    "dev": "nuxt-ts",
    "build": "nuxt-ts build",
    "generate": "nuxt-ts generate",
    "start": "nuxt-ts start",
    "lint": "eslint --ext .js,.vue --ignore-path .gitignore .",
    "doc": "nuxt-ts --config-file ./doc/nuxt.config.ts -p 9001", // 追加
    "test": "jest"
  },
  ...
}

Dockerの修正

次にdockerの設定を変更します。

docker-compose.ymlに9001ポートを追加します。

version: '3'
services:
  nuxt:
    build: .
    stdin_open: true
    tty: true
    volumes:
      - ./:/app:delegated
    ports:
      - 5000:5000
      - 9001:9001 # 追加
    environment:
      - HOST=0.0.0.0
      - CHOKIDAR_USEPOLLING=true

上記の状態の設定では@や~などのエイリアスのパスが解決できずエラーになってしまいます。そのため、元のroot/nuxt.config.tsを修正します。

その前にライブラリのpath@types/webpackをインストールしておきます。

$ yarn add path @types/webpack
import { Configuration } from 'webpack'

const path = require('path')

export default {
  ...
  /*
   ** Global CSS
   */
  css: ['@/assets/sass/main.scss'],
  /**
   * Build configuration
   * https://ja.nuxtjs.org/faq/extend-webpack/
   */
  build: {
    devtools: true,
    extend(config: Configuration) {
      config.resolve.alias['~'] = path.join(__dirname, './src')
      config.resolve.alias['@'] = path.join(__dirname, './src')
    }
  }
}

シンボリックリンクを貼る

pluginsを使っている場合、他のディレクトリを参照する場合、~@のパスを解決することができません。

そのため、シンボリックリンクを貼る必要があります。

Dockerを使っているので、コンテナ内に入ってからシンボリックリンクを貼る必要があります。ちなみにシンボリックリンクはGithubでcloneしてもしっかりと機能します。

# コンテナの中に入る
$ docker-compose run --rm nuxt sh

# docに移動
/app # cd doc

# 必要なシンボリックリンクをはる
/app/doc # ln -s /app/src/assets/
/app/doc # ln -s /app/src/plugins/

/app/doc # exit

これでパスが解決されます。docを起動してみましょう。

# コンテナの中に入る
$ docker-compose run --rm --service-ports nuxt yarn run doc

http://localhost:9001 で表示されると思います。

まとめ

Storybookを使わずにコンポーネントカタログページを作成することができました!

ただ、カタログデザインのテンプレートを作っておかないと毎回作成することになってしまうので、テンプレートを作っておきましょう。

時間があれば、カタログページのデザインテンプレートもおいておきます。