サードパーティ JavaScript ライブラリの使用

サードパーティ JavaScript ライブラリを使用する前に、AppExchange で要件を満たすサードパーティアプリケーションを確認することをお勧めします。または、基本コンポーネントで目的の機能を実現できるかどうかを確認してください。

Tip

Lightning Web コンポーネントでは、サードパーティの JavaScript ライブラリを使用できます。たとえば、対話型グラフでライブラリを使用したり、コードを簡素化するライブラリを使用したりします。

  1. サードパーティライブラリのサイトからライブラリをダウンロードします。

  2. ライブラリを自分の Salesforce 組織に静的リソースとしてアップロードします。これは、Lightning Web コンポー���ントのコンテンツセキュリティポリシーの要件です。

  3. LightningElement を拡張する JavaScript クラスで以下を実行します。

    • ライブラリをその静的リソース名でインポートします。

      import RESOURCE_NAME from "@salesforce/resourceUrl/RESOURCE_NAME";

    たとえば、静的リソースの名前が myLib の場合は次のようになります。

    import myLib from "@salesforce/resourceUrl/myLib";
    • platformResourceLoader モジュールからメソッドをインポートします。

      import { loadStyle, loadScript } from "lightning/platformResourceLoader";

    lightning/platformResourceLoader リファレンスドキュメントを参照してください。

  4. ライブラリを読み込んで、その関数を then() メソッドでコールします。

    loadScript(this, myLib + "/myLib.js").then(() => {
      let result = myLib.myFunction(2, 2);
    });

Lightning Web セキュリティ (LWS) が有効になっていない組織でコンポーネントが実行されている場合、コンポーネントで使用するライブラリは Lightning Locker 要件を満たす必要があります。「JavaScript ライブラリが Locker 準拠かどうかの確認」を参照してください。組織で Lightning Web セキュリティ (LWS) が使用されている場合、ほとんどのサードパーティライブラリは変更なしに期待どおり機能します。ただし、一部のライブラリは、LWS を利用するための変更が必要です。「LWS に対するサードパーティライブラリの考慮事項」を参照してください。

Important

JavaScript での DOM の操作 

JavaScript を使用した DOM の操作はお勧めしません。Lightning Web Components の方がより効率よく操作できるためです。ただし、DOM の操作を引き受けるサードパーティの JavaScript ライブラリもあります。

Salesforce では、サードパーティ JavaScript ライブラリに対するサポートを提供していません。サードパーティ JavaScript ライブラリの使用方法を示したドキュメントや例は、サードパーティ JavaScript ライブラリを推奨するものではありません。使用方法については、サードパーティ JavaScript ライブラのドキュメントを確認することをお勧めします。

Note

appendChild() へのコールで DOM を操作する場合、付加された要素にはスタイルは適用されません。

これらのライブラリを Lightning Web コンポーネントで使用する場合は、JavaScript で操作したい HTML 要素に lwc:dom="manual" を追加してください。エンジンは、このディレクティブを検出するとカプセル化を維持します。

空白のネイティブ HTML 要素には lwc:dom="manual" ディレクティブを追加してください。コンポーネントのオーナーは、その要素に対して appendChild() をコールして、DOM を手動で挿入します。

<template>
  <div lwc:dom="manual"></div>
</template>

D3 コードは、lwc-recipes リポジトリの libsD3 コンポーネントです。

Tip

例: D3 JavaScript ライブラリ 

コンポーネントは、D3 JavaScript ライブラリを使用してデータを対話的に視覚化します。

カラードットを線で繋いだグラフを表示するコンポーネント。ドットをクリックしてドラッグすることで、グラフの形状を変更できます。

d3js.com から D3 をダウンロードします。d3.zip を静的リソースとして Salesforce 組織にアップロードします。

まず、マップを含むコンポーネントを作成します。コンテナ <svg> は空です。lwc:dom="manual" ディレクティブは、<svg> 要素の DOM が手動で挿入されたことを LWC に伝えています。

<!-- libsD3.html -->
<template>
  <div class="slds-m-around_medium">
    <svg class="d3" width={svgWidth} height={svgHeight} lwc:dom="manual"></svg>
  </div>
</template>

コンポーネントの JavaScript クラスで、lightning/platformResourceLoader から loadStyleloadScript をインポートします。d3 静的リソースもインポートします。D3 はリソースを読み込むための静的リソース参照であり、d3 は Salesforce にアップロードされた静的リソースの名前です。

グラフを作成するため、初回の表示時に loadStyleloadScriptrenderedCallback() で呼び出します。renderedCallback() により、グラフの作成前にページがコンテナを呼び出して表示することが保証されます。

