目標
- TypeScriptによる型検査を伴った開発体制をLightning Web Components(LWC)の開発に対しても導入できるようにする
- npmなどのライブラリについても通常のWeb開発と同様に利用できるようにする
指針
-
LWCとしてプッシュするメタデータに含まれるのはJavaScriptコードである必要があるが、ソースコードをTypeScriptで記述するため、プッシュ前にビルドフェーズを設けてトランスパイルを施す。
-
ただし、トランスパイルのターゲットは一般的なブラウザ環境ではない。クラス構文やクラスプロパティ、デコレータなどのリリース前のES機能をそのまま残した状態で出力する必要がある
- トランスパイルにはTypeScriptのコンパイラ(
tsc
)ではなく、プラグインが豊富かつ柔軟なBabelを利用する。 -
@babel/preset-env
などは利用せず、@babel/preset-typescript
に型定義のストリップのみを任せる。 -
@babel/plugin-proposal-decorators
や@babel/plugin-proposal-class-properties
などを指定してしまうと同構文はトランスパイルされてしまう。指定しない - だがbabelのparserは同構文を理解する必要があるので、babelの設定内の
parserOpts.plugins
にdecorator-legacy
を指定する。
- トランスパイルにはTypeScriptのコンパイラ(
-
npmのライブラリのバンドル方法については「Lightning Web Components で npmで公開されているライブラリを利用する」で書いた内容と同様にrollupを行う。
- 前回は参照ライブラリのみビルドしていたが今回はコンポーネント本体もバンドルに含めているところが違い
- rollup実行時にはlightning platform関連のmoduleをresolveしないように無視する設定を追加する(e.g.
lwc
,lightning/*
,@salesforce/*
)。- これにより
lightning
npmモジュール (BitcoinのLightning Networkを利用するためのJSライブラリ)は利用できないことになるが、まあLWCでこれを使うケースはほぼないだろう
- これにより
- また
wire
デコレータでwireした関数の関数名はminify時にはmangle(名前の短縮)しないように設定する(現状、変数名がshadowされないようにする必要がある模様)
-
その他、前処理用のbabelのプラグイン、バンドル時の後処理用rollupのプラグインをrollup時に含めている。
- これはrollup.jsが内部で扱う構文木が対応していない新しいES構文(デコレータなど)が含まれるコードはrollup内では扱えないため、そのhatch。
-
TypeScriptソースコードは
force-app/main/default/lwc
とは別のディレクトリに管理する- サンプルではプロジェクトルート直下に
src
ディレクトリを配置し、こちらでコンポーネント開発をすることにしている。もちろん場所は自由である。
- サンプルではプロジェクトルート直下に
-
テンプレートHTMLは今回は
lwc
以下の各コンポーネントフォルダに直接保持する。もちろん何らかの前処理が必要だと考えるなら別に管理し、ビルド時にコピーする形でも構わない。 -
プロジェクト内で利用するすべてのコンポーネントのコードをまとめたバンドルを作成し、バンドルされたファイルを共通LWCコンポーネントとして参照させるようにする。各コンポーネントではそれらを単に読みこんでからdefault exportするだけのJSファイルを保持しておく。
サンプルプロジェクト
順次更新中
https://github.com/stomita/lwc-typescript-dev-example
注意点
- 参照しているnpmのライブラリサイズが大きくなると、コンポーネントのpush時に
Error: Value too long for field: Source maximum length is:131072
が発生する。適宜Code Splittingを行う必要がある。 - AppExchangeパッケージのセキュリティレビューが必要な場合では、バンドル後のファイルだけではなく、別にソースコードの提出を求められるかもしれない。
- 現時点ではプロジェクト内容によって個別に対処が必要になるだろう点が多く(先のCode Splittingなど)、上記の方法がベストプラクティスというところまでにはならないと思われる。npmライブラリの利用をあきらめて単にTS->JSへtranspileするだけなら穴は少ないかもしれないが…
-
wire
などの型定義はlwc
(OSS版)に同梱されているが、あまりインテリジェントではない(たとえばハンドラ側の引数は自分で型アノテーションしてやる必要がある)。もちろんplatform側のサービス参照の型定義は提供されていないので、適宜自分で型定義ファイルを作ってやる必要あり。