vitePressでもいいのですが、基本を勉強しようとVue3とViteSSGを使って静的ページの生成をやります。
目的
- WebpackやViteでMarkdownからHTMLの書き出しをしてたのでVueでもやりたい
- hostingサービスで使えるページを生成
- LPやコーポレートサイトにVueの便利さを追加したい
- コンポーネントを使いまわしたい
- ページのロード遅延を少なくしたい
- 画像やCSSの圧縮したい
参考
Node
node -v 22.2.0
クイックスタートでvue3を開始
npm create vue@latest
ターミナルの指示に従って適切な環境を作成する。
個人的には以下。
✔ Project name: … vue-project
✔ Add TypeScript? … Yes
✔ Add JSX Support? … No
✔ Add Vue Router for Single Page Application development? … Yes
✔ Add Pinia for state management? … No
✔ Add Vitest for Unit Testing? … No
✔ Add an End-to-End Testing Solution? › No
✔ Add ESLint for code quality? … No
✔ Add Vue DevTools 7 extension for debugging? (experimental) … No
- TSは使いたい
- vue構文で記述するのでJSXは不要
- 下層ページを作るのでvue-routerは必要
- データ保存が必要な場合は、SSGしないのでPiniaは不要
- 簡単なページなので、テストは不要。複雑な場合は必要
- ESlintは後で独自にいれるので不要
- DevToolsはどっちでもいいが、Pinia使ってないしSSGだけなら不要
ESLintとPrettierとVSCode
VScodeのESLintが保存時に遅延して保存できないissueがあるので、無効化した。
代わりにRun on Save
で保存時にpackage.jsonのnpm run lint
を実行する。
packageのアップロード(注意)
npm-check-updates
で全部のpackageをアップロードする。ESLint8から9への更新は注意する
ncu
以下の更新がある
@rushstack/eslint-patch ^1.8.0 → ^1.10.4
@types/node ^20.14.5 → ^22.5.4
@vitejs/plugin-vue ^5.0.5 → ^5.1.3
eslint ^8.57.0 → ^9.10.0
eslint-plugin-vue ^9.23.0 → ^9.28.0
npm-run-all2 ^6.2.0 → ^6.2.2
prettier ^3.2.5 → ^3.3.3
typescript ~5.4.0 → ~5.6.2
vite ^5.3.1 → ^5.4.4
vue ^3.4.29 → ^3.5.4
vue-router ^4.3.3 → ^4.4.4
vue-tsc ^2.0.21 → ^2.1.6
Run ncu -u to upgrade package.json
ESLint9への更新
ESLint8からESLint9は破壊的な更新なので、注意。ESLint10にflat構文が基準になるので、新しくサービスを作成するならESLint9を勉強しておく
typescriptは5.4で止めとく
@typescript-eslint/typescript-estree.
がWARNINGを出す
WARNING: You are currently running a version of TypeScript which is not officially supported by @typescript-eslint/typescript-estree.
You may find that it works just fine, or you may not.
SUPPORTED TYPESCRIPT VERSIONS: >=4.7.4 <5.6.0
typescript5.6にupgradeした場合、npmでは削除してから入れ直す
npm rm typescript
npm i -D typescript@5.4
ESLint9のセットアップ
npm init @eslint/config@latest
ターミナルの指示に従って適切な環境を作成する。
個人的には以下。
✔ How would you like to use ESLint? · problems
✔ What type of modules does your project use? · esm
✔ Which framework does your project use? · vue
✔ Does your project use TypeScript? · typescript
✔ Where does your code run? · browser, node
The config that you've selected requires the following dependencies:
eslint, globals, @eslint/js, typescript-eslint, eslint-plugin-vue
✔ Would you like to install them now? · No / Yes
✔ Which package manager do you want to use? · npm
eslint.config.js
が作成される。eslint.config.ts
と変更してts化。
vueのセットアップで作成された、.eslintrc.cjs
があったら不要なので削除。eslint-plugin-vue
や他のpackageがセットアップ時にはいるので@vue/eslint-config-prettier
や@vue/eslint-config-typescript
も不要になる。あるとESLint9をサポートしてないので、Errorになる
run lintの追加
"lint": "eslint --fix 'src/**/*.{js,ts,vue}'"
src配下のファイルだけlintをかける
WARNINGが出た場合には、上記のtsのダウングレードする
firebase の設定(任意)
hostingだけなので、パッケージのインストールはない
firebase init
ViteSSGなのでFrameworkは使用しない
hostuingを選択して、projectを選択
チームメンバーがいるならgithubワークフローも追加
viteのbuildはdistフォルダに追加されるのでfirebase.json
を書き換える
{
"hosting": {
"public": "dist",
"ignore": [
"firebase.json",
"**/.*",
"**/node_modules/**"
]
}
}
パッケージインストールしてvueの起動を確認
npm install
npm run dev
viteSSGと便利なPlugin追加
npm i -D vite-ssg
npm i -D vite-plugin-vue-layouts vite-plugin-pages unplugin-vue-router unplugin-vue-markdown critters @unhead/vue vue-gtag vite-ssg-sitemap autoprefixer vite-plugin-compression vue-cookie-accept-decline @macropygia/vite-plugin-imagemin-cache
vite-plugin-vue-layouts // unheadのmetaでlayout設定
vite-plugin-pages // pagesフォルダ内のファイルをpageComponentとして設定
unplugin-vue-router // viteSSGのvue-routerのErrorを解消
unplugin-vue-markdown // Markdownを使えるように
critters // inline CSS化
@unhead/vue // metaタグをpageコンポーネントから設定
vue-gtag // Analyticsの追加
vite-ssg-sitemap // サイトマップの自動生成
autoprefixer // 言わずもがな
vite-plugin-compression // gzip圧縮
@macropygia/vite-plugin-imagemin-cache // 画像圧縮
vue-cookie-accept-decline // GDPR対応
viteSSGとPluginの設定
READMEを見ながら始める
https://github.com/antfu-collective/vite-ssg
packageのbuildをvitSSGに変更
"build-only": "vite-ssg build",
main.tsのcreateAppをViteSSGに変更。typesは適切に追加
import './assets/main.css'
import { ViteSSG } from 'vite-ssg'
import App from './App.vue'
import { setupLayouts } from 'virtual:generated-layouts'
import { routes } from 'vue-router/auto-routes'
import VueGtag from 'vue-gtag'
import { createHead } from '@unhead/vue'
import VueCookieAcceptDecline from 'vue-cookie-accept-decline'
const ga = 'G-XXXXXXXXXXXXXXX'
export const createApp = ViteSSG(
App,
{ routes: setupLayouts(routes) },
({ app, router, routes, isClient, initialState }) => {
app.use(VueGtag, {
config: { id: ga, },
}, router),
createHead(),
app.component('vue-cookie-accept-decline',
VueCookieAcceptDecline)
},
)
import { fileURLToPath, URL } from 'node:url'
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import ViteSSGOptions from "vite-ssg";
import VueRouter from 'unplugin-vue-router/vite'
import Layouts from 'vite-plugin-vue-layouts';
import Pages from 'vite-plugin-pages'
import generateSitemap from 'vite-ssg-sitemap'
import imageminPlugin from '@macropygia/vite-plugin-imagemin-cache'
import viteCompression from 'vite-plugin-compression';
import Markdown from 'unplugin-vue-markdown/vite'
import autoprefixer from 'autoprefixer'
const hostname = "https://example.com";
// https://vitejs.dev/config/
export default defineConfig({
plugins: [
VueRouter(),
vue(),
Layouts(),
Pages(),
Markdown({}),
imageminPlugin(),
viteCompression(),
],
css: {
devSourcemap: true,
postcss: {
plugins: [
autoprefixer({}),
]
}
},
ssgOptions: {
dirStyle: "nested",
script: "async",
formatting: "minify",
format: "esm",
onFinished: () => {
generateSitemap({
hostname: hostname,
exclude: []
})
},
crittersOptions: {
preload: 'media',
},
},
resolve: {
alias: {
'@': fileURLToPath(new URL('./src', import.meta.url))
}
}
})
<script setup lang="ts">
import { RouterView } from 'vue-router'
</script>
<template>
<router-view v-slot="{ Component, route }">
<component :is="Component" :key="route" />
</router-view>
</template>
ここまで設定したら、buildしてみる。hostingで動くかも確認
npm run build
以上で基本的な設定は終了です。
ViteSSGはabout/index.vue
をabout.html
変換するので、dirStyle: "nested",
を追加すると、about.vue
やabout/index.vue
をabout/index.vue
に書き出してくれる。