Hyperappでhead内のタグを書き換えるライブラリ、Hyperapp Helmetをリリースしました!
はじめに
Hyperapp Helmetという、Hyperappフレームワーク用のライブラリをリリースしました。
Helmetとは、React Helmetが有名/はしりですが、<head>タグの中を書き換えるコンポーネントのことを言います。
昨今の検索エンジンbotはJavaScriptを解釈しますので、SSRはOGP/Twitter Card対応のためにあると言っても過言ではないと思います。その時に、ページ内容に合わせた<head>内タグの書き換えが必要になりますが、Hyperappにはそれに対応するライブラリがありませんでした。これで最後のピースが埋まった!
特長
Hyperapp Helmetは以下の特長を持ちます。
- @hyperapp/render対応。
renderToString()
だけじゃなく、renderToStream()
でSSRする時も使えます。 - @hyperapp/router対応。JSDOMと併用することにより、サーバサイドでも、ルーティングに合った<head>内タグの書き換えができます。
- ネスト対応。親・子・孫……コンポーネントそれぞれで定義した<Helmet>が全て<head>内タグに反映されます。
- TypeScript対応。
インストール
$ npm install hyperapp hyperapp-helmet or $ yarn add hyperapp hyperapp-helmet
使い方
公開メソッドは2つしかないので、README.md読めばわかると思いますが、軽く紹介しておきます。
<Helmet>
任意のコンポーネントで使える。<Helmet>タグで囲まれた部分が<head>タグの中に挿入される。key
アトリビュートが必須。
import { h } from 'hyperapp' import { Link } from '@hyperapp/router' import { App as A } from '../App' import { Helmet } from 'hyperapp-helmet' export const Counter = (): any => (state: A.State, actions: A.Actions) => ( <div key="counter"> <Helmet key="counter-helmet"> <title>Counter: {state.count}</title> <meta name="description" content="Number Counting Page" /> </Helmet> <h1>{state.count}</h1> <button onclick={() => actions.down(1)}>-</button> <button onclick={() => actions.up(1)}>+</button> <div> <Link to="/about">About</Link> </div> </div> )
getHelmetNodes(view, state, actions) => VNode[]
アプリケーションのビューを探索し、該当の<head>内タグのVNodeの配列を返す。
import { h, View } from 'hyperapp' import { App as A } from './App' import { getHelmetNodes } from 'hyperapp-helmet' const Fragment = '' export const Html: View<A.State, A.Actions> = ( state: A.State, actions: A.Actions ) => { const helmetNodes = getHelmetNodes(A.view, state, actions) return ( <Fragment> <Fragment innerHTML="<!doctype html>" /> <html lang="ja"> <head> <meta charset="utf-8" /> <meta name="viewport" content="width=device-width, initial-scale=1" /> <script src="/index.js" defer /> {helmetNodes} </head> <body> <div id="app">{A.view}</div> </body> </html> </Fragment> ) }
こんだけ! サンプルプロジェクトを公開してあるので、動かして見てください。
開発
せっかくなので、小話をば。
経緯
- 小さくて速いウェブアプリが作りたいな〜
- Reactはエコシステムが大きいから開発が早いけど、サイズがデカいしな〜
- おっしゃ、Preact挑戦してみたろ
- この
preact-compat
っての入れるとReact用のライブラリが使えるが、サイズがデカくなるぞ? う〜ん…… - そういえばHyperappってのがあったな?
@hyperapp/router
でルーティングもできるし、@hyperapp/render
ってやつでSSRもできる。全部小さい! ええやんけ!- (素振りリポジトリを作ってみる)
- えっ、HyperappにHelmetないの? マ? 今時SSRはOGP/Twitter Card対応だから意味ないやんけ! う〜ん……
- せっかくだし、作ってみるか!
実装
そんな難しいことはしてないのですが、迷いながら実装したところがあるので、説明させてください。
具体的には2点あり、 1. <Helmet>コンポーネントが<template>タグを返し、それがレンダリングされる。 2. <head>内タグの更新のとき、一旦全削除して、全追加している。
まず、1についてですが、Reactコンポーネントと違って、Hyperappのライフサイクルメソッドは外挿なんですよね。なので、なんらかのノードを返す必要がありました。
最初は<div style={{ display: 'none' }}>{children}</div>
を返していたのですが、<div>の中に<title>とは入ってるのかっこ悪い……となって一度はchildren
を書き出さず、空の<div>だけ返してました。しかし、SSRをするに当たってノードを探索・解釈してみたんですが、実際にはマウントされないため、oncreate
ライフサイクルメソッドが実行されず、タグを格納するグローバル変数に入らないという問題が発生しました。
というわけで、またchildren
を書き出す実装に戻したんですが、上記の通り気味が悪いので、実際には表示されないエレメントは何かないかと探したところ、<template>が見つかりました。これなら<title>等があっても違和感が少ないと考え、これを使うという選択をしました。
現在の実装ではテンプレートとしては使ってないのですが、将来実際にテンプレートとして使って、<head>に流し込むというのもありうるのではないかなと思います。
次に、2についてですが、最初は実際に書き出したエレメントと架空のノードとの差分をとってパッチを当てる実装にしてたんですが、これだと、props/state変数をタグに使用したとき、同定が難しいという問題が発生しました。
ユーザーに逐一key
を設定してもらえば同定できるのですが、それは手間だろうということで、現在のように、<Helmet>毎に全削除&全追加という実装になってます。
おわりに
このライブラリを使うことにより、HyperappでSSRするに当たって、最後の障害がなくなったと思います。ぜひ、使ってやってください。
このライブラリを作るにあたり、@r7kamura 氏のkatatemaを参考にしました。氏にはTwitterで助言を頂いたりして大変お世話になりました。ここにお礼を申し述べます。
よし、これで次はアプリに取りかかれるぞ〜
『カンバン仕事術』を読んでいる3
6章 WIP制限を読んだ。
「デヴィッド・P・ジョイス」が誰だかググッてもよくわからなかった。
おーっ、人にWIP制限をかけるとか、作業項目をタスクに分割するとか、自由度が高い! 物理強い!!
- 作者: Marcus Hammarberg,Joakim Sundén,原田騎郎,安井力,吉羽龍太郎,角征典,?木正弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/03/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
ポスト・イット 強粘着ノート 75x100mm 90枚x混色10個 6571SS-NE
- 出版社/メーカー: 3M(スリーエム)
- メディア: オフィス用品
- この商品を含むブログを見る
『カンバン仕事術』を読んでいる2
5章 仕掛り作業を読んだ。WIPについて。
チケットに付ける[WIP]と紛らわしそう。「チケットのWIP」「カンバンのWIP」って呼び分けるのかな。それとも前者をWork in Progress、後者をWork in Processと呼び分けるのかな。(追記:角さんのTwitterでのツッコミで、「開発」列を「プルリクエスト」列と「マージ」列に分割すれば「チケットのWIP」などと呼ばないでいいことに気づいた)
「システムのヘルニア」のところでウッとなった。今作ってるやつもバグじゃないけど正しい実装とは思えないのが3つぐらいあって絡まり合ってる。
- 作者: Marcus Hammarberg,Joakim Sundén,原田騎郎,安井力,吉羽龍太郎,角征典,?木正弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/03/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
ポスト・イット 強粘着ノート 75x100mm 90枚x混色10個 6571SS-NE
- 出版社/メーカー: 3M(スリーエム)
- メディア: オフィス用品
- この商品を含むブログを見る
Clojureを勉強している20
4clojureの問題はギブアップして最後の章やった。難しくて億劫になってしまったもんで。
Clojure 1.7.0から入ったtransduce
の説明だった。
これにて終わり。
- 作者: Carin Meier
- 出版社/メーカー: O'Reilly Media
- 発売日: 2015/04/14
- メディア: Kindle版
- この商品を含むブログを見る
『カンバン仕事術』を読んでいる1
いまのところ4章まで。おもろい。特急レーンのとこで「おっ、頭いいな。なるほど〜」と思った。
4章の作業項目カードは全部はできないなと思った(全部やる必要ないと書いてある)。既に買った付箋がそんなに大きくないので。Post-itの75x100mmのを買ったんだけど、もう一つ上のサイズの方がいいかもしんない。Amazonで見る限りは150x100mmは色のバリエーションがない。
- 作者: Marcus Hammarberg,Joakim Sundén,原田騎郎,安井力,吉羽龍太郎,角征典,?木正弘
- 出版社/メーカー: オライリージャパン
- 発売日: 2016/03/26
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (2件) を見る
ポスト・イット 強粘着ノート 75x100mm 90枚x混色10個 6571SS-NE
- 出版社/メーカー: 3M(スリーエム)
- メディア: オフィス用品
- この商品を含むブログを見る
『リモートチームでうまくいく』を読んだ
手を動かさないでよい本も読むことにした。
内容なんですが、流石実践者ということで一日の長があるな、と感じた。特に、2章3節の「オフィスにあってリモートにないものを補完する」が面白かった。オフィスにはある「存在感」「雑談」などを試行錯誤でリモートに導入する試行錯誤。恐らくこれで完成ではなく今も時おり改良が進んでいるのだろう。
また、2章5節で外部とのやりとりはメールは非同期メッセージングとして優秀だが記録・多人数での参照などで不完全なので「掲示板のようなもの」を作り使ってるというのがなるほどなと思った。私も受託開発してたときがあるんですが、メールだと重すぎるんよね。
リモートハッカソンとリモート飲み会はどうやろと思ったけど、これまた実践者ならではの細々とした諸注意がある。
あと1つ懸念点があって、同じ時間に作業するってのがどうにかならないものかと思った。オープンソースの開発みたいな感じだとやはりスピードは失われるような気もするし。半日分ぐらいいいやみたいな判断ではどうか。スピードはともかく、顔を見ながら作業できないというのはやはり厳しいか。う〜ん。
リモートチームでうまくいく マネジメントの?常識?を変える新しいワークスタイル
- 作者: 倉貫義人
- 出版社/メーカー: 日本実業出版社
- 発売日: 2015/12/17
- メディア: 単行本(ソフトカバー)
- この商品を含むブログ (1件) を見る
はじめに 第1章 リモートチームという古くて新しい働き方 第2章 リモートチームが実践している習慣と環境づくり 第3章 リモートチームの成功は企業文化にかかっている 第4章 リモートチームで変わるマネジメント 第5章 リモートチームで変わるワークスタイル 第6章 リモートチームで起きる課題を解決する 第7章 リモートチームに至るまでの道のり おわりに
Clojureを勉強している19
- Week3
- Day 1
- To Tree, or not to Tree
- バイナリツリーのチェックかー。3要素のコレクションだったらいいのかな?と思ったらfalseと空リストはアカンっぽい
- できた。
- Beauty is Symmetry
- 安直に95の条件に
(= (second t) (last t))
を加えてみたが4つ目で死んだ。シンメトリックだからleftとrightが入れ替えなあかんのか - アカン。解けんかった。我慢できずに他の人の答え見た。我慢が足りない。
- 安直に95の条件に
- To Tree, or not to Tree
- Day 1
- 作者: Carin Meier
- 出版社/メーカー: O'Reilly Media
- 発売日: 2015/04/14
- メディア: Kindle版
- この商品を含むブログを見る
- Chapter 10 Weekly Living Clojure Training Plan
- How Do I Use This Training Plan?
- What If I Miss a Day or Two?
- What If I Don’t Understand the Exercise?
- Week 1
- Week 2
- Week 3
- Week 4
- Week 5
- Week 6
- Week 7
- Congratulations