Ionic Frameworkの開発チームが先週のJSConf EUで、その名も"Stencil One"というステンシルツールチェーンの、最初のメジャーイテレーションを公開した。Stencil Oneは、最適化されたWebコンポーネントと、プログレッシブWebアプリ(PWA)にコンパイルする。開発者がStencilコンポーネントを1度作成すれば、Stencilコンパイラのオプションを調整することによって、Angular、React、Vue、Ember、あるいはプレーンなバニラJavaScriptを含む、任意のフレームワークで再利用することができる。Stencil Oneはさらに、ユーザと開発者のエクスペリエンス向上を目的としたツールチェーンも提供する。ページの事前レンダリング、コンポーネントのドキュメントの自動生成、内蔵されたHot Module ReplacementとStyle Replacementなどである。
開発チームはStencil Onemについて、"高速で再利用可能なUIコンポーネントとプログレッシブWebアプリを構築するための、Webコンポーネントコンパイラである、と説明している。Stencilコンポーネントは単なるWebコンポーネントであり、ReactやVueなど主要なフレームワークで動作する。また、Webコンポーネントをサポートするあらゆるブラウザで、従来のフロントエンドフレームワークの代替として使用することも可能だ。さらにStencil Oneは、特に"ヘッドレスブラウザ、プレレンダリング、オブジェクト・アズ・プロパティを実行する必要のないサーバサイドレンダリング(SSR)"など、Webコンポーネントをポータビリティにおいて重要な機能も数多く備えている。コンポーネントのドキュメントを自動生成することも可能だ。
Webコンポーネントとは、開発者が独自のカスタムタグでHTMLを拡張可能するための、低レベルの標準化Web APIである。ただし、この標準は、開発上の共通的な問題(効率的なアップデート、テスト、プレレンダリングなど)には言及していない。これらは通常、フレームワークによって対処される。また、他のHTML要素と同様に、Webコンポーネントは、プロパティまたは属性として文字列のみを受け入れる。
カスタム要素(Custom Elements)(Webコンポーネント仕様の重要部分)を直接使用する場合と比較した場合、Stencilのコンポーネントは、仮想DOMレンダリング、JSX構文、非同期レンダリングパイプライン( React Fiberなど)などを内部的に備えている。開発者としては、主要なフレームワークが提供するものと同様の開発エクスペリエンスを享受することが可能であると同時に、使用するコンポーネントが、標準ベースの再利用可能なWebコンポーネントにコンパイルされることが保証される。開発チームは、次のように説明している。
開発者は、優れたツール、定義された構造、アプリの迅速な構築を求めて、フレームワークを導入することが少なくありません。Stencilの最大の目標のひとつは、開発において、優れたフレームワーク機能と一流のツールを自由自在に使用しながら、カスタムフレームワーク固有のコードではない、将来的な価値のある標準的なWebコードを生成可能にすることです。
StencilのコンポーネントはTypeScriptとJSXで記述され、プロパティとメソッドをセットで持ったクラスである。クラスのプロパティは、@Prop
デコレータでタグ付けして、コンパイル結果のターゲットWebコンポーネントの属性にしたり、カプセル化された標準クラスのプロパティとして残すことが可能だ。クラスのメソッドも同様に、@Method
デコレータでタグ付けして、コンパイル結果のターゲットWebコンポーネントのインターフェースの一部としたり、内部的に残すことができる。ローカル状態も@State
デコレータでタグ付けできる。タグ付けされたローカル状態が変更されると、Stencilクラスのrender
プロパティが呼び出される。さらに、@Watch
デコレータを使用して、監視対象のプロパティの更新時に実行される関数を用意することもできる。これらのAPIの最終結果が、コンパイル後のWebコンポーネントのパブリックインターフェイスや、コンポーネント内部のリアクティブロジックの定義である。
基本的なHello World
の例は次のようになる。
import { Component, Prop } from '@stencil/core';
@Component({
tag: 'my-component',
styleUrl: 'my-component.css'
})
export class MyComponent {
@Prop() first: string;
@Prop() last: string;
render() {
return (
<div>
Hello, my name is {this.first} {this.last}
</div>
);
}
}
Stencilはこのクラスを、任意のHTML要素として使用可能なWebコンポーネントにコンパイルする。
<my-component first="Stencil" last="JS"></my-component>
コンパイルされたWebコンポーネントは、defineCustomElements
関数を使用してDOMに追加されて、ブラウザのグローバルwindow
オブジェクト上で公開されることにより、プレーンなJavaScriptで使用できるようになる。フロントエンドフレームワークがレンダリングするHTMLに含めることもできる。ただし、Webコンポーネントを完全にサポートしないターゲットフレームワークと完全に統合するためには、ある種のグルー(glue)開発が必要になる場合もある。例えばReactとPolymerは、Webコンポーネントと完全に相互運用でないので、追加開発が必要になるかも知れない。
最新のブラウザ機能とAPIをサポートしていないごく一部のブラウザに対しては、Stencilがオンデマンドでそれらを自動的にポリフィルする。これはDifferential Bundling、あるいはDifferential Loadingと呼ばれることがある。機能をネイティブサポートするブラウザでば、関連するポリフィルを含める必要がないため、バンドルのサイズが小さくなる。現在のブラウザサポート(ポリフィルを使用)には、IE11以降が含まれている。
Svelte、Dojo、あるいはLit-htmlといった他のフロントエンドフレームワークも、Webコンポーネントにコンパイルできる。InfoQはSvelteの作成者であるRich Harris氏に先日インタビューした際、Webコンポーネントにコンパイルすることのメリットについて議論した。コンパイラは、ターゲット出力に最適化(ツリーシェイキングの詳細化や使用しないCSSの削除など)を施して、バンドルサイズの削減やパフォーマンスの向上を行うことができる。Stencilは次のような、同じアプリケーションに対して生成されたバンドルサイズの比較を公開している。
StencilとIonicは別々のプロジェクトである。IonicはStencilの最大のユーザでありプロモータだが、Stencilには、規定されたフロントエンドフレームワークはない。
Stencilはオープンソースソフトウェアで、MITライセンス下で利用することができる。フィードバックはStencil GitHubプロジェクト経由で募集されているが、Stencilのの行動規範に従う必要がある。