TypeScript ベースの VuePress 2 に更新する
💇‍♀️

TypeScript ベースの VuePress 2 に更新する

#Vue#VuePress#TypeScript#YouTube

By jiyuujin at

製作・運用しているウェブサイトの VuePress のバージョンを 2 系に上げた。

これは Flutter 日本ユーザグループ (大阪) のドキュメントサイトで、主にハンズオンやミートアップ等で開発者と技術情報を共有するため 2 年前に開設した。

docs/.vuepress/config.ts でナビゲーションバー並びにサイドバーの設定を書く。これは VuePress 1 系と比べて書き方は一切変わらないので今回は割愛させていただく。

VuePress 2 の特長

VuePress は Markdown をベースに書ける静的サイトジェネレータで適宜 Vue コンポーネントを使ってカスタマイズできる。

この度 VuePress 2 最大の特徴として型安全に書けるようになったことを挙げる。

※ VuePress 2 は 8 月 3 日現在 α 版です。

  • TypeScript で書けるようになった
  • Vue 3 で書けるようになった
  • webpack 5 サポート

このように TypeScript で書けるのと同時に Vue 3 でも書けるようになった。

::: message is-primary

これまでの Vue 2 系の書き方ではなく createApp で生成された app インスタンスに対し use を使ってプラグインを注入して書けば良い。

  • Vue コンポーネントを読み込む
  • サードパーティ製プラグインを読み込む
import { defineClientAppEnhance } from '@vuepress/client'

import Example from './components/Example.vue'

export default defineClientAppEnhance(({ app, router, siteData }) => {
  app.component('Example', Example)
})

:::

また内部的に Vite が入っており体感的にビルド速度が速くなった。

TypeScript で書けるようになった

docs/.vuepress/config.ts でウェブサイトの設定を書く。

かつて JavaScript で書いた設定を defineUserConfig<DefaultThemeOptions> という型定義の下で書けるようになった。

import { defineUserConfig } from 'vuepress'
import type { DefaultThemeOptions } from 'vuepress'

export default defineUserConfig<DefaultThemeOptions>({
  //
})

meta 周りの書き方で VuePress 1 系と違う点が存在しハマった。

lib/types/head.d.ts を見ると、第 1 引数にヘッダタグを必ず追加する必要がある。

  • CSS を読み込む際に link を追加する
  • JavaScript を読み込む際に script を追加する
export declare type HeadConfig = [HeadTagEmpty, HeadAttrsConfig] | [HeadTagNonEmpty, HeadAttrsConfig, string];

export declare type HeadTagNonEmpty = 'title' | 'style' | 'script' | 'noscript' | 'template';

export declare type HeadTagEmpty = 'base' | 'link' | 'meta' | 'script';

export declare type HeadAttrsConfig = Record<string, string | boolean>;

この規則を頭に入れておけばハマる心配も無くなる。

  head: [
    [
      `meta`,
      {
        hid: `title`,
        name: `title`,
        content: `<TITLE>`
      }
    ],
    [
      `meta`,
      {
        hid: `description`,
        name: `description`,
        content: `<DESCRIPTION>`
      }
    ],
  ]

その他ハマった点

先述の Vue 3 について、これまで使えていたプラグインが使えなくなることもある。

Flutter 日本ユーザグループのウェブサイトでは YouTube の配信動画を埋め込むため vue-youtube というプラグインを利用している。

しかし VuePress 2 ではそのプラグインが動かない。

それもそのはず、まだ Vue 3 に対応していないため。

<template>
  <YouTube :video-id="videoId" :player-vars="playerVars" />
</template>

<script>
import YouTube from 'vue-youtube'

export default {
  components: {
    YouTube
  },
  props: {
    videoId: {
      type: String,
      default: ''
    }
  },
  data() {
    return {
      playerVars: {
        origin: `${location.protocol}//${location.hostname}/`
      }
    }
  }
}
</script>

そこで Vue 3 に対応しているプラグイン (があったので、それ) に乗り換えた。

先の vue-youtube と違い YouTube URL を引数にして渡している。

<template>
  <YouTube :src="`https://www.youtube.com/watch?v=${videoId}`" @ready="onReady" ref="youtube" />
</template>

<script lang="ts">
import YouTube from 'vue3-youtube'

export default {
  components: {
    YouTube
  },
  props: {
    videoId: {
      type: String,
      default: ''
    }
  },
  methods: {
    onReady() {
      this.$refs.youtube.playVideo()
    }
  }
}
</script>

あくまで違う方が開発されておりこの辺りの仕様が違っている点は仕方ありません。