Web Components と Lightning Web Components
「Web Components」というWeb標準仕様があります。具体的には "Custom Elements" と "Shadow DOM" および "HTML Template" という個別の仕様群となりますが、この仕様に対応したブラウザプラットフォーム上であれば、開発者はこの仕様に則ることで再利用可能なコンポーネントを開発することができる、というものです。
Salesforce が最近発表した「Lightning Web Components (LWC)」は、このWeb Components仕様に対応した形で開発ができるというアナウンスがされています。
これについて、実際には 「Web Components標準仕様に準拠」といってしまうのは少し無理がある、少なくとも文字通り受け取るのは難しいと考えています。以下にその理由を述べます。
非標準のコンポーネントの登録手段
Custom Elementsの仕様では、開発者が作成したコンポーネント(カスタム要素)について、ブラウザであるランタイム環境に登録するための方法を標準仕様として定めています。具体的には window.customElements
というオブジェクトの define()
というメソッドをコールして登録することになっています。
window.customElements.define('my-element', MyElement);
Lightning Web ComponentsがSalesforceのプラットフォームで稼働する際には、このような標準的な登録手段は用いられません。ディレクトリ構成/名前ルールに従って配置されたコンポーネントは自動的に登録されるような動作となります。
それだけならプラットフォーム独自のフレーバーとして特に問題ではないかと思いますが、問題なのは__標準仕様で定められているcustomElements
を使ったカスタム要素の登録については利用できないようになっている__ことです。
この仕組みについては通常はWebブラウザが提供するものなので、Custom Elementsに対応したブラウザであれば利用できるのでは、と考えるのが通常かもしれません。Salesforceでは、セキュリティ的な理由から、独自に制限されたBOM/DOMを持つランタイム環境(Locker Serviceとして知られています)を提供するというアプローチを取っています。そのため、たとえ対応ブラウザであっても、Salesforceプラットフォームで利用する限りは、同インターフェースによって登録されることを想定したコンポーネントは利用することができない という事態になっています。
コンポーネントをDOM要素として取り扱えない
Web Componentsの利点として、カスタム要素としてDOMレベルで対応されていることから、開発したコンポーネントを標準のDOM要素と同じ枠組で利用できるという点があります。このようにブラウザによるプラットフォームレベルでのプラグイン機構が提供されたことにより、開発者は統一的な方法(DOM API)のみで描画のコントロールに対応できるようになっています。また、DOMの操作に対応しているライブラリであれば、Web Componentsで構成されたツリーについても基本的にそのまま適用できるというメリットがあります。
現状 Lightning Web Components ではこのような利用方法について対応できていません。具体的には__動的にLightning Web Componentsの要素を生成してDOMツリーに追加することが許されていません__。
これについて Lightning Web Components の開発リーダーであるDiegoのStackOverflowでの回答は、個人的にかなり失望させるものでした。
We have purposely made the decision of not allowing dynamic component creation yet (the equivalent of $A.createComponent) on the Salesforce platform to make sure we had a clean, statically analyzable and predictable behavior on which to build upon in LWC.
この回答については(おそらく上記のアンサーは初回の回答後何度か修正されていますが)、Lightning Web Componentsとしての標準仕様への準拠の重要性への認識を疑わせるに足る回答として認識しています。Web Components (Custom Elements) が既存DOMの拡張の実現を目的にしている以上、このような操作(dynamic component creation)の実現については仕様としてMUSTであると考えられます。少なくともプラットフォーム独自の理由で採用の可否を判断して良いものではありません。プラットフォームの制約上どうしても難しいというのであれば、それはWeb Components準拠を謳うべきではないのです。
上記指摘に対するSalesforceの見解
Not sure what “abusing the standard” means. LWC is fully standard compliant. We put more restrictions (ex. security constraints) at the platform level because our business requires it. I guess we will agreee to disagree. 🤷♂️
— Diego Ferreiro Val (@diervo) January 26, 2019
Please don't be binary... LWC is compliant to standard formatting and it can run anywhere including outside of our platform (if it not have specific function such as data access etc..). this means LWC is Web component.
— Mitsuhiro Okamoto (@mitsuhiro) January 27, 2019
Our platform runtime added security restriction. This means our Platform is not have 100% compatibility for “Environment” of standard Web Component, but It's same as Lightning Locker. Locker added some restriction for DOM access, but no one says 'It's not Javascript'
— Mitsuhiro Okamoto (@mitsuhiro) January 27, 2019
「LWC自体はWeb Components仕様準拠である、ただしそれが稼働するプラットフォームの方に制限がある」という主張です。実際には(あまり利用シーンがあるかわかりませんが)LWC は(データサービスなどのプラットフォームに起因する機能を利用しない限りは)Salesforceプラットフォーム以外でも動作できるように作られており、その意味で、「純粋な」Lightning Web Componentsは標準仕様準拠だ、という意図だと思います。
これについては、確かにSalesforceにおける製品開発上はコンポーネント実行環境プラットフォームとしてのLightningとコンポーネント開発フレームワークとしてのLWCは別のものとして切り分けられているのかもしれません。しかしながら、パートナーや開発者、あるいは新規にSalesforceへの参入を検討しようとするベンダーにとって、そのような区別が重要でしょうか? LWCの開発者が第一の動作環境として想定しているプラットフォームにおいて通常のWeb Componentsとしての動作要件を満たせないのであれば、LWC単体では標準に準拠しているという主張になんの意味があるでしょうか。
特に、ユースケースなどから考えて、Salesforceプラットフォームの外で稼働するLightning Web Componentsがビジネス上の価値を持っていくことは現状考えにくいかと思います。純粋に技術的な要求(ローカルでの単体テスト実行など)以外でメリットが薄い話です。そのようなものを念頭にして殊更に標準準拠をアピールするのは、プラットフォームで提供している実態と混同させる目的があるのではと問われても仕方ないのではないかと思います。
標準準拠でないことの現実的なデメリットについて
ここまではLWCが標準準拠であるというSalesforce側の主張に対する私の見解であり、製品サービスとしてプラットフォームを一体として見ることが当たり前の中でそのような主張をするのはとても非誠実であり、ともすれば欺瞞になりえる、というのが骨子となります。
しかしながら、もしも標準準拠を謳わないのであれば、彼らのプラットフォームに適した形での制約を加えておくというのは、かならずしも問題にはならないでしょう。先の段落においての私の指摘はあくまで「Web標準をアピールしていながら標準仕様に準拠していない」こと、および「準拠をアピールする以上は対応しなければならない、という認識がない」ことを問題にしています。
ただし、現実にこのような制約を設けてしまうことについては、やはり大きなデメリットをもたらすと考えています。Web ComponentsとしてはコンポーネントはDOM要素としてfirst classであることが重要であり、それこそが価値であるからです。
例えば現在IonicやOnsen-UIといったHTML5のUIコンポーネントライブラリがありますが、これらは現在Web Componentsをプリミティブなコンポーネントとして、ReactやVue、Angularなどの上位のUI構築フレームワークを用いてWrapしたものをそれぞれ提供しています。これにより特定のUIフレームワークに非依存でありながらどのUIフレームワークでも同じUI体験を提供することに成功しています。このようなことが可能なのは、各UI構築フレームワークがDOMを直接取り扱うものであり、そしてWeb Componentsのカスタム要素はあくまでDOMとして取り扱えるからです。特に、ReactやVue/AngularなどのそれぞれのUI構築フレームワークを利用した開発ノウハウは多方面で蓄積されており、それらをWeb Componentsのみで置き換えるということにはまだ難しいと予想されているため、Web Componentsをプリミティブな要素の提供に限定して提供するといったアプローチがとれるのは大変有利であると考えられます。
また、Web Componentsの内部の描画はShadow DOM内でDOMツリーを構築していくことになります。なので、そのツリー構築に先のUI構築フレームワークを利用して行うことも可能なのです。Web Componentsは画面を構築するプリミティブな要素としても使えるとともに、ある程度のUIツリーの塊をまとめ上げる単位としても利用可能ということになります。そしてそれらは入れ子にすることももちろんできます。
このような柔軟性こそがWeb Componentsのメリットといえるのですが、LWCのコンポーネントがDOM要素としての操作を許さないのであれば、上記のような開発方法は選択できなくなります。もちろんSalesforce以外のプラットフォームではそのような制約はないため、今後の動向によってはWeb ComponentsをDOM要素として扱えることを前提とした開発が主流となり、エコシステムもすべてそれを中心に構築されるかもしれません。先に上げたように一部ではその目が見えつつあります。そのようなとき、LWCもまたAuraのときのように時代から取り残されたフレームワークとして位置づけられることになるでしょうし、そのようなものに投資してしまったパートナーも開発者も浮かばれないでしょう。
まとめと提言
Salesforceの製品開発は、標準仕様への準拠というものについて本当にちゃんと考えているのか、ということです。W3Cへの参画についてアナウンスするくらいですから、重要性は理解しているのだと期待します。ただ、今回指摘したとおり、そのような対外的なアピールにもかかわらず、一部で本当に価値を理解しているのか不明な実装および言動があるのも事実です。そもそも一体何のために標準ができたのか、フラグメンテーションを招かないために何をしなければならないのか。ちゃんと考えてほしいですし、考えていることを我々にちゃんと伝えてほしいものです。
(※ 本記事はいずれ時間があれば英訳する予定です)