loadStyleloadScript をコールすることで、promise が返されます。Promise.all() を使用すると、��果が集約され、コールバックの呼び出し前に両方のファイルが解決されることが保証されます。then() コールバックは、読み込みの完了後に、エラーが発生していない場合にのみ呼び出されます。読み込みプロセスで発生する潜在的なエラーを処理するための catch() コールバックを使用することもできます (省略可能)。

promise コールバックでグラフを初期化するには、initializeD3() をコールします。このメソッドは、DOM 内部にアクセスして、グラフを表示するコンテナ (ここでは <svg> 要素) への参照を取得します。

// libsD3.js
/* global d3 */
import { LightningElement } from "lwc";
import { ShowToastEvent } from "lightning/platformShowToastEvent";
import { loadScript, loadStyle } from "lightning/platformResourceLoader";
import D3 from "@salesforce/resourceUrl/d3";
import DATA from "./data";

export default class LibsD3 extends LightningElement {
  svgWidth = 400;
  svgHeight = 400;

  d3Initialized = false;

  renderedCallback() {
    if (this.d3Initialized) {
      return;
    }
    this.d3Initialized = true;

    Promise.all([loadScript(this, D3 + "/d3.v5.min.js"), loadStyle(this, D3 + "/style.css")])
      .then(() => {
        this.initializeD3();
      })
      .catch((error) => {
        this.dispatchEvent(
          new ShowToastEvent({
            title: "Error loading D3",
            message: error.message,
            variant: "error",
          }),
        );
      });
  }

  initializeD3() {
    // Example adopted from https://bl.ocks.org/mbostock/2675ff61ea5e063ede2b5d63c08020c7
    const svg = d3.select(this.template.querySelector("svg.d3"));
    const width = this.svgWidth;
    const height = this.svgHeight;
    const color = d3.scaleOrdinal(d3.schemeDark2);

    const simulation = d3
      .forceSimulation()
      .force(
        "link",
        d3.forceLink().id((d) => {
          return d.id;
        }),
      )
      .force("charge", d3.forceManyBody())
      .force("center", d3.forceCenter(width / 2, height / 2));

    const link = svg
      .append("g")
      .attr("class", "links")
      .selectAll("line")
      .data(DATA.links)
      .enter()
      .append("line")
      .attr("stroke-width", (d) => {
        return Math.sqrt(d.value);
      });

    const node = svg
      .append("g")
      .attr("class", "nodes")
      .selectAll("circle")
      .data(DATA.nodes)
      .enter()
      .append("circle")
      .attr("r", 5)
      .attr("fill", (d) => {
        return color(d.group);
      })
      .call(d3.drag().on("start", dragstarted).on("drag", dragged).on("end", dragended));

    node.append("title").text((d) => {
      return d.id;
    });

    simulation.nodes(DATA.nodes).on("tick", ticked);

    simulation.force("link").links(DATA.links);

    function ticked() {
      link
        .attr("x1", (d) => d.source.x)
        .attr("y1", (d) => d.source.y)
        .attr("x2", (d) => d.target.x)
        .attr("y2", (d) => d.target.y);
      node.attr("cx", (d) => d.x).attr("cy", (d) => d.y);
    }

    function dragstarted(d) {
      if (!d3.event.active) {
        simulation.alphaTarget(0.3).restart();
      }
      d.fx = d.x;
      d.fy = d.y;
    }

    function dragged(d) {
      d.fx = d3.event.x;
      d.fy = d3.event.y;
    }

    function dragended(d) {
      if (!d3.event.active) {
        simulation.alphaTarget(0);
      }
      d.fx = null;
      d.fy = null;
    }
  }
}

Lightning Web コンポーネントでは、document を使用して DOM 要素に対するクエリを実行することはできません。代わりに、this.template を使用します。この D3 コード例では、this.template.querySelector('svg.d3') を使用しています。「DOM のアクセスコンテインメント」を参照してください。

Note

便利なパターン 

コードを読み込むための便利なパターンを紹介します。このコードは、CSS ファイルなしで JavaScript ライブラリを読み込みます。

loadScript(this, RESOURCE_NAME + "/lib.js").then(() => {
  /* callback */
});

このコードは、複数の JavaScript ファイルを並列で読み込みます。

Promise.all([
  loadScript(this, RESOURCE_NAME + "/lib1.js"),
  loadScript(this, RESOURCE_NAME + "/lib2.js"),
  loadScript(this, RESOURCE_NAME + "/lib3.js"),
]).then(() => {
  /* callback */
});

関連トピック

The Japanese Summer '24 guide is now live

日本語の Summer '24 ガイドが公開されました! 「Component Reference (コンポーネントリファレンス)」は、以前と同様にコンポーネントライブラリにあります。