Madogiwa Blog

主に技術系の学習メモに使っていきます。

Vue.js: Vueアプリケーション内で発生したエラーをRollbarに通知するメモ📝

個人のWebサービスのエラー通知にRollbarを利用しているのですが、以下の通りデフォルトではVueアプリケーション内で発生したエラー(コンポーネント内のロジックでエラーが起きたケース等)は通知されないことに今更気づき、通知されるようにしたので対応したことをメモ📝

Add Rollbar to Vue’s global error handler. Uncaught exceptions within the Vue app are sent to this handler, and appear in the browser console, but are not sent > to the browser’s global error handler. Adding Rollbar here ensures that these errors are reported. https://docs.rollbar.com/docs/vue-js

Rollbarへ通知するためのプラグインを追加

ほぼドキュメントの通りですが、app.config.errorHandlerを設定し、Vueアプリケーションでエラーが発生した場合にRollbarへの通知ロジックが実行されるようなPluginを用意して、

// NOTE: Rollbarにブラウザ側で発生したエラー通知を送る機能を有効化
// https://docs.rollbar.com/docs/browser-js

import Rollbar from "rollbar";
import type { App } from "vue";

const token = process.env.ROLLBAR_POST_CLIENT_ITEM_ACCESS_TOKEN;
const rollbarParamsValidation = () => !!(!(NODE_ENV === "test") && token);

const rollbar = new Rollbar({
  accessToken: token,
  captureUncaught: true,
  captureUnhandledRejections: true,
  enabled: rollbarParamsValidation(),
  payload: {
    environment: NODE_ENV,
  },
});

export default rollbar;

// NOTE: Vueアプリケーション内部のエラーをRollbarに通知するプラグイン
// https://docs.rollbar.com/docs/vue-js
export const VueRollbarPlugin = {
  install(app: App) {
    app.config.errorHandler = (error, _vm, info) => {
      // NOTE: 公式docでは以下となっていたが、おそらく送信時にvueComponentをjsonに変換するのにブラウザがフリーズするため送信しないようにした。
      // rollbar.error(error, { vueComponent: vm, info });
      rollbar.error(error as Error, { info });
      // NOTE: 本来はエラーをコンソールに出力するのは避けるべきだが、
      // エラー発生時にconsole.errorに表示しておいた方が確認しやすいため残している
      // eslint-disable-next-line no-console
      console.error(error);
    };
    app.provide("rollbar", rollbar);
  },
};

Pluginの有効化

以下のようにcreateApp時にuseして有効化するようにしました。

import NavigationBar from "@js/components/organisms/NavigationBar.vue";
import { VueRollbarPlugin } from "@js/services/Rollbar";
import { createApp } from "vue";

const app = createAppWithDefault({ components: { NavigationBar } });
app.use(VueRollbarPlugin);
app.mount("#vue-header");

また、毎回これを書くのはめんどくさそうに思ったのでcreateAppWithDefaultを定義して、

import { createApp, type CreateAppFunction } from "vue";
import { VueRollbarPlugin } from "./Rollbar";
type VueCreateAppType = CreateAppFunction<Element>;

export const createAppWithDefault: VueCreateAppType = (...args: Parameters<VueCreateAppType>) => {
  const app = createApp(...args);
  app.use(VueRollbarPlugin);
  return app;
};

以下のように利用するとcreateApp後に自動的にuseするようにしました。

import NavigationBar from "@js/components/organisms/NavigationBar.vue";
import { createAppWithDefault } from "@js/services/Vue";

const app = createAppWithDefault({ components: { NavigationBar } });
app.mount("#vue-header");

おまけ:Sentryのケース

Sentryの場合には、@sentry/vueが提供されていてDocumentの通りに設定すると自動的にapp.config.errorHandlerをよしなに設定してくれるっぽかった。

https://docs.sentry.io/platforms/javascript/guides/vue/