Posted at

複数のコンポーネントから同じJavaScriptライブラリーを使う方法

More than 3 years have passed since last update.


Loader componentについて

Lightningコンポーネントを作っていて誰しもこれどうするのかなーと思うのが、外部JavaScriptライブラリーを良い感じに読み込む方法で、私もRequireJSコンポーネントを使ったLightningコンポーネントの部品化という記事を書きましたし、Qiitaでも他の方の記事も見られます。

さて、Lightning FAQを改めて読むと、何やら記述があります。


Q: 外部JavaScriptライブラリを組み込むにはどうしたら良いでしょうか?

A: RequireJSコンポーネントもしくはLoader component (https://github.com/rajaraodv/loadcomponent) を使って、

外部のJSやCSSファイルを組み込むことが可能です。


RequireJSは冒頭の記事に書いた通りで、実際は準備がやや大変なのですが、Loader componentの方が実は本命とも考えられ、直列読み込み、並列読み込みを読み込み時に簡単に指定したり、読み込み完了イベントも準備されています。

<namespace:load 

filesInParallel="/resource/to/css1.css,/resource/to/fileParallel1.js,/resource/fileParallel2.js"
filesInSeries="/resource/to/file1.js,/resource/dependentOnFile1.js"
/>

<aura:handler event="jam:staticResourcesLoaded" action="{!c.initScripts}"/>

もっと前からこの存在に気づいていれば冒頭の記事も違う形になっていたんじゃ、とか言っていても仕方がないので、冒頭の記事同様、「外部JavaScriptを使っている自作Lightningコンポーネントを第三者に使ってもらう」ことを念頭に、2つの読み込み方を提示し検討したいと思います。


呼び出し側での一括読み込み

依存関係が複雑でなければ使用側が外部リソースをまとめて読み込めば良いでしょう。下記は、myCmp1およびmyCmp2common1.jscommon2.jsまたはその両方を利用する場合です。基本的に当コンポーネントの配布元ではそのような利用方法を想定しているようです。


ComponentsUser1.cmp

<aura:component>

<c:load filesInSeries="/my/zip/common1.js,/my/zip/common2.js" />
<c:myCmp1 />
<c:myCmp2 />
</aura:component>

読み込み指定を忘れた時の対処として、冒頭の記事の利用例と同様に、myCmp1myCmp2内にて、setTimeoutにて外部リソース読み込みの確認を取ると親切かと思います。


コンポーネント内からの読み込み

依存関係が複雑な時や、コンポーネントのユーザー側により楽をしてもらいたい場合は、提供コンポーネント内(上記で言うmyCmp1)にてLoader component等を使用して外部リソースを読み込む方法が考えられます。


ComponentsUser2.cmp

<aura:component>

<c:myCmp1 />
<c:myCmp2 />
</aura:component>


myCmp1.xml

<aura:component>

<aura:attribute name="loadPath" default="/my/zip" type="String" />
<aura:if isTrue="{!v.loadPath != ''}">
<c:load filesInSeries="{!v.loadPath + '/common1.js,' + v.loadPath + '/common2.js'}" />
</aura:if>
<!-- Your component body goes here -->
</aura:component>

この場合、各コンポーネントからload.cmpを読み込む必要があるため、そのまま呼び出した場合、一括読み込みの場合と比較してコンポーネントの読み込み回数が増えてしまいます。読み込み済みを意味する引数を準備し活用することにより、比較的効率的に動作させることも可能と思われます。


ComponentsUser3.cmp

<aura:component>

<c:load filesInSeries="/my/zip/common1.js,/my/zip/common2.js" />
<c:myCmp1 loadPath="" />
<c:myCmp2 loadPath="" />
</aura:component>