技術書典6にサークル参加しました
技術書典6お疲れ様でした!ブログを書くまでが技術書典です、ということで参加レポートです。
前回に引き続き、会社を巻き込んで技術書を執筆してサークル参加してきました。個人としては技術書典2から5回目、自分が主宰するサークルとしては2回目のサークル参加となりました。
頒布物
今回は2冊を頒布してきました。
- Web Components First Book
- チームマネジメントとGridsome / VuePress
それぞれ
- 製本 + DLカード 50部
を持ち込みました。
前回はDLカード版のみだったんですが、せっかく書いたなら、ということで今回は製本することにしました。
参加メンバー
今回執筆に参加したメンバーは自分を含めて4名です。
- foxtrackjp(きつね)(2回目)
- ちー(ゲンガー)(初)
- tyankatsu5(ほうれん草)(初)
また、『チームマネジメントとGridsome / VuePress』の表紙は我々と同じ福岡でフロントエンドエンジニアをしているカオルコさんにご提供頂きました。感謝。
頒布結果
頒布数 | |
---|---|
Web Components First Book | 43 |
チームマネジメントとGridsome / VuePress | 28 |
合計 | 71 |
売上的にはギリギリ印刷費を回収した感じです。
交通費、宿泊費を回収するには1.8倍〜2倍程度は売らないといけません。
あくまで同人活動なので特別大きな利益とかは求めてなくて、ささやかながら執筆メンバーで打ち上げができるくらいの利益があったら嬉しいな、くらいなのですが、やはり地方参加組としては交通費によるハードルの高さがありますね......
もろもろ感想とか
執筆環境
前回執筆で利用したMarkdown → PDF変換のプログラムを改良して利用しました。Textlintとか入れてリアルタイムに校正できるようにしたんですが、ついつい長くなりがちな文章が自然と短くなって体験としては良かったと思います。
ページ番号がつけられないのが悩みだったので、入稿直前にVivliostyle.jsを使う方式に変更して入稿しました。今まで対応を後回しにしてたんですがめちゃくちゃ便利でした。もっと早く使えばよかったなーという気持ちで当日、Vivliostyleユーザー会が頒布していた本も購入しました。次回に活かしたいと思います。
とはいえMarkdownは書籍を書くには機能的に弱くて「もっとこんな機能があれば......」と思うことも少なくないです。
自分は今後も技術書典には継続参加していくつもりなので、よりよい執筆環境を求めていろいろ試していこうかなと思ってます。
- Re:VIEWを直接書く
- Scrivenerを頑張る
次回、次々回あたりで上記のどちらかは試してみたいなと。
InDesignを使ってみたい気持ちもありますが高くて手が出せないので、Affinity Publisherがもっとまともになって正式リリースされる日を待っています。
やっぱり現地は紙の本のほうが売れる
傾向としては以前から分かっていたことではあるのですが、技術書典当日はDLカードのみより紙の本があったほうが売れます。
今回73部頒布しましたが、DLカードのみを希望されたのは一人だけでした。
後払いアプリの利用率が上がってきてる
かんたん後払いも定番化してきて、利用率も上がってきたなーという印象です。
今回売れた73部のうち31部(26決済)はかんたん後払いによるものでした。次回からは手数料がかかるようになるかも?と運営側からアナウンスがありましたが、これだけ普及してくると手数料も運営側でカバーできる規模じゃなくなってきた、というのもわかる気がします。
ワンオペしんどい
ワンオペと言いつつ当日は偶然別の予定で東京に来ていた同僚がヘルプに入ってくれたので、忙しい時間帯は2人でのオペレーションでした。
後半、忙しさに一段落つく頃にワンオペになりましたがそれでも回すのは結構大変だったので、始めからワンオペだったらどうなっていたことか、、、という感じです。感謝。
あと盲点だったんですが、ワンオペになると撤収作業がものすごく面倒でした。ブースを片付けるだけでなく、残った在庫を委託に出す手続きをしたり、本を配達に出したりと結構動き回ることになりますし、売上金を放置するわけにもいかないのでジャラジャラ言わせながら行動することになります。
やはり現地には2人以上で参加するほうが望ましいですね。
次回にむけて
目指すはサークル参加
次回ももちろんサークル参加を目指します。
執筆は(かなり)大変ですが書いた本を買ってくれたり、本の感想が聞けたりするのはすごく嬉しいし楽しいので、これからも継続して参加していきたいなと思います。
ありがたいことに前回、今回と会社の同僚が執筆に参加してくれたので、こうして福岡にも執筆文化が根付いてくれたら嬉しいなと思います(そしてゆくゆくは福岡でも技術同人誌イベントを......!)
次回も製本はしたい
実は原稿を製本したのは私が別サークルで頒布していた技術書典3以来でした。長らくコストとの兼ね合いでDLカードのみで頒布していたのですが、今回50部ずつと少数ですが思い切って製本してみました。
売上的に印刷費の回収がやっと、という感じで金銭面では裏目に出たのですが、自分が書いた原稿が本という形になったのをみるとやはりテンションあがりますし、原稿を書いてくれた他のメンバーにも記念として渡せるので、次回も製本はしたいです。
ポスター作る
販促用&当日掲示用のポスター作ろうと思ってたはずがすっかり忘れてました。
周りを見ると結構作ってるサークルさんも多かったし、ポスター立ててると混雑してても本の内容を見てもらえるのでやっぱりあったほうが良かったなと反省しました。
ポスターがないぶん、今回はずっと本を持って呼び込みしてたんですが腕が筋肉痛になりました。
ポスター作るならスタンドも買わないと。。。
値札作る
値札作ろうと思ってたはずがすっかり(ry
前日夜中に作ってコンビニで印刷しました(笑)池袋のキンコーズで印刷しようと思ってたんですが、あの店舗は朝10時からなんですね(汗)
おわりに
今回も楽しく参加させてもらいました。次回もサークル参加できるよう祈りながら、ネタを考えながらまた半年過ごしたいと思います。 皆さんお疲れ様でした!
P.S
今回頒布した書籍のDL版はBOOTHで販売してます。ご興味のあるかたはぜひご覧ください。
技術書典6にサークル参加します
タイトルの通り、技術書典6にサークル『VEGA Tech』としてサークル参加します。
これで個人的には技術書典2の頃から5回目のサークル参加です。最近は回を追うごとに倍率も高くなっているようなので当落発表までドキドキでしたが、当選したからにはサークル側として楽しみたいと思います!
サークルページはこちら
頒布するもの
今回の新刊は2冊を予定しています。
※ 掲載のサンプルは執筆中のものなので、実際に頒布する際は構成が変更されている可能性があります。
チームマネジメントとGridsome / VuePress
著者:
自社エンジニアチーム有志の合同本です。3人が執筆に参加してくれました。
テーマは大きく2つで、「チームマネジメント」と「Vue.js製の静的サイトジェネレーター」についてになっています。
チームマネジメント
チームマネジメントについては ちー(ゲンガー)が担当しています。
自社サービスのリーダーとしてマネジメントをする中で意識したこと、考え方をまとめて頂きました。
簡潔で分かりやすく、スピード感が求められる開発チームにはすごく参考になる内容になっているんじゃないかと思います。
Gridsome
Vue.js製の静的サイトジェネレーター『Gridsome』のパートはコラボレーターでもあるほうれん草こと tyankatsu5が執筆しました。
Gridsome自体の解説だけでなく、実際にGridsome製のブログをNetlifyで公開するサンプルだけでなく、テスト環境の構築方法のようなTipsも交えて解説しています。
図も多めで、自分のサイトを作ってみたいという方やWeb制作などに携わる人におすすめな内容です。
VuePress
Gridsomeと同じVue.js性の静的サイトジェネレーター『VuePress』パートの担当は foxtrackjp(きつね)です。
まだアルファ版ではありますが、Markdownで気軽にページが配信できるVuePressを使ったページを、実際にNetlifyで公開するサンプルを交えながら紹介します。
まだ情報も少ないので、貴重な日本語情報ではないかなと思います。Gridsomeと比較してみても面白いですね。
WebComponents First Book
著者:
自分は前回に引き続き、Web Componentsについてまとめました。
Web Componentsの構成仕様(Custom Elements、Shadow DOM)の解説に加えて、Polymerの後継であるLitElementについても解説しています。
モダンブラウザの全対応間近となった技術で、「使ってみたい、興味がある」方も増えているのではないかと思います。自分はWeb Componentsにすごく未来を感じているので、この本を通して興味を持ってもらえると嬉しいです。
か-68 でお待ちしてます!
今回諸事情で当日は自分一人でサークルを切り盛りしないといけなくなりました(苦笑)
普段なら自分も歩き回って本を買い漁るのですが、今回はちょっと難しそうです;; せっかくならいろんな人とお話したいので、本の内容にちょっとでも興味をもっていただけたらぜひブースまで遊びに来ていただけると嬉しいです!
サークルページはこちら
最近の福岡ITイベントについて思うこと
最近イベントを主催したり、他の人の主催イベントに管理者として携わらせていただくことが増えてきて、少し思うところがあったので記事にします。
ご注意
技術的な内容は一切ありません。
自分は主にフロントエンド界隈のイベントに出入りしているので、その近辺を見ている中で、かつフロントエンド界隈でもすべてのイベントに出入りしているわけではないので、観測できる範囲での印象です。
あまり大きな主語で話す意図はないのであらかじめご了承ください。
TL;DR
- 福岡IT界隈盛り上がってる
- 福岡ITイベント、キャンセル率が上がってる
- イベントへは気軽に参加してほしい
- ただ、気軽なキャンセルはやめて欲しい
- 無断不参加は論外
- 良い解決策をみんなで探していきたい
福岡IT界隈の盛り上がり
他県のエンジニアの知り合いからも「福岡はITが盛り上がってるらしいね」と言われることがありますが、実際最近の福岡IT界隈は盛り上がっていると思います。
最近では毎日どこかしらでイベントが開催されていて、1日に2~3個のイベントがかぶるのも珍しくなくなりました。
同時に、イベントの人数規模も大きくなっています。以前は30人規模ならそこそこ大きいイメージでしたが、最近は50人~60人規模のイベントも少なくなくなってきました。
自分が主催したり、運営に携わらせていただいてるイベントで「初めてイベント参加します」という方も増えていて、イベントを主催する側としては嬉しい限りです。
最近の福岡ITイベント
ここ1年くらいで、イベントのキャンセル数が増えているように感じます。
目安として総申込者数の30%~35%程度。申し込み総数が50人なら15人くらいかなと。先日開催したイベントを例に取ると、総申し込み80名弱に対してキャンセルが29名でした。(うち10名超が当日キャンセル)
よくイベントを開催している方も最近はそのくらいを目安に人数を計算してる、ということだったので実態から大きく乖離してはいないのかなと。
体調不良や急な業務があるのはもちろん承知してますし、どのイベントでも、そういった事情があってやむなくキャンセルする人もいるでしょう。こういったキャンセルを問題にするつもりはありません。
30%~35%という比率についても、東京で開催されているイベントも同程度なので、比率という面ではそのあたりに収束するものなのかもしれません。
しかし2~3年前50人規模のイベントでもキャンセルは3、4人だったこともあるので、福岡のITイベントについてキャンセル率が悪化しているのは間違いないと思います。
気軽なキャンセルはやめて欲しい
当然、イベント参加自体は企業主催のイベント以外は主催者も参加者もプライベートの時間を使っているはずなので、参加することを義務と言うつもりはありません。どうしても都合がつかない場合は遠慮なくキャンセルしていただければ良いと思います。
ただ、気軽なキャンセルだけは本当にやめてください。
同じくイベントを主催している友人からは「イベントはそんなもの」「諦めるしかない」とも言われましたが、これはイベント主催者が諦めるものではなく、参加者側の倫理の問題だと思います。
主催者は会場を押さえたり、登壇者と調整したり、申込数によっては新しい会場を手配したり、いろいろな準備をしています。登壇者の方も発表資料作りなどの準備をしています。
もちろん、「絶対参加したい!」と思ってもらえるようイベントの魅力を伝えきれなかった自分にも反省すべき点はありますが、参加される方も参加申し込みをした以上は、できる限り参加できるよう準備をして頂きたいな、というのが正直な気持ちです。
不参加は論外
申し込みだけしてキャンセルせず、当日会場に来ない人もいます。直近のイベントではそれぞれ13人、7人が連絡なく不参加でした。
ここまでキャンセルについて言いたいことを書きましたが、主催者側としてキャンセルはある程度覚悟している面もあります。
ただ無断での不参加は論外です。参加したいのに補欠で参加できなかった方もいる中、参加枠を埋めておいて参加しないというのははっきり言って迷惑行為でしかありません。
無断で不参加だった方は名前はわかるので、繰り返されるようなら今後は強制キャンセルも辞さないつもりでいます。
良い解決策を探したい
当日、直前キャンセルは以前から課題としても上がっているので、connpassも何かしらの対応を考えて欲しいところなのですが、今のところそういった機能の実装はなさそうです。
今のところ、デポジット形式はどうかなと思ったりしています。(参加申し込みでいくらかお金をお預かりして、参加受付のタイミングでお返しする)ただこれは、企業から会場提供を受けている場合などの課題もあるのでなかなか実施が難しいので、もう少し気軽に実施できる方法がないか模索してます。
イベント主催者で協力して、この辺の解決策を探していけたら良いなと思っています。
おわりに
好き勝手書きましたが、これからも福岡IT界隈はどんどん盛り上がっていって欲しいし、少しでも力になれればと思っています。
自分もいろいろイベントは開催していこうと思っているので、ぜひ気軽に参加してください!(こんなイベントがしたい!というアイデアもあればぜひ)
最後に
これは主催者側としてのエゴですが、キャンセルのときに一言添えてくれるだけでも全然気持ちが違うのでぜひともよろしくお願いします。
Gitコマンドをちょっとだけ便利にするプラグイン書いた
何をつくったの?
Gitを使った開発フローでは、作業に応じていくつもブランチを作成して 切り替えて使っていくことになります。
ブランチごとにファイルは独立していて、気軽にファイルの書き換えもできるし、他の人と協業しやすいので非常に便利です。
ですが、正直ブランチを操作するコマンドって面倒じゃないですか?
ブランチ名を覚えておいて、毎回そのブランチ名を入力してあげないといけません。ブランチ名を忘れてしまったらgit branch -a
して......と、よくやる操作にしては手順もタイプ数も多いです。
SourceTreeのようなGUIクライアントを使っている人ならあまり気にならないかもしれませんが、基本的にコマンドを叩いている自分は常々「面倒だなー」と感じていました。
加えて、最近仕事で細かくブランチを切り替えて作業することが多くこのストレスがピークに達してしまったので、以下のようなツールを作成しました。
リポジトリの指定が必要な
- git checkout
- git branch -d
コマンドのターゲットとなるブランチを、ブランチ一覧からカーソル移動で選択できます。
それぞれ
- git switch
- git remove
で実行できます。
インストール
Homebrew経由でインストールできます。
brew tap ponday-dev/git-plugin-choosable brew install git-plugin-choosable
開発環境など
↓リポジトリはこちら
ponday-dev/git-plugin-choosable
珍しくGo言語で開発してみました。今のところmacOS用のビルドしか準備してないですが、ビルド自体はDockerでやってるのでクロスコンパイルの設定書き換えてもらえればWindowsでも動くかも。
昨日思いついて走り書いたので正常系しか確認していなくて、Ctrl + Cで中断するとGo言語のスタックトレースが表示されたりと粗はたくさんありますが一応使う分には問題ないということで公開しました。
また、GitHubでしか動作確認してないので他の環境では動かないかもしれません。修正などがあればPRいただけると嬉しいです!
↓ 使用したライブラリ
『Atomic Design周りについての私見』の補足
先日、ITのむずかしいを簡単にする会 - LT会 #5というイベントでAtomic Design周りについての私見という発表をしてきました。
しかし、15分枠と勘違いして作った(実際は10分枠)+当日思いついた話しておきたいことを考えなしに突っ込んだ結果スライドが40枚に登ってしまい、すごく早口での発表になってしまったので、補足を含めた内容を記事にします。
※ この記事はタイトルの通り個人的な主観が多分に含まれた内容になっていて、一概に「これが正しい」というものを示すものではありません。プロジェクトやチームの特性によって正しい方法は変化し得ますので、参考程度の内容とお考え下さい。
そもそもAtomic Designとは?
概要はいろいろなWebサイトで解説されているのでそちらに譲りますが、いわゆるUIデザインの手法として提唱されているものの一つです。
コンポーネントを原子(Atoms)、分子(Molecules)、有機体(Organisms)といった化学の用語で表現します。
1つのページが複数の部品を持つのではなく、複数の部品の組み合わせでページが構成されている、という考え方です。
よく次のような図が使われるので、1度は見たことがあるという方も多いのではないでしょうか。
理屈はかんたん。しかし...
ページをコンポーネントの組み合わせで表現する。理屈はこれ以上無いほどにかんたんなのですが、実際Atomic Designを適用して開発をしてみると次のような悩みが尽きず、やりづらさが拭えません。
なぜ?
ではなぜAtomic Designでの開発にやりづらさを感じるのかというと、Atomic Designが「そもそもアプリケーション開発の設計をターゲットにしたものではない」という点に尽きると思っています。
最初に述べたとおり、Atomic DesignはあくまでUIデザインの手法であってアプリケーションの設計手法ではありません。
このあたりの認識があいまいになってしまっていて、いざAtomic Designを適用してアプリケーション開発を始めてみたら「あれ、思ってたよりつらい......」という状態に陥っている人が多いのではないかなと思います。
Atomic Designとアプリケーション設計
Atomic Designがもたらしたもの
ではなぜ最近Atomic Designの名前をよく聞くようになってきたのかという点にですが、個人的に命名の勝利という側面もあるかなと思っています。
コンポーネントの階層と役割をきちんと体系付けて名前を与えたこと。それを化学になぞらえた名前にしてイメージを湧きやすくしたことで、エンジニアとデザイナーの共通言語としての役割を担えるようにしたというところに価値があるのかなというのが個人的な印象です。
さらに言うと、近年のフロントエンドにおいてJSフレームワーク(ReactやAngular、Vue.js)を用いて開発する中で確立されてきたコンポーネント志向とマッチしていたこともエンジニア層に受け入れられた要因ではないかと。
これまで一般的だったページ → 部品というデザインの流れに逆らって、部品 → ページという考え方で作られたUIデザイン手法だった、というところも大きかったのではないでしょうか。
Atomic Designが考慮しないもの
繰り返しになりますがAtomic DesignはあくまでUIデザインの手法なので、アプリケーションの設計に適用しようとすると色々と足りない部分があります。
基本的にCSSやJSの領域について、Atomic Designは面倒を見てくれません。これらの領域については、Atomic Designとは別に+αの設計が必要になってきます。
特にロジックの分離が問題で、「デザイン上のコンポーネントの境界」と「プログラム的なコンポーネントの境界」が必ずしも一致しない、というより一致しないことの方が多いです。
「ロジックは全部同じだけどデザインが異なるコンポーネントは、プログラム的に1つのソースにまとめるべきか、複数に分割して作るべきか」
といった部分をあらかじめ取り決めたうえで設計をする必要があります。
+αの設計を考える
Atomic Design + αを考えるとき、先のような内容について検討する必要があります。
基本戦略
+αの内容を検討する前に、基本戦略としてAtomic Designで定義されたレイヤー(Atoms, Molecules, etc)に、プログラム的な視点での役割を決めておきましょう。
個人的には、以下のように定義する場合が多いです。
Atoms、Moleculesはあくまで汎用的な部品として、ページを形作るのはOrganisms、Templatesというイメージです。
そのような分け方をするとき、Atoms、Moleculesはできるだけ汎用性を保って部品化できるようにすべきだと思っています。なるべくアプリケーション固有のデータに依存する作りにはせず、そのアプリケーション内だけではなく、他のプロジェクトでも流用できるようなものになるのが理想的です。
例えばUIライブラリとして提供するのはこのあたりまでかなと思います。
逆にOrganisms以上の層は他のアプリケーションで再利用することのない固有のコンポーネントというイメージです。
ここまでAtoms、Molecules、Organisms、Templatesについてのみ定義をしてきましたがこれには理由があります。
元々の定義によると、PagesはTemplatesに具体的なデータが流し込まれたものです。つまりPagesは最終的にレンダリングされてエンドユーザーが見ている画面と同じになるはずで、Pagesを個別にコンポーネントとして作成する必要はないだろう、というのが個人的な意見です。
Pagesをコンポーネントとして定義することがあるとするなら、UIテスト用にTemplatesにデータを流し込むコンポーネントとして定義する、という感じかと。
コンポーネントの管理
これは開発、運用面の話で、同じ機能を持つコンポーネントを作ってしまわないためにどうするか、という点です。
ここは設計とかあまり難しい話ではなくて、Storybookなどのコンポーネントカタログをきちんと用意して、使いたいコンポーネントが用意されているかどうかを誰でもすぐ確認できるようにしておけば良いと思います。
コンポーネントの依存関係
元々のAtomic Designの定義では、あるコンポーネントはその一つ下のレイヤーのコンポーネントのみに依存することになっています。
TemplatesはOrganismsにのみ、OrganismsはMoleculesにのみ、MoleculesはAtomsにのみ、という極めてシンプルな依存関係です。
しかしながら、現実的にこの制約はかなり辛いと言わざるを得ません。例えばOrganismsでAtomsも使いたいというニーズですが、実際に作ってみるとこういう場面は少なくなく、厳密にやろうとするあまりAtomsにパラメータを横流しするだけのMoleculesが生まれてしまう、という状況に陥ります。
そこでこのあたりの制約をもう少し柔軟にして、次のように定義しました。
比較的規模が小さく、理想的にはUIライブラリとして切り出せるようにしたいAtoms、Moleculesはオリジナルの定義に則り、アプリケーション固有の層となるOrganismsについてはオリジナルの定義から外れて依存するレイヤーを広げた形です。
TemplatesはあくまでUI上のレイアウトやそれに紐づく状態を管理するレイヤーと位置づけているので、最終的に出来上がった部品 = Organismsを配置するのを役割としてOrganismsのみに依存する、としました。
コンポーネント間のデータの受け渡し
UIデザインをコードに落とし込んで行くとき、開発者側が1から検討する必要があるのがコンポーネント間のデータの受け渡しをどうするか、という点です。
とはいえ、ここは愚直に「親から子にはプロパティを渡して、子から親にはイベントを経由してデータを渡す」という原則に立ち返って設計するのが一番良いのではないかと思います。
親から子にプロパティ渡しというと、「またバケツリレーになるのか......」と思われるかもしれませんが、単なるバケツリレーではなく「親は子が必要とするプロパティを適切に振り分けていく」イメージです。
例えばTemplatesでは複数のオブジェクトを持っているけど、Organismsに渡すときにそのうちの1つだけを渡す。そのOrganismsが受け取ったのはオブジェクトだけど、Moleculesにはそのうち必要な値だけを選択して渡す......という感じ。
このように原則は親→子のプロパティ渡し、子→親のイベント伝搬で、例外としてFluxのようなObserverパターンをベースにした状態管理が入っている場合が挙げられるのかなと思います。
状態管理
近年のフロントエンド開発、ことフレームワークを利用したSPA開発においてFluxベースの状態管理は必ずと言って良いほど入ってくるので、状態管理が絡んだデータフローについても検討が必要になってきます。
先に示した図は個人的にイメージしているデータフローです。Storeと書いているのが状態管理層で、ReactならRedux、AngularならNgRxや状態管理用のService、Vue.jsならVuexをイメージして貰えれば良いです。
subscribeはStoreからデータを読み出す操作、dispathはStore内のデータを更新する操作と読んで貰えればOKです。
先程、Atoms、Moleculesは可能な限り汎用的に保ちたいという話をしました。
状態管理層はアプリケーション固有のデータ、ロジックの塊なので、汎用性を保つという観点から行くと、Molecules、Atomsからは一切アクセスさせないようにすべきです。
状態管理に何のライブラリを使っているのか、そもそも状態管理をしているのかすらMolecules、Atomsが知る必要はなくて、あくまでOrganismsから与えられるプロパティを使ってビューを構築するようにしておきます。
Storeはアプリケーション固有仕組みになるので、そこにアクセスするのも同様にアプリケーション固有のレイヤー(= Templates、Organisms)になります。
では、Templates、OrganismsからStoreに対するアクセスポリシーも検討しておきます。考えうるパターンはいくつかありますが、個人的にはOrganismsが直接Storeからデータを読み出す操作(subscribe)は禁止することが多いです。次点でOrganismsからStoreへのアクセスを禁止するパターン。
ここはどのやり方も一長一短あるので、チーム内できちんとルールが決まっていれば良いと思います。
まとめ
何度も繰り返しているように、まずきちんと認識しておくべきことは「Atomic DesignはあくまでUIデザインの手法である」、ということです。
なので実際にアプリケーションを開発する、という視点で見ると制約が強すぎたり、そもそもプログラム的な問題は考慮されていなかったりとつらい部分が多くあります。
当然、開発に適用するためには+αのルールづくりが必須で、事前に決めておくべき(決めておかなければならない)ルールも少なくありません。
個人的にはAtomic Design原理主義的に厳密に実践しようとするのは悪手だと思っていて、上手くバランスをとって取り入れたルールを作って使うのが賢い使い方かなと思います。
現状Atomic Designで開発してみた、という記事を読むと、ここまで書いた内容と似たルールをチーム毎に決めて運用しているという状況になっているので、そのうちアプリケーション開発を念頭においたAlt Atomic Designのようなものが登場すると予想しています。Atomic Designっぽい作り方はしつつもそれが登場するまで待って、将来的にはそちらに乗ったほうが幸せかもしれません。
とはいえ、コンポーネント志向ライクなUIデザイン手法として、概念的にはシンプルで良いものだと思います。これからもこの周辺の情報は抑えていきたいと思います。
React + TypeScript環境でもWebComponentsを使いたい!
この記事はWeb Components Advent Calendar 2018 3日目の記事です。
TL;DR
TSX(TypeScript + JSX)環境でWebComponentsを使うときは型定義を拡張してあげる必要がある。
WebComponentsとJSフレームワーク
今年はFirefoxが正式サポートされるなどブラウザの対応も進み、そろそろプロダクションでの採用も増えてきた感があります。
とはいえ、WebComponents単体では
- プロパティが文字列渡しになる
- 再描画の面倒を開発者側が見る必要がある
など辛さがあります。
それを改善すべく、Polymer ProjectからLitElement
というベースクラスが提供されていて、かなり便利にCustom Elementsが作れるようになっています。
とはいえ、WebComponentsは「再利用可能なコンポーネントを作る」ことを目的にした仕様群なので、SPAなどの開発に必要になるルーティングや状態管理などはスコープに入っていません。
Polymer Projectが提供しているPWA Starter KitはこのあたりをReduxと組み合わせたり、自前で開発したりして解決していますが、現実的にはまだ既存のJSフレームワークと組み合わせて使うことになるでしょう。
Reactと組み合わせる
JSの場合
WebComponentsとReactを組み合わせて使うコードは、次のようになります。
import React from 'react'; import ReactDOM from 'react-dom'; import { LitElement, html } from '@polymer/lit-element'; class MyElement extends LitElement { static get properties() { return { name: { type: String } }; } render() { return html` <h1>Hello, ${this.name} !!</h1> `; } } customElements.define('my-element', MyElement); const App = () => (<my-element name="WebComponents" />); ReactDOM.render(<App />, document.getElementById('root'));
customElements.define
に登録したカスタム要素も問題なく使えています。
TypeScriptの場合
このままでも良いのですが、TypeScriptでも使いたいところです。
そこで、コードを次のように書き換えてみます。(デコレータを使ったコードに直していますが、やっていることは同じです。)
import React from 'react'; import ReactDOM from 'react-dom'; import { LitElement, html, property, customElement } from '@polymer/lit-element'; @customElement('my-element' as any) class MyElement extends LitElement { @property({ type: String }) name: string = 'no name'; render() { return html` <h1>Hello, ${this.name} !!</h1> `; } } const App = () => (<my-element name="WebComponents" />); ReactDOM.render(<App />, document.getElementById('root'));
が、このままでは上手く動きません。
[ts] プロパティ 'my-element' は型 'JSX.IntrinsicElements' に存在しません。
コードはほぼそのままなのですが、なぜ動かないのでしょうか?
TypeScriptにおけるJSX(TSX)
先の現象はReactというよりTSXの仕組み上の問題です。TypeScriptではJSXで使用される要素(Reactコンポーネントなどを除く、HTML標準のタグなど)について、JSX.IntrinsicElements
というインターフェースに該当の要素名(今回の例ではmy-element
)が定義されることになっています。
上記のコードだけではJSX.IntrinsicElements
の中にmy-element
が定義されていないのでエラーが発生してしまう、というわけです。
JSX.IntrinsicElementsを拡張する
JSX.IntrinsicElements
に要素名が定義されていないのが問題なら、JSX.IntrinsicElements
を拡張して要素名を追加してあげれば良い、ということになります。
declare namespace JSX { interface IntrinsicElements { 'my-element': { name: string } } }
TypeScriptの型定義において、interfaceはopen-endedなのでわざわざオリジナルのinterface定義を拡張するような宣言をせずとも自動的にオリジナルの定義を拡張する形でマージされます。
型定義を記述してあげることで、TSX上でも補完付きでカスタム要素が使えるようになります。
雑な書き方
とはいえ、「タグ1つ1つに対してこのように型定義を記述するのは面倒だ、とりあえず動くようにしたい!」という場合もあるでしょう。その場合、次のように記述します。
declare namespace JSX { interface IntrinsicElements { [tagName: string]: any } }
このように記述することで、TSX上でいかなる名前の要素でも利用できるようになります。
ただし、当然ながら要素名が誤っている場合のエラー表示や、属性の補完などは一切行ってくれなくなるので、あくまで一時しのぎとして使う程度にとどめたほうが良いでしょう。
まとめ
理屈は分かるのですが、「面倒だなー」というのが正直なところです。とはいえ、ReactとWebComponentsを組み合わせる事例が増えるにつれて同じ面倒さにぶつかる人も増えてくるはずなので、上手いこと解決できる仕組みが登場することに期待しています。
lit-htmlが便利という話
9/22にFukuoka Engineers Day 2018 ~Autumn~というイベントで、2月に開催された同イベントに続いてWeb Components周辺の内容で発表してきました。
そこで取り上げたlit-html
というライブラリが結構便利で最近気に入っているので記事にして紹介します。
lit-htmlとは?
Web Components向けにPolymerというライブラリが提供されているのですが、その開発チームが提供している『HTML in JS』を実現するためのライブラリです。位置づけ的にはJSXに近いものというイメージをしてもらえれば良いかと。
Polymerチームによって提供されていますがPolymerには依存しておらず、単体で利用できます。
npm install --save lit-html
でインストールできます。
使い方
lit-htmlはすごくシンプルなAPIを提供していて、html
とrender
という2つの関数でほとんど完結します。html
でテンプレートを生成し、render
で実際にテンプレートをDOMにレンダリングする、という具合です。
import { html, render } from 'lit-html'; window.addEventListener('DOMContentLoaded', () => { const template = html`<h1>Hello, lit-html !!</h1>`; render(template, document.body); });
上記コードで、bodyタグ直下にh1タグが出力されます。見てのとおり、ES2015のTemplate Literal
をベースにテンプレートを構築していきます。
一見普通の文字列ベースにDOMを構築してinnerHTML
に直接突っ込むのと同じように見えますが、決定的に異なるのは、html
関数を通してlit-html
用のテンプレートに変換され、最終的にDOM APIによってDOM上に追加される点にあります。文字列を直接innerHTML
に設定するのに比べて遥かに安全と言えます。
変数は${}
でバインドできます。
import { html, render } from 'lit-html'; window.addEventListener('DOMContentLoaded', () => { const name = 'lit-html'; const template = html`<h1>Hello, ${name} !!</h1>`; render(template, document.body); });
変数を直接埋め込んでいるだけだと、XSSなどを心配されるかもしれませんが、埋め込まれる文字列は適切にサニタイズされるので問題ありません。
ここまではただTemplate Literal → DOMのみの機能のようですが、いくつか拡張が加えられています。代表的なのは、イベントハンドラ用の構文です。
DOM APIでテンプレートを構築していてイベントハンドラを設定したい場合、以下のようにしなければなりません。
const button = document.createElement('button'); button.addEventListener('click', (e) => { console.log('clicked!!'); });
lit-htmlでは、イベント名に@
を付けて関数を渡すと、自動的にイベントハンドラに登録してくれます。以下のコードは、上記をlit-htmlで記述した例です。
const template = html`<button @click="${(e) => console.log('clicked!!')}"></button>`;
lit-htmlではこの他、
- プロパティ(input属性のvalueなど)用の
.
- プロパティを付与する/しないを制御する
?
などのプレフィックスを提供していて、テンプレートを便利に記述することができます。
lit-htmlの良い点
- シンプルなAPI
- 変数のサニタイズがデフォルトでサポートされており文字列ベースのDOM構築に比べ安全
- DOM APIを直接使うよりコード量が削減できる
- 特別なビルド設定を必要としない(lit-htmlさえバンドルしてしまえば動作する)
lit-htmlの気になる点
- テンプレートを文字列で記述するので補完などのサポートが微妙(拡張でハイライトなどは効くがEmmetなどが使えない)
イベントハンドラ以外に関数オブジェクトを子要素に渡す方法がないdirectiveでできましたね。すみません。- まだベータ版なので、APIが変更される可能性がある&既存のソースが古く動作しない場合が多い(一応)
lit-htmlの今後
AngularやReact、Vue.jsが普及していてそれぞれが独自にテンプレート構文を持っている現状、lit-htmlのような独自のHTML in JSライブラリなんてどこで使うのか?という話なんですが、それらのライブラリを使っている場合はそこに導入する必要はないです。(というかしない方が良い)
やはり主な使い所Polymerでの開発(というかWeb Components開発)になってくるのではないでしょうか。Polymerは次世代の基本クラスとして@polymer/lit-element
というものを開発中で、これは名前の通りlit-html
をベースにしています。ReactがJSXならばPolymerはlit-html、といった具合になるんじゃないかと。
とはいえ特別な環境構築不要で手軽に使えるHTML in JSのライブラリで、1時間もあれば習得できるくらいシンプルなので目を通しておいて損はないんじゃないかと思います。
最後にちょっと宣伝
この記事で紹介したlit-htmlの内容も含むWeb Components本『Web Components First Book』を、池袋で開催される技術書典5というイベントで頒布予定です。Web Componentsの他、
と色々なジャンルを揃えて参加します。
フロントエンド以外にも幅広いジャンルの技術系同人誌が集うイベントで、私は今回これまでとサークル名を変更して参加しますが、福岡からは前回爆売れしたとうわさのneko-noteも引き続き参加しています。こちらは
ネタだそうです。
非常に楽しいイベントなので私の本に興味を持ってもらえた方もそうでない方も、お越しいただければ嬉しいです!