Next.js / Sentry / Vercel の連携が楽になっていた件

4 min read読了の目安(約3900字 1

はじめに

Next.js でサービスを開発しており、エラー検知に使っている Sentry の SDKをアップデートしようとしたところ、以前に比べドキュメントが充実していて新しく @sentry/nextjs というパッケージが登場したことでかなり設定が楽になっていました。

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

Next.js のリポジトリ内にも設定のサンプルがあります。
(examples 内のコードは他にもいろいろと充実していて参考になります)

https://github.com/vercel/next.js/tree/master/examples/with-sentry

変更点

以前は @sentry/borwser @sentry/node @sentry/webpack-plugin @sentry/integrations を利用する必要があり、 next.config.js 内の設定も多く複雑でした。

こちらのコミットで新旧の設定が比較できます。

https://github.com/vercel/next.js/commit/4bc87e479ccb32f36a3f8ee7114362370434533a#diff-7944d4c272e9e4afb4e8164b3ca0a63525d16a47114527cb49f6187fbb6bf458

next.config.js 内では withSentryConfig を使うだけでよくなり、だいぶシンプルになりました。

アプリケーション側のコードでも utils/sentry.js というファイルを作り、 _app.js や API ルート内で init() を呼ぶ必要がありましたが、 @sentry/nextjs では sentry.client.config.jssentry.server.config.js というファイルを用意しそこで Sentry.init() が実行されるようになりました。

_app.js には修正が要らなくなりましたが、 API ルートではそれぞれを withSentry() という関数で囲う必要があります。

Vercel にデプロイする

Vercel と Sentry を連携するには Sentry Integration を使うと環境変数などの設定を数クリックで自動で行ってくれて大変便利です。

https://docs.sentry.io/product/integrations/vercel/

@sentry/nextjs の設定をし Vercel 上で確認しようとしたところ、プレビュー環境でのビルドに失敗しました。
Sentry の環境変数が Production にのみ設定されていたのが原因だったため、 Preview でも参照できるように設定を変更しました。

プロジェクト内に sentry.properties というファイルを作って設定することもできますが、せっかく Sentry Integration で環境変数を設定してくれるので SENTRY_AUTH_TOKEN を管理する必要がなくなるこの設定を選びました。

ローカル開発時にプラグインを除外する

@sentry/nextjs を設定すると、ローカル開発時は dryRun モードで動くため実際の sourcemap のアップロードは行われないのですが、コンソールにデバッグログが流れてしまうのが邪魔でした。

@sentry/nextjs が内部で使っている Sentry Webpack Pluginsilent: true というオプションもあるようなので設定してみたのですが動かず、色々試した結果ローカル開発時には withSentryConfig 自体を除外することにしました。

next.config.js 内で複数のプラグインをセットアップする必要がある場合は next-compose-plugins を使うのが便利です。
もともと next-transpile-modules を使っていたため、最終的に以下のような設定になりました。

追記: withPlugins の配列形式の第2引数に対応していなかったため silent: true を設定できませんでしたが、以下のように関数形式で渡せば出力を抑制できました。

https://github.com/cyrilwanner/next-compose-plugins/issues/50
next.config.js
const withPlugins = require("next-compose-plugins");
const { withSentryConfig } = require("@sentry/nextjs");

const withTM = require("next-transpile-modules")([ ... ]);

const nextConfig = { ... };

module.exports = withPlugins(
  [
      // Sentry Webpack Plugin のコンソール出力を抑制する
     (nextConfig) => withSentryConfig(nextConfig, { silent: true }),
    // (修正前) Vercel上でのみSentryのsourcemapをアップロード
    // ...(process.env.VERCEL ? [withSentryConfig] : []),
    withTM,
  ],
  nextConfig
);

ここで使っている process.env.VERCEL というのは Vercel 側で用意されている環境変数で、 利用するためにはプロジェクトの設定で Automatical expose System Environment Variables にチェックを入れる必要があります。

https://vercel.com/docs/environment-variables#system-environment-variables

Sentry の environment を設定する

Sentry のエラーを Slack などで通知している場合、 environment を設定しておくと通知設定などを分けられるので便利です。

sentry.client.config.jssentry.server.config.js を書き換えて、こちらも Vercel 側で用意されている環境変数を使い production preview development をセットするようにしました。

sentry.client.config.js
import * as Sentry from "@sentry/nextjs";

const SENTRY_DSN = process.env.SENTRY_DSN || process.env.NEXT_PUBLIC_SENTRY_DSN;
const SENTRY_ENVIRONMENT = process.env.VERCEL_ENV || process.env.NEXT_PUBLIC_VERCEL_ENV || "development";

Sentry.init({
  dsn: SENTRY_DSN,
  environment: SENTRY_ENVIRONMENT,
});

まとめ

Next.js で開発をしていると next.config.js の設定変更が必要になることがありますが、複雑になってくると設定が絡み合ってメンテナンスが難しくなってしまいます。
特に従来の Sentry の設定は複雑でしたが、 @sentry/nextjs に移行したことによって見通しがよくなりました。
Next.js / Sentry / Vercel の組み合わせは日々改善されて使いやすくなっており今後にも期待できそうです。