Nuxtでvue-axeを使おうとしたらダメだったのでaxe-coreを利用した話
はじめに
Nuxt に vue-axe を入れようとしたら動かなかったので、最終的に axe-core をそのまま利用した、というお話です。
vue-axe というのは、Vue プロジェクトの開発中にアクセシビリティをチェックできるライブラリです。
react-axe というライブラリにインスパイアされたライブラリだそうです。
公式のインストール手順では動かない
ドキュメント通り、以下のコードで設定を進めましたが、ダメでした。
import Vue from 'vue'
if (process.env.NODE_ENV === 'development') {
const VueAxe = require('vue-axe').default
Vue.use(VueAxe)
}
また GitHub の Issue に様々な方がコメントされていて試してみましたが、どれもダメでした。
(多くの方が VueAxePopup というコンポーネントを利用していますが、このコンポーネントが存在していないっぽい)
代替策: axe-core を直接利用する
vue-axe は Nuxt では使えなさそうなので、axe-core というライブラリを使います。
// 必要な部分のみ記載しています
// 開発環境でのみ動作するように設定
export default defineNuxtConfig({
plugins: [
{ src: '~/plugins/axe.client.ts', mode: 'client' }
],
vite: {
optimizeDeps: {
include: process.env.NODE_ENV === 'development' ? ['axe-core'] : []
},
},
})
plugins フォルダに axe.client.ts というファイルを作成し、以下のように記述します。(ファイル名は任意)
デフォルトの設定で処理をかけていますが、色々カスタマイズできます。詳しくはドキュメントを読んでみてください。
WCAG のレベルなども設定できるようで、驚きました。(2.0 なのか 2.1 なのか。A なのか AA なのか、など)
import { defineNuxtPlugin } from '#app';
export default defineNuxtPlugin(async (nuxtApp) => {
if (process.env.NODE_ENV === 'development') {
try {
const axeCore = await import('axe-core')
const results = await axeCore.default.run() // デフォルト設定で実行(参照:https://www.deque.com/axe/core-documentation/api-documentation/)
if (results.violations.length === 0) {
console.log('Congratulations! No accessibility issues found🎉');
} else {
console.log('a11y issues:', results.violations);
}
} catch (error) {
console.error('error running axe-core:', error)
}
}
});
実行してアクセシビリティを改善する
特に何も実装していない Nuxt 環境で実行してみたらうまく動いているようです!
具体的には、以下の項目で怒られているようです。
- タイトルタグがないよ!
- html タグに lang 属性がないよ!
- img タグに alt 属性がないよ!(この項目はテストのため故意に alt なし画像を置いたので出ています)
- main タグがないよ!
- ページ上のコンテンツがランドマーク領域に含まれてないよ!
良い感じにエラーを出してくれていますね。これらを修正します。
修正後
プロジェクトによって解決方法は違うと思いますので参考までに。
export default defineNuxtConfig({
app:{
head:{
title: 'サイトタイトル',
htmlAttrs: {
lang: 'ja'
}
}
}
})
<script setup lang="ts">
import AppHeader from "~/components/AppHeader.vue";
import AppFooter from "~/components/AppFooter.vue";
</script>
<template>
<NuxtRouteAnnouncer />
<NuxtLayout>
<AppHeader />
<main>
<NuxtPage />
</main>
<AppFooter />
</NuxtLayout>
</template>
無事解消できたようです!
まとめ
今回は Nuxt 環境で苦戦したので axe-core を利用しましたが、Vue プロジェクトであれば vue-axe をそのまま利用できるかもしれません。
また、Issue にはない他の方法で Nuxt 上でうまく vue-axe を利用できた方がいらっしゃいましたら教えていただけると嬉しいです!
もちろん Vue 以外の React や素の HTML などでも利用可能だと思うので、気になる方はぜひ導入してみてください。
参考文献
Discussion