Code

2017年4月22日土曜日

Server Side Rendering の注意点

 いろいろ契約上の問題で、今のプロジェクトは Server Side Rendering 使ってないですが、個人趣味でいろいろやってました。React.js は JSX を使って、DOM を作ってるので、AngularJSに比べて、Server Side Rendering に向いています。
 まず参考として、下記の記事があります。
 もし ReactRouter 使ってない場合、これはさらに簡単になります。React には renderToString, renderToMarkup などの関数があります。それを使って、props などを設定すれば、自然に HTML string が出来上がります。こちらは注意すべきところは ajax を使って、データを lazy load する場合です。
 Server Side Rendering を使ってる場合、componentDidMount が呼び出されないので、この中に使ってる ajax は当然呼び出されません。解決方法としてはまず isomorphic-fetch を使って、データを取得します。その promise then 関数の中に、React.js Component を render します。また、componentWillMount が呼び出されるので、その中で ajax call してもいいような気がしています。ただし、fetch してから react component を render するほうがよいと思います。
 また、一つ注意すべきところは、data の取得はできるだけ store と関係あるところでやりましょう。なぜなら、Server Side Rendering するとき、window.__data__ に初期 data を client side に渡す必要があるため、componentDidMount が呼び出されないので、自分で data の取得をいちいち洗い出して、自分で呼び出す必要があります。もし、service layer を作って、例えば、config data を取得する際に、いつも service.loadConfig 関数を読んで、その中に dispatch をすれば、store を返して、アプリの更新ができますし、Service Side Rendering の時も、通常通り、その関数を読んで、store 中の値をそのまま保存すれば、いいので、便利です。
 Node と Express を使ってる場合、require('react'); は react 直接ロードできますので、かなり便利です。だから、Node Express を使って、thin layer を作って、Web の Edge Layer として使ったほうがいいような気がしています。これで、API layer とも、Client Side ともスムーズに連携できるようになります。
 また Redux は pure javascript なので、普通に使えますし、サーバーサイドで実行する場合も当然 Client サイドと同じです。あまり気をつける必要がなさそうです。

 最近、React.js は結構流行ってます。preact とか、twitter lite とか面白そうなものが出てきました。次は Progressive Web App の時代かと。Safari は早くサポートしないとな。。。

 それでは。また。

2017年4月7日金曜日

Webpack 2 を使ってみた

 最近、なかなか時間が取れなくて、困ってます。プロジェクトも色々大変な事になって。。。
 唯一いいことは Webpack 2 にアップグレードする事になりました。まぁ、やってる方はとても若いので、いつできるかはまだわからない。
 Webpack2を使うと、自動的に code splitting をやってくれたり、css ファイルも<head> に入れてくれたりします。まぁ、いろんな loader を使う必要がありますが。
 その中の HtmlWebpackPlugin はかなり使いやすいです。なぜなら、HTML を書かないで、webpack は自動的に作成して、bundle した js ファイルや css ファイルを入れてくれるからです。
 それに、loader も使ってくれるため、handlebars などのテンプレートも簡単に変換してくれます。
 もしもう少し自分で作成された HTML をコントロールしたい場合、options 中の template を js ファイルにせってして、js から HTML code を作成する関数を export して置けば、その関数が呼ばれるので、色々便利です。
 さらに、 もし React.js を使ってる場合、react-to-html-webpack-plugin も使えるので、パワフルなツールになります。

 ほかに、Webpack 2 も dev server がついています。dev server を使うと、必要なリソースが動的に作成して、hot reload 機能も使えるようになります。これは便利の一言。
 さらに、Express を使っている場合、Webpack もサーバー側のファイルを一つファイルにまとめることができます。これは Server Side Rendering を使うとき、Client サイドのコードをそのままサーバー側に実行することができます。
 また環境ができたら、後日詳細をメモしておきます。

2017年3月11日土曜日

