🗂

Next.jsv14にTableauダッシュボードを埋め込むタスクでハマったところと解決策

に公開

📝はじめに

Next.jsプロダクトにTableauダッシュボードを埋め込む際、EmbeddingAPIとTableauCloudのバージョン差異が原因でエラーが発生しました。
その原因と対応策に加え検討した代替案についてまとめます。


⚙️環境

-Next.js14.1.3(PageRouter)
-React18.3.0-TypeScript5.5.2
-TableauCloud(リージョン:prod-apnortheast-a,バージョン2025.1.0)
-@tableau/embedding-api-react3.12.0


🎯目的

弊社のプロダクトで営業職向けのツールを開発しているのですが、
より高度に営業レポートを分析したいというニーズがあったためBIツールを導入することになりました。
今回はBIツールはTableauを採用し、ユーザーが報告したデータをTableauで分析させるようにしました。


📌当初の実装方針

公式ドキュメントに従い、@tableau/embedding-api-reactを使用してReactコンポーネントとして埋め込む方法を採用していました。

import { TableauViz } from "@tableau/embedding-api-react";

export const SalesDashboard = () => (
  <TableauViz
    src="https://prod-apnortheast-a.online.tableau.com/t/my-site/views/Sales/Overview"
    token={PAT_OR_EMBED_TOKEN}
    toolbar="hidden"
  />
);

調査の段階では公式チュートリアルに載っているURLを使って動作確認をしていました。

https://help.tableau.com/current/api/embedding_api/en-us/tutorial/tutorial.htm

🐛トラブったこと

いざバックエンドから受け取ったURLを表示させようとした時に下記のようなエラー画面になってしまいました。

Error:incompatible-version-error:TheversionoftheEmbeddinglibraryisnotcompatiblewiththeversionofTableau.Thevisualizationwillload,buttheEmbeddingAPImethodsandeventsarenotavailable.

⚠️原因

エラーになる原因は、
TableauCloud(2025.1.0)と@tableau/embedding-api-react(3.12.0)のバージョンの不一致によるものでした。

Tableauが提供しているAPIは異なるバージョンとの互換性がないためにエラーとなってしまうようでした。

🌀ハマったこと

実はTableauのnpmパッケージのドキュメントに、このエラーについての警告が記載されています:

Warning:IfyourembeddedvizzesareinenvironmentswhereyoudonotcontrolthedeployedversionofTableau,likeTableauPublicorTableauCloud,itisrecommendedtoimporttheEmbeddingAPIlibraryfromtheserveritself—notinstallingitfromnpm—sincetheserverwillalwaysprovidethelatestcompatibleversion.

(出典:https://www.npmjs.com/package/@tableau/embedding-api-react)

つまり、TableauCloudやTableauPublicを使用する場合は、npmパッケージではなくサーバーから直接ライブラリを読み込むことが推奨されています

🧩バージョン不一致の詳細

調査の結果、以下のことが判明しました:

1.@tableau/embedding-api-reactの最新バージョン(3.12.0)は、TableauCloud北米版と互換性がある
2.しかし、アジア版(prod-apnortheast-a)とは互換性がなかった3.TableauCloudは北米版から段階的に他地域版のバージョンが更新される

このため、npmで提供されるパッケージは常に最新の北米版に対応しており他地域のTableauCloudとバージョンが合わないことがあります。


🔍対策の検討

この問題を解決するために、以下の3つの対策を検討しました:

1.@tableau/embedding-api-reactのバージョンを手動で調整

アジア版のTableauCloudのバージョンに合わせて、npmパッケージのバージョンを手動で下げる

{
  "dependencies": {
    "@tableau/embedding-api-react": "3.10.0" // 例:古いバージョンを指定
  }
}

問題点:

  • TableauCloudは自動でバージョンアップされるため、都度バージョンを確認・更新する必要がある
  • メンテナンスコストが非常に高い
  • 適切なバージョンを見つけるのが困難

2.@stoddabr/react-tableau-embed-liveを使用

サードパーティのReactラッパーライブラリを使用する方法

問題点:

  • メンテナンスされていない(最終更新が古い)
  • テストが不十分で動作の保証がない
  • 将来的なサポートに不安がある

3.Webコンポーネント(Tableau公式推奨)を利用する✅

Tableau公式が推奨する方法でサーバーから直接JSファイルを読み込んで使用

<script
  type="module"
  src="https://prod-apnortheast-a.online.tableau.com/javascripts/api/tableau.embedding.3.latest.min.js"></script>

メリット:

  • 常に使用しているTableauCloudのバージョンに対応したライブラリが読み込まれる
  • バージョン不一致の問題が発生しない
  • Tableau公式の推奨方法

採用理由:
最も安定した方法であるため、この方法を採用しました。


💻最終的な実装

Next.jsでWebコンポーネントを使用するための実装は以下のようになりました:

1.スクリプトを読み込む

Next.jsを採用しているプロジェクトなので、Scriptを使用

import Script from 'next/script';
const tableauScriptUrl = `${process.env.NEXT_PUBLIC_TABLEAU_BASE_URL}/javascripts/api/tableau.embedding.3.latest.min.js`;

~~~~~~~

 <Script type="module" src={tableauScriptUrl} />

2.TypeScript用の型定義を追加

/* eslint-disable @typescript-eslint/no-namespace */
declare global {
  namespace JSX {
    interface IntrinsicElements {
      'tableau-viz': React.DetailedHTMLProps<React.HTMLAttributes<HTMLElement>, HTMLElement> & {
        src?: string;
        token?: string;
        toolbar?: string;
        width?: string | number;
        height?: string | number;
      };
    }
  }
}

3TableauVizというtableau-vizを読み込ませるコンポーネント作成

// TableauViz.tsx
type Props = {
  id: string;
  src: string;
  token: string;
};

export const TableauViz = ({ id, src, token }: Props) => (
  <tableau-viz id={id} src={src} token={token} toolbar="top" />
);

これで表示させることができました。


📝まとめ

1.npmパッケージは北米版に最適化されているため、他地域のTableauCloudでは互換性の問題が発生する可能性がある
2.TableauCloudを使用する場合は、Webコンポーネントの使用が推奨される
3.地域別のTableauCloudのURLから直接ライブラリを読み込むことで、バージョン不一致を回避できる

この実装により、バージョン管理の手間なく安定したTableauダッシュボードの埋め込みが可能になりました。
チュートリアルで動作確認しただけで安心していましたが、公式に書いてある情報はちゃんと読もうと思いました。


🔗参考リンク

Discussion