続・Nuxt3の開発用テンプレート作ってみた(Docker/Vitest/Storybook対応)
はじめに
2022/08にrc版になったNuxt3の開発用テンプレートを作成しました。それから1年が経ち、周辺ライブラリが整ってきたため改めてテンプレートを拡張しようと思います。
成果物
是非「Use this template」からリポジトリを作って使ってみてください。
要所解説
Version等(今回追加した箇所を中心に要所のみ抜粋)
(nodeに関しては20系の最新版を使用しています)
{
<中略>
"devDependencies": {
"@nuxt/devtools": "^1.0.3",
"@vitest/coverage-v8": "^0.34.6",
"@vitest/ui": "^0.34.6",
"@vue/test-utils": "^2.4.1",
"jsdom": "^22.1.0",
"nuxt": "3.8.2",
"typescript": "^5.2.2",
"unplugin-auto-import": "^0.16.6",
"unplugin-vue-components": "^0.25.2",
"vite-plugin-vuetify": "^1.0.2",
"vitest": "^0.34.6",
"vuetify": "3.4.2"
}
<中略>
}
Docker対応
個人的にはdockerで立ち上げるのはバックエンドフレームワークだけでいいだろうと考えていましたが、いざ、dockerを構築してみると(たとえ本番環境へのデプロイには使わないとしても)やっぱり立ち上げが楽ですね。
まずはDockerfileから
FROM node:20-alpine3.17
ENV TZ Asia/Tokyo
WORKDIR /frontend
COPY package.json ./
続いてcompose.yml
version: '3.9'
x-common-settings: &common-settings
build: .
volumes:
- .:/frontend:cached
- nuxt-node-modules:/frontend/node_modules:delegated
tty: true
services:
dev_nuxt:
container_name: dev_nuxt
<<: *common-settings
ports:
- '3000:3000'
command: >
sh -c `
npm install &&
npm run dev
`
prod_nuxt:
container_name: prod_nuxt
<<: *common-settings
ports:
- '3001:3001'
command: >
sh -c `
npm install &&
npm run build &&
PORT=3001 node ./.output/server/index.mjs
`
storybook:
container_name: storybook
<<: *common-settings
ports:
- '6006:6006'
command: >
sh -c `
npm install &&
npm run storybook
`
vitest:
container_name: vitest
<<: *common-settings
command: npm run test --exit
volumes:
nuxt-node-modules:
下記設定の箇所で共通している設定をまとめています。各containerでは<<: *common-settings
と書いて呼び出します。
x-common-settings: &common-settings
build: .
volumes:
- .:/frontend:cached
- nuxt-node-modules:/frontend/node_modules:delegated
tty: true
まず、先述のDockerfileではRUN npm install
を行わず、compose.ymlでやっている理由ですが、DockerfileではRUN npm install
を行う場合、ライブラリの更新があった際に下記のようなコマンドを打つ必要があります(あくまで一例になります。実際にはやり方は何通りかあります)
docker compose run --rm dev_nuxt npm install
docker compose run --rm prod_nuxt npm install
個人開発なら問題ないのですが、(会社等で)複数人で開発している場合、PRをレビューする際に上記コマンドの打ち忘れが発生し得るのです。その度に
レビュワー「このPR動かないよ」
筆者「あ、今回ライブラリの更新があったので更新コマンド打ってください!」
レビュワー「了解〜」
みたいな問答をするのも手間です。
そのため、npm install
はcompose.ymlのcommandに設定しています。
下記記事を参考にさせていただきました。
Vitest対応
viteベースのvue環境だとvite.config.tsの中に書いたりもしますが、nuxtではnuxt.config.tsがあるのでtestに関する設定のみを書くvitest.config.tsを作成します。
happy-domを使うのも良かったんですが、安定性重視でjsdom採用としました。
エイリアスは必要に応じて追加してください。
あとはtest配下に.test.tsか.spec.tsのテストファイルを作成するだけです。
// <reference types="vitest">
import { defineConfig } from 'vitest/config'
import Vue from '@vitejs/plugin-vue'
import AutoImport from 'unplugin-auto-import/vite'
import Components from 'unplugin-vue-components/vite'
import { Vuetify3Resolver } from 'unplugin-vue-components/resolvers'
import { fileURLToPath } from 'node:url'
export default defineConfig({
plugins: [
Vue(),
AutoImport({
dirs: ['utils', 'composables'],
imports: ['vue', 'vue-router', 'vitest'],
dts: 'test/auto-imports.d.ts'
}),
Components({
dirs: ['components'],
resolvers: [Vuetify3Resolver()],
directoryAsNamespace: true,
dts: 'test/components.d.ts'
})
],
resolve: {
alias: {
'@': fileURLToPath(new URL('./', import.meta.url)),
'~': fileURLToPath(new URL('./', import.meta.url)),
}
},
test: {
root: '.',
globals: true,
environment: 'jsdom',
coverage: {
provider: 'v8',
enabled: true
}
}
})
Storybook対応
今回の更新作業の中で一番時間が掛かりました。。。
なぜ時間が掛かったのかの詳細は別記事を書くつもりなのでそちらに譲るとして、ここでは概要のみまとめます。
Storybookには基本的に公式から提供されている各フレームワーク用のライブラリがあります。
しかし、Nuxt3は唯一主要webフレームワークの中でStorybook公式ライブラリが提供されていません。
そのため、自力で環境をセットアップする必要があります。
↑こちらのライブラリを使うことにしました。
READMEを拝見するとStackbliz上で動くDemoも複数用意されています。(ありがたい)
そして入れてみてなんやかんやした結果、
- Nuxtのversionは最新だけどStorybookは入っていない「Nuxt3-template」repository
- Nuxtのversionは3.6.5止まりかつ、パッケージマネージャはpnpm限定だけどStorybookは動く「Nuxt3-template-with-storybook」repository
の二つに分けて管理することになりました。
以降「Nuxt3-template-with-storybook」においての話となります。
まずは設定ファイルからです。
元々vitestの設定と同じようにunplugin-auto-import
やunplugin-vue-components
を使ってこねくり回していましたが@storybook-vue/nuxt
を導入してからは必要なくなりました。
import type { StorybookConfig } from '@storybook-vue/nuxt'
const config: StorybookConfig = {
stories: [
'../stories/**/*.mdx',
'../stories/**/*.stories.@(js|jsx|ts|tsx)',
'../components/**/*.mdx',
'../components/**/*.stories.@(js|jsx|ts|tsx)',
],
addons: [
'@storybook/addon-links',
'@storybook/addon-essentials',
'@storybook/addon-interactions'
],
framework: {
name: '@storybook-vue/nuxt',
options: {}
},
docs: { autodocs: 'tag' }
}
export default config
import { type Preview } from '@storybook/vue3'
const preview: Preview = {
parameters: {
actions: { argTypesRegex: '^on[A-Z].*' },
controls: {
matchers: {
color: /(background|color)$/i,
date: /Date$/
}
}
}
}
export default preview
以上となります。
この記事で紹介した二つのテンプレートリポジトリは継続的にキャッチアップして更新していきますのでまた大きな変化があったら記事にまとめたいと思います。
Discussion