a11y - アクセシビリティ

 最近引っ越しのため、あまりパソコン使ってませんでした。iPhone とiPad は確かに便利です。
 昨日、アップルからのアクセシビリティレクチャーを参加しました。前では、あまり知らない機能など、なぜアクセシビリティを重視するかを勉強しました。
 例えば、アクセシビリティを実装することで、どんなユーザでも使いやすくなります。色のコントラストは目の不自由な方だけではなく、通常のユーザも多大な影響があります。
 そして、幾つか認識間違いがちなところを書こうと思いました。
 まず、アクセシビリティは Screen Reader のことだけではないし、aria 属性を使うことだけではありません。キーボードのみでウェブサイトを操作できることや、色のコントラスト、文字の大きさなどもその範囲内です。
 ただ、一番難しいものはやはり Screen Reader の対応です。基本的に、NVDA や Jaws、アップルの VoiceOver に対して、各ブラウーザーはインターフェースを提供していますが、実装により、いろいろ違いがあります。そこで、HTML タグで解決できないものを aria 属性を使うことです。
 HTML は基本中の基本です。まず、一ページには各メインコンテンツにジャンプするリンクを入れたほうがいいです。Tab キーを押すと、隠しているリンクを画面 上に表示して、ページ中のコンテンツにジャンプします。
 次、header, h1 - h6, nav, fieldset, label, form の HTML コードはできるだけ正しく書かないといけないです。screen reader を使うユーザーは主にショートカットキーを使うので、Jaws の場合、Insert + H ですべての h1 - h6 のタグをリストすることができます。同じように、一つのキーですべてのリンクをリストして、一つ一つ見て、好きなところに行くこともできます。だから、リンクはできるだけ意味を持った文言を使わないといけません。"Learn more" とか全然わからないものを使わないでおこう。
 そのあと、もし HTML のタグが解決できないことを Aria 属性と JavaScript を使うことです。例えば、pop up dlg の tab order や、aria-live を使って、ユーザーに画面に何か起こったかを知らせるとか。いろいろあります。
 最後に、特殊のデバイス対応する場合、特殊のことをしないといけない。例えば、auto complete など複雑な Input を機能を説明するために、aria-label などを使うとか。
 
 それでは、後日また。

2017年1月29日日曜日

React Component の Render 関数を変更

 先週、作ってる Web App が別のサイトに入れることになりました。機能としてはそのままですので、JS ファイルをロードすれば ReactDOM.render () 関数を呼び出して、CSS もロードすれば、そのまま Component が動くので、とても便利です。ただ、そのサイトの Analytics 仕組みが今まで使ってるものと違って、<a> や <button> などには data-tracker-type とか、Analytics 専用の属性を追加しなければならない。
 つまり、入れる場所により、render する Component の HTML が少し違います。まぁ、一番思いついた方法はやはり、一つの <a> や、<button> を探し出して、属性を追加するだけです。ですが、これは根本的な解決方法ではありません。なぜなら、開発者にとって負担になるからです。
 本来、プログラミングで解決できる問題は、力でやるのはあまり良くないのです。もう一つの方法としては、property を childContext とか、そのまま各 Component に設定して、render 関数の behaviour をその property を読んで、変更すると。
 property をパスとかいろいろ面倒だから、さらに変更方法を調べてみました。そこで、render 関数を直接変更したほうがもっと簡単だろうと。具体的には、react.createClass(spec) 関数で返された instance には type という実際の Component が含まれています。
 component.type.prototype.render は定義された render 関数です。
 DOM に render する前にその render を変更すれば、そのタイプの Component の HTML も変わります。
 後日また詳細を。それでは。

2017年1月14日土曜日

