概要
Vue.jsでエラーハンドリングをどうしようか悩んでたときにerrorHandlerなるものがあることを知ったけれど、想定していた挙動と違って利用するのをやめた話。
参考にさせてもらった記事は以下です。感謝!
Vue.jsでフロント側のエラー検知を共通化する
http://sms-c-engineer.hatenablog.com/entry/2018/04/24/142445
GitHubに利用したプロジェクトをUPしています。実際に試してみたい方どうぞ^^
https://github.com/kai-kou/vue-js-typescript-error-handling
準備
ここではDockerを利用して環境構築していますが、ローカルで構築してもらってもOKです。
> mkdir 任意のディレクトリ > cd 任意のディレクトリ > vi Dockerfile > vi docker-compose.yml
Dockerfile
FROM node:10.8.0-stretch RUN npm install --global @vue/cli WORKDIR /projects
docker-compose.yml
version: '3' services: app: build: . ports: - "8080:8080" volumes: - ".:/projects" tty: true
> docker-compose up -d > docker-compose exec app bash
コンテナ内
> vue create app Vue CLI v3.0.1 ? Please pick a preset: Manually select features ? Check the features needed for your project: Babel, TS, Vuex, Linter ? Use class-style component syntax? Yes ? Use Babel alongside TypeScript for auto-detected polyfills? Yes ? Pick a linter / formatter config: TSLint ? Pick additional lint features: Lint on save ? Where do you prefer placing config for Babel, PostCSS, ESLint, etc.? In dedicated config files ? Save this as a preset for future projects? No ? Pick the package manager to use when installing dependencies: (Use arrow keys) ❯ Use Yarn Use NPM
コンテナ内
> cd app > yarn serve
これで環境が整いました。
検証
errorHandlerを利用してエラー検知できるようにします。
src/main.ts
import Vue from 'vue'; import App from './App.vue'; import store from './store'; Vue.config.productionTip = false; Vue.config.errorHandler = (err, vm, info) => { console.log('error!!!'); console.log(err); console.log(vm); console.log(info); }; new Vue({ store, render: (h) => h(App), }).$mount('#app');
App.vueのtemplate内でエラー発生させてみます。
src/App.vue
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png"> <!-- HelloWorldをHelloWorld2に変更してエラー --> <HelloWorld2 msg="Welcome to Your Vue.js + TypeScript App"/> </div> </template> (略)
どうなるか、ブラウザで確認してみます。
errorHandlerにひっかからず、ブラウザでエラー発生がされてしまいました。
App.vueのscript内でエラーを発生させてみます。
src/App.vue
(略) <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import HelloWorld from './components/HelloWorld.vue'; @Component({ components: { HelloWorld, }, }) export default class App extends Vue { private created() { throw new Error('hoge'); } } </script> (略)
ブラウザで確認します。
こちらはerrorHandlerにひっかかりました。
お次はHelloWorldコンポーネントのtemplate内でエラーを発生させてみます。
src/components/HelloWorld.vue
<template> <div class="hello"> <!-- msgをmsg2に変更してエラー --> <h1>{{ msg2 }}</h1> (略)
ブラウザで確認します。
これもerrorHandlerで拾ってくれず。
templateで発生するエラーに関しては拾えなさそうです。
次にVuexを利用してStoreを実装してみます。
実装は下記の記事を参考にしています。
VuexをTypeScriptで利用するのに悩んだ
https://cloudpack.media/42966
src/store.ts
import Vue from 'vue'; import Vuex from 'vuex'; Vue.use(Vuex); interface State { conuter: number; } export default new Vuex.Store({ state: { conuter: 0, } as State, getters: { getCounter: (state, getters) => () => { return state.conuter; }, }, mutations: { increment(state, payload) { state.conuter += 1; }, }, actions: { incrementAction(context) { context.commit('increment'); }, }, });
App.vueで利用できるようにします。
src/App.vue
<template> <div id="app"> <img alt="Vue logo" src="./assets/logo.png" @click="increment"> <HelloWorld :msg="`Welcome to Your Vue.js + TypeScript App ${this.counter}`"/> </div> </template> <script lang="ts"> import { Component, Vue } from 'vue-property-decorator'; import HelloWorld from './components/HelloWorld.vue'; @Component({ components: { HelloWorld, }, }) export default class App extends Vue { private get counter(): number { return this.$store.getters.getCounter(); } private increment(): void { this.$store.dispatch('incrementAction'); } } </script> (略)
これで、画像をクリックすると「TypeScript App」の後ろにある数字がカウントアップするようになりました。
storeのgetters
にエラーを仕込んでみます。
src/store.ts
(略) getters: { getCounter: (state, getters) => () => { throw new Error('hoge'); return state.conuter; }, }, (略)
ブラウザで確認しています。
errorHandlerでエラーを拾ってます。
続いてmutations
に仕込みます。
src/store.ts
(略) mutations: { increment(state, payload) { throw new Error('hoge'); state.conuter += 1; }, }, (略)
ブラウザで確認しています。
むむ。errorHandlerで拾ってくれません。
続いてactions
に仕込みます。
ブラウザで確認しています。
むむむ。拾ってくれません。
うーん。Vue.config.errorHandler
利用方法の理解がそもそも間違っているのかもしれませんが、template内のエラーはともかく、mutations
やactions
で発生したエラーは検知してほしい。。。
最終的に拾いきれてないエラーを検知するのに利用できるかなと期待していたのですが、ひとまず、思っていたのと違うぞってことがわかりました。
参考
Vue.jsでフロント側のエラー検知を共通化する
http://sms-c-engineer.hatenablog.com/entry/2018/04/24/142445
API — Vue.js#errorHandler
https://jp.vuejs.org/v2/api/index.html#errorHandler
Vue.js+TypeScriptで開発するときの参考記事まとめ
https://cloudpack.media/43084