こんにちはー、ニアです!
自分のポートフォリオはフレームワークにVue.jsを使っているのですが、先日にポートフォリオの更新のついでに、Vue.jsのバージョンを2(以下、Vue 2)から3(以下、Vue 3)にアップデートしました。
1. Vue 2はサポート終了済み! Vue 3にアプデする? それともReact?
Vue 2は、2023年末にサポートが終了していたので、セキュリティの観点からアップデートなどの対応が必要でした。
業務では、フロントエンドの開発で主にReactやNext.jsを使っているので、プログラミングの復習も兼ねてReactにする案もありましたが、別の案件でVue.jsを使うことになった時に取り掛かりやすいように、自分のポートフォリオではVue.jsを引き続き使い、Vue 3にアップデートすることにしました。
ついでにビルドツールもVue CLIからViteに変更しました。もちろん、Vercelでのビルド&デプロイに利用できます。
自分のポートフォリオでも、高速化を体感できました
2. Let’s Vue 3にアップデート
Vue 3へのアップデートとViteへの変更は、以下のように作業をしました。
- Vue.jsなどのライブラリをアップデート、Viteをインストール
- Viteのコマンドラインツールで、新しいVue.jsのプロジェクトを作成
- Viteでのビルド必要なファイルを、ポートフォリオのプロジェクトにコピー
- コンポーネントなどのソースコードをVue 3用に修正
2.1. Vue 3では、Composition APIを使って、コンポーネントを記述
Vue 2の頃は、Vue Class ComponentとVue Property Decoratorを使って、コンポーネントを記述していました。
<template>
<tr>
<td>{{ name }}</td>
<td>{{ skillGradeStar }}</td>
</tr>
</template>
<script lang="ts">
import { Component, Prop, Vue } from 'vue-property-decorator';
export interface SkillItem {
name: string;
skillGrade: number;
}
@Component
export default class SkillListItem extends Vue {
@Prop()
private name!: string;
@Prop()
private skillGrade!: number;
get skillGradeStar() {
let adjustSkillGrade = Math.min( 5, Math.max( 1, this.skillGrade ) );
return "★".repeat( adjustSkillGrade ) + "☆".repeat( 5 - adjustSkillGrade );
}
}
</script>
Vue 3では、Composition APIを使って記述し、プロパティは defineProps()
で定義し、getterの部分は、computed()
で定義しました。
<script setup lang="ts">
import {computed} from "vue";
export interface SkillItem {
name: string
skillGrade: number
}
const props = defineProps<SkillItem>();
const skillGradeStar = computed(() => {
let adjustSkillGrade = Math.min( 5, Math.max( 1, props.skillGrade ) )
return "★".repeat( adjustSkillGrade ) + "☆".repeat( 5 - adjustSkillGrade )
})
</script>
<template>
<tr>
<td>{{ name }}</td>
<td>{{ skillGradeStar }}</td>
</tr>
</template>
あと、Viteではプロジェクト直下にあるindex.htmlを読み込む仕様なので、index.htmlをプロジェクト直下に移動しました。
3. Vue 3にアップデート&Viteに変更で遭遇したトラブル
3.1. Viteでビルドすると、「URI malformed」のエラーが発生する
これはindex.htmlに設定していた、ファビコンのURIに「<%= BASE_URL %>
」が含まれていたのが原因でした。
ファビコンはビルド時にindex.htmlと同じディレクトリに配置されるので、URIから「<%= BASE_URL %>
」を取り除き、解決しました。
<!-- Viteでビルドするとエラーになる -->
<link rel="icon" href="<%= BASE_URL %>favicon.ico">
<!-- 修正後 -->
<link rel="icon" href="/favicon.ico">
3.2. 画面に何も表示されない(ビルドしても、JavaScriptが出力されない)
Vue CLIの場合は、ビルド時に出力されたindex.htmlに、ビルドされたJavaScriptファイルを読み込む <script>
タグが自動的に挿入されます。
Viteの場合は、index.htmlに エントリポイントのTypeScriptファイルを読み込む <script>
タグを明示的に入れる必要があります。
<script type="module" src="/src/main.ts"></script>
3.3. <router-link> の tag プロパティは利用不可 → 必ず <a> タグがレンダリングされる
ナビゲーションメニューには、<ul>
タグの中に入れた <router-link>
の tag
プロパティを li
にセット( <li>
タグがレンダリングされる)して構成していました。
<ul>
<router-link tag="li"> ... </router-link>
<router-link tag="li"> ... </router-link>
...
</ul>
しかし、Vue 3用のvue-router(バージョン4)の <router-link>
では、tag
プロパティがオミットされてしまい、必ず <a>
タグがレンダリングされるようになったので、<ul>
タグを <nav>
タグに変更し、CSSを修正して、なんとか以前のレイアウトを復元しました。
<nav>
<router-link> ... </router-link>
<router-link> ... </router-link>
...
</nav>
デバッグし始めた頃は、表示がかなり崩れていました(汗)
4. おわりに
修正がちょっと大変でしたが、無事にポートフォリオのVue.jsのアップデート作業を完了できました。
ちなみにViteはVue.jsの他にReactでも利用できるので、今後新たにReactを使用する機会がある時にも効率よく開発できそうです。
[END]