React.js Component stateless から stateful に変更に伴う問題点

 今週、新しい機能を実装しているうちに、ある Component を Stateless から Stateful に変更しました。その Component を使っているところはあまり変わりがないと思いました。ただ、テストすると、ちょっとだけ不具合が発見しました。
 React.js は Component を更新する際に、もし _owner, key と component の type 変更がなければ、その Component を再利用して、HTML も再利用します。ここで、再利用される Component はもし State を持っている場合、その State は更新されません。もし何か State にある変数を更新したい場合、自分でやるしかないです。ここで、componentWillReceiveProps () 関数が利用して、setState を呼び出して、変数を更新します。
 componentWillReceiveProps では、setState を呼び出しても、実際は一回の Render にまとまります。かなり便利な関数ですね。

 ネットでは、毎回 key を変更すれば、React.js は毎回新しい Component を Mount するので、心配しないで済むとの方法もありましたが、新しい Component を作るにはまたいろいろコストがあるので、前のものを再利用したほうがいいでしょう。

 React.js の中に、Component を更新する方法は setState と新しい Props を渡す、forceUpdate() を呼び出す3種類しかないし、forceUpdate() はあまりおすすめできないし、setProps もないので、setState をうまく使わないといけないです。
 これでまたいつ Component は state を持つべきかとの原点に戻りました。Redux を使うと、store の中に state を置いて、その state と関係あるところは container を通じて、自動的に更新されますが、ただ、それは app 範囲の state の方です。state を持ってる component があまり向いてないようが気がしています。なぜなら、store は個別の component の state を持ってると、もし同じような component 複数ある場合、別の reference を使わないといけません。あるデータをある component のものと示すためです。
 この場合、Wrapper を使ったほうがいいようなが気がしています。state に入れるものは親 Component を持っていて、前の stateless の component も残したほうがいいでしょう。これで、state がいるかどうかによって、使い分けもいいでしょう。とにかく state を持ってない component が再利用しやすいから。ネットでは presentation component という design pattern もあります。こちらは render のみ提供する component と lifecycle 関数や、state を操作する関数を別の component に入れて、container component 両方分けて、どっちでも再利用しやすくするための方法です。
 それでは。

2016年12月29日木曜日

Website Performance checklist

 Smashing Magazine から:
 Front-End Performance Checklist 2017

 いくつか Quick Win アイテムがリストされています。その中に website を 3 秒以内ロードするとか、会社のパフォーマンスチェックチームも実施していますが、Critical Path とかは特に考えてないようです。なぜなら Adobe の AEM を使っているので、古いサイトの新しいコンポーネントベースのページが両方存在していますため。予算がないので、この2、3年は変わらないでしょうと。
 しかし、その中に、古いサイトが残していても、実施できる項目も結構あります。例えば、画像の最適化とか、FOUT / FOIT など Font 関係の Fix とか。まぁ、HTML, CSS など古いサイトでも、新しいサイト共通の部分は結構あるので、それらを精査して、一つ一つやれば、だんだんサイトが速くなります。
 JavaScript に関しては、モジュール化が絶対必要です。Tree Shaking や Code Splitting などを使って、使わないコードを最終 JS に含まないことも可能なので、ぜひチャレンジしていきたいです。例えば、Modernizr にはいろんなテストがあって、実際はほんの1、2個の Class が使われています。その他のものが必要ないので、Front End に Ship することももったいないです。
 これからも HTTP2 を考えないといけないなと。

 それでは、Happy new year!

2016年12月10日土曜日

React.js stateful component 独自で更新可能

 最近、React.js の Component を作るとき、属性を親から、子や 孫 Component まで渡すにはちょっと面倒だなと思いました。Component Tree が大変深いからです。。。
 それで色々調べて、考えました。まず解決方法として、React.js には ChildContext という概念があります。まず親でどういうデータを Context に設定するかを指定して、孫の Component などは ContextType を定義すれば、this.context でそのインスタンスがアクセスできます。しかも shouldComponentUpdate に第三の引数が nextContext となっています。ただし、もし孫の Component と親の間に、shouldComponentUpdate が false を返す親がいると、孫が更新されません。。。これは最大の問題です。
 今アプリの作りでは、childContext はちょっと使いにくいです。。。

 次となる方法としては Redux を使って、子や孫 Component に store と直接連携するようにして、もし何か state 変更が発生すれば、store からの Event がトリガーされます。これはとっても便利ですね。具体的には store からのデータを孫 Componet の state に保存して、ajax call や、どこかの View でイベントが発生したら、Redux store が自分の state を Reducer で更新して、イベントを登録している Component には送ります。その Component のイベントハンドラーで setState() を使うと、その Component のみ更新されます。とても便利です。

 それで、もう一回 React.js Component の仕組みを考えてみると、完全に独立で自分を動けます。他の Component や、アプリ他の部分と関係ありません。別に親は普通の HTML Div でも、React Component でも、Angular Directive でも。

 これはアプリが一定程度に複雑になった話しです。通常であれば、属性で関数とかを子や孫に渡すべきです。

 それでは。