Code

2017年7月8日土曜日

Observable Lib Rx.js ってなに?

 結構前から、Microsoft が Observable という概念の元に、いろんな Lib を開発し始めました。そのあと、約 3 年前、Rx.js が出てきました。いわゆる Reactive Programming の JavaScript バージョンです。Angular 4 は基本的に Observable を使って、Data Binding を行なっています。
 Rx.js 今のバージョンは 4.0 です。Netflix のエンジニアが 5.0 を開発しています。Observer Pattern を元に、Browser の Scroll Event や、Promise、Array などのデータタイプから Observable に変更する関数がありますし、map、filter などデータの操作関数、flatMap, flatMapLatest などの関数も実装されています。
 Event Stream を操作するので、やや抽象的ですが、実際使ってみると、そんなに難しいことではないそうです。
 例えば、ajax 関数を使うと、request を送って、response が帰ってきたら、subscribe() したlistener 関数を自動的に呼び出します。一見 Promise と変わらないですが、Event になると、結構変わります。
 例として、
    obs$.debounceTime(500)
    .map(ev => ev.key)
    .distinctUntilChanged()
    .scan((acc, one) => acc + one)
    .subscribe(term => this.search(term));
debounce などの機能は簡単にできます。

 それだけではない。Observable は chain, merge, zip などの関数もあるので、複雑な操作は簡単にできます。
 例えば、Promise ではできない、ajax call キャンセルするという機能も簡単にできます。

 ただ、Rx.js Lib かなり大きいなので、使う時は、こまめに operator など import すべきです。
 それでは。

2017年6月25日日曜日

アクセシビリティよくある間違い

 先日、新入社員というか、ジュニア開発者に対して、チームレベルのアクセシビリティ研修が行われました。結構効果的でした。一番聞かれたことはどうやって Form を実装するか、Screen Reader はどう使うかと。
 その中に、ちょっと理解の間違いが気づきました。一つはアクセシビリティは Screen Reader のことを全てだと思われているそうです。アクセシビリティはそれだけではありません。キーボードのみユーザーや、目に障害ある方や、いろんな対象があります。
 実は良い HTML を書けば、自然に Screen Reader が動きます。aria の属性は通常の HTML tag や、属性が動的ではない場合、転用された場合を使うのので、メインではありません。例えば、HTML に fieldset という tag があります。それはラジオボタンなどを一つの括りとして表示する場合使います。それを使うと、 Screen Reader は自然にそれを認識して、Role - Function - current situation の順に読みます。もし div タグを使うと、通常のコンテンツとして認識しますので、同じようには読みません。ラジオボタンの選択を変更する場合、何が読まれたかをよく聞いて、すぐ区別がわかります。
 次に、全てのコンテンツが tab キーで読ませると。それは間違っています。tab キーは interactive element のみ stop します。もし、むやみにすべてのコンテンツを止まるようにしたら、それは通常と違うので、逆にわかりづらくなります。例えば、a tag など、href があれば、tab stop は起きます。順番として、top - bottom, left - right に stop すべきです。
 ユーザーは通常 Shortcut key を使って、例えば、Insert - L とか、画面にある全部の a link をリストして、画面に表示します。これは [learn more] という link が良くないことをわかるはずです。コンテキストがわからないから、learn more というのは何の more になるかわかりません。だから、ボタンなら button を使って、link なら a tag を使うべきです。
 最後に、色の Contrast Ratio も注意すべきですし、文字のサイズも対象です。それに、High Contrast モードもあるので、それを使うときのサイトも一度チェックした方がいいでしょう。
 まぁ、Screen Reader だけ対象にすべきではないです。

 ちなみに、Screen Reader を使うとき、IE を使うべきです。驚くかもしれませんが、今 JAWS とか Chrome でのサポートが IE ほど良くありません。全て一つのブラウザーでテストすべきではないです。
 それでは、また。

2017年6月10日土曜日

Angular 4 vs React.js vs Polymer and some thinking of component

 # I posted the same article on Medium, and will use Medium from now on.
https://medium.com/@newying61/angular-4-vs-react-js-vs-polymer-and-some-thinking-of-component-596085325d5

 This week, I got some time to have a look at Angular 4 and Polymer, the two frameworks for developing component based SPA. As I have used React.js for about 2 years, just wanted to write down what I feel about these two comparing with React.
 First about Angular 4. It is said to be component base, but when I saw other projects which are using it, I just feel, it's kind of like Angular 1. Component becomes controller, and all the logic are still in services. Also, it's quite confusing about directives, when and where to use it...
 I should say, Angular 4 's learning curve is too high, and if you use it, it's very easy to get effected by the former experience with Angular 1.
 For Polymer, it's quite well organised and because of it's shadow dom is a standard, it can make HTML so easy to understand. Although, it has two way bindings just like Angular, it is still a UI library, not like Angular as a framework.
 So, Polymer can easily re-organised with Redux by adding a store component and pass it anywhere by using a singleton pattern.
 Compared to React.js, I think Polymer may be a good competitor. It also batch the changes to DOM and can make some operations easier by two way binding.

 Then I started to think about what component means for SPA. React.js and Polymer let you define a component and by wrapping it with other components or using higher order components you can organise an app with good structure. Angular 4 can do the same thing, but compared the effort, I would say, React.js and Polymer are much better.
 A component should be kind of dumb, which means it should only care about itself and only work with the attributes passed in. It can has it's own state (state in React.js component and property in Polymer component) to control how it looks like.
 Also, it doesn't care about what it's children looks like. By wrapping anything, we can just create a new component with new functions.
 This can dramatically increase the usability of the components. We can use it anywhere and it should just work. :)
 Also by doing this, it can easily integrate with other libs like Redux to control model data.
 A warning is, if a state is only related to a specific component, then it should not be put in store, don's abuse Redux to store everything.

 A good example is Polymer's iron-page, by defining the selected attribute and the target attribute, it just select the right child component and add a new attribute to it.
 The same as react-router, just define the structure, and it just work.
 By the way, compared to these two, Angular 4's router is kind of ugly. It needs a json object... which is not direct at all...

2017年5月7日日曜日

How to use React-Intl to format multiple message id

 Recently, I am working on some project using React-Intl to format strings. One of the bad things about it is, the FormattedMessage component only support one id and a long message. When you want to combine several short messages together, it's kind of hard.
You have to use something like this (please refer react-intl document):

<FormattedMessage
    id="welcome"
    defaultMessage={`Hello {name}, you have {unreadCount, number} {unreadCount, plural,
    one {message}
    other {messages}
    }`}
    values={{name: <b>{name}</b>, unreadCount}}
/>

When you want to do something like format aria-label for a button, you have to wrap a function:

<FormattedMessage id="aria-label-id" defaultMessage="label">
    { (label) =>
          <button
            type="button"
            className="test"
            aria-expanded={expanded}
            aria-label={label} />
    }
</FormattedMessage>

In fact it's quite hard to use, also the format makes it difficult to read if you have a lot of buttons to render.

An easy way to avoid this is to use it's injectIntl function to wrap your component, like this:

import {injectIntl, intlShape} from 'react-intl';

const ButtonComponent = ({className, intl}) => (
    <button className={className} aria-label={intl.formatMessage({id: "aria-label", defaultMessage="test"})}>
        <span>Button Icon</span>
    </button>
);

ButtonComponent = {
    date: PropTypes.any.isRequired,
    intl: intlShape.isRequired,
};

export default injectIntl(ButtonComponent);

 injectIntl will create a wrapper component for the ButtonComponent, which will inject a childContext with locale and message information. Also it inject the intl prop for using.
By this intl prop, you can use the APIs like formatMessage (which is used inside the FormattedMessage component).

 When you want to use multiple messages to combine together to be a string, currently, there is no good way to do it, as far as I read the documents and looking into the examples.
So I created something to do it:

class Formatter extends React.Component {
    static defaultProps = {
        as: 'span'
    };

    constructor(props) {
        super(props);
        this.getFormattedMsg = this.getFormattedMsg.bind(this);
        this.formatMessage = this.formatMessage.bind(this);
    }

    getFormattedMsgWithValue(match, p1) {
        const { intl, defaultMessage } = this.props;
        return intl.formatMessage({ id: p1, defaultMessage });
    }

    formatMessage(msg) {
        return msg.replace(/@{([\w]+)}/g, this.getFormattedMsg);
    }

    render() {
        const { intl, as, ariaLabel, children, ...others } = this.props;

        if (children) {
            if (typeof children === 'string') {
                others.childre = this.formatMessage(children);
            } else {
                others.children = children;
            }
        }

        if (ariaLabel) {
            others['aria-label'] = this.formatMessage(ariaLabel);
        }

        return React.createElement(as, others);
    }
}

export default injectIntl(Formatter);
 
Then you can use this Formatter function like this:

<Formatter as="button" className="btn" aria-expanded={expanded}>
    {`@{label-id} ${otherParams} @{another-label-id} ${others}`}
<Formatter>

Or you can just wrap some children like this:

<Formatter as="button" className="btn" aria-label={`{@{aria-label-id} others`}>
    <span className="btn-icon arrow"></span>
<Formatter>

If you want to format with values, just change getFormmatedMsg like the following:

    getFormattedMsgWithValue(match, p1) {
        const { intl, defaultMessage, values } = this.props;
        const targetValue = (values && values[p1]) || {};
        return intl.formatMessage({ id: p1, defaultMessage }, targetValue);
    }

Will raise a pull request for the FormmattedMessage component in react-intl later, when I got enough time to make it properly.

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 でも。

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

 それでは。

Akamai Bad Request (400) Restful API Delete method

 TL; DR: If you don't have time to find the root cause, just change Delete method to Post.

 In the past several weeks, we were experiencing an issue with Akamai: in a special sequence like Get + Delete + Get, or Post + Delete + Post, the request after Delete returned a Bad Request with reference no (xxxx.xxx.0) from Akamai edge server. But it never happened in our own environment, even the prod evn behind Akamai.

 We had some meetings with Akamai support engineers. They suspected that there may be some function keeping the HTTP connection with their edge server. At first, they thought our endless scrolling function caused the issue. But in fact we just load more data at the first time, then render only the first part of the data in the screen. When user scroll, we load other parts.

 After they checked their log, they found browser is using the same TCP connection for our Delete request. Which happens in the following case:
   Get /favourites  => setting up a connect with content-length some number
   Delete /favourites/{id} => using the same connection, with content-length xxx
   Get /favourites => bad request (400) from Akamai

In this case, Akamai edge server is sending Keep-Alive header to browser, so browser may use the same TCP connection to send the Delete request => Akamai edge server counts Delete request content-length as something not correct => edge server is waiting for more data from the next request => so next Get doesn't count as a separate request, and because it doesn't match what edge server expects, edge just returns 400 bad request to browser.
(It happens as if something like nullPost, nullGet when content-length is not correct - by support engineers).

 Their explanation sounds reasonable, but I used Fiddler and Wire Shark to check the content-length for all the requests,  couldn't find any incorrect data. All numbers seemed to be correct.

 We didn't have enough time to look into this issue further, and thinking of the request after POST never fails, I changed our Restful API Delete method to Post. This fixed everything.

 I am still not sure where the problem is, but at least changing Delete to Post makes everything good...

 Hope in the future, I can get some chance to make this clear. :)

2016年11月12日土曜日

良い HTML を書こう

 最近 AEM 開発チームと一緒に仕事をしています。Front End に関してはみんな多少知っていますが、本物の Front End Dev ではないため、まぁ、結構な数の Front End Dev も Bad HTML を書いているようです。日々勉強しないと。
 さ、良い HTML ってなんでしょう?結構大きいテーマだから、とりあえず、自分の考えをリストしよう:
 ー HTML ページ全体的な構造がわかりやすく、無駄がないこと、すべての HTML Tag が正しく使われていること。例えば、<nav> や、<aside> などのタグ、とページ全体が上から、下へ、要素がロジックにあってるとか。
 ー Content First 主義。JavaScript 使ったり、CSS アニメーションを使ったり、ページは綺麗になりますが、Content はやはり第一です。ユーザーが JS を disable にすることもあるし、イメージをダウンロードしない設定もあるので、UK では 2% のユーザーがその部類らしいだそうです。(隣の Designer さんに聞いた話しです。)だから、JS などに拘らず、ページの Content はどこでも、どんなデバイスでもわかりやすく伝えられるならいいでしょう (Responsive は実は大変重要)。
 ー Accessibility は正しいこと。ページ全体の h1 や、h2 などが正しく、HTML タグに意味が正しく、どうしても HTML だけで難しい場合、ARIA 属性が正しいこと。HTML は実はそれほど動的ではないので、tab や、アコーディオンが Tag のみで難しいです。それで aria-hidden や aria-expand に使う必要ですね。
 ー ページ全体が Browser で軽くて、速いこと、いわゆるパフォーマンスが良いこと。100 ms 遅くなると、5% のユーザーを失うという記事がどこかで見たことがあるようです。具体的な数字は覚えてないけど。
CSS を <head> に、JS を <body> にロードするとか、minify とか、とにかくページを速くしないと。
 
 まぁ、ページのデザインなども重要ですが、HTML としては上記実現すれば、良い HTML だと思います。

 それでは。また後日何か思いついたら、追加します。

Pokemon Go にはまってる。。。

 Poke Index を完成するために、770 km 走った。

2016年10月16日日曜日

element.href と element.getAttribute('href') の区別

 先週、一つのバグを発見しました。まぁ、強いといえば、Back End の問題ですが、ただ引き起こされた原因は Front End にあります。
 まず、SSO をするとき、Return Url を Back End に渡していますが、もし相対 Url の場合、正しく動きますが、フルの Url を渡したら、途中で処理を止まりました。原因は Back End の処理は絶対 Url の処理はできていません。
 Domain は同じでも、Front End からどんな ReturnUrl 文字列が渡されるかはわからないので、ちゃんと処理しないと。。。

 この件、<a href="/digital/url"> を書きましたが、実際 Return Url を取得するとき、e.target.href を使ってしまいました。この場合、Browser は相対 Url に Base Url を自動的に追加します。そうすると、本来なら、相対パスであるところは絶対パスになってしまいます。。。
 解決方法は Back End 修正すべきですが、一応、 Front End も正しい動きにしたほうがいいと。e.target.getAttribute("href") にすれば、ちゃんと href 中の相対パスが取得できます。これは属性を直接使う場合、と getAttribute() 関数の違いです。
 ちなみに、jQuery はいつも getAttribute を使っているそうです。
 
 こちらは HTML Specification によると、.href を使う時は、DOM Property と呼んで、.getAttribute の場合は attribute となります。DOM Property は計算後の値になります。例えば、上記の .href。また .checked の場合、DOM Property なら true, false になりますた。.getAttribute を使うと、"" 空の文字列になる。今後ご注意を。

 それでは。

2016年10月3日月曜日

iOS での position: fixed をスムーズにする

 先日リリースした Web App の Header を position: fixed にしました。PC では問題ないですが、iOS や Android など Tablet Webkit 系では、ちょっと変な動きをしました。実際指でスクロールすると、Header が一瞬消えて、そのあと画面がほぼ静止したとき、 fixed になります。これは多分 Tablet 自身のパフォーマンス問題で、解決方法を調べてました。
 ネットではいろいろ書き込みがあります。基本的に
     transform: translate3D(0, 0, 0) を使ったり、transform: translateZ(0) を親要素に追加して、強制的に Layer を作って、ハードウェアの加速を使います。
 追加してみたら、ほぼ解決するようになりました。ただ、Header に要素が多い場合、まだまだ不自然です。デザイナーを相談して、できるだけ Header にある要素を Tablet の場合、減らしました。。。

 さらに調べてみると、transform: translate3D(0, 0, 0) か translateZ(0) を使うと、Browser はその要素を一つの Layer として、イメージを作って、Video Card のメモリにアップロードします。そのあと、何かアニメーションが起きたら、CPU の時間ではなくて、Video カードを使って、画面を更新しています。これは速いはずです。
 注意点としては、むやみにいろんな Layer を作ると、逆にパフォーマンスに悪影響が発生します。本当に使ったほうがいい時、使うよという書き込みもいっぱいあります。

 もう一つの注意点としては、新しい Layer が作られたため、z-index と translateZ(0) が衝突する可能性があります。例えば、親の間に z-index を使って、画面上の上下位置を調整していますが、親レベルですので、translateZ(0) を使うと、その z-index が効かなくなる可能性があります。よくテストしましょう。
 もう一つ、これは Tablet など画面の大きいデバイスでは、画面の小さい mobile phone では、position fixed を使わない方がいいです。media query を使って、header を元の位置に戻しましょう。
 それでは。

2016年9月18日日曜日

最新 React.js にアップデート

 先週、つい React.js のバージョンを 0.12 から 15.3 にアップグレードしました。Component 自身の修正はそんなに多くないですが、jest でのテストはかなり変わりましたので、少し時間がかかりました。
 まず、全ての node モジュールを最新バージョンにして、npm dedupe コマンドを実行して、node_modules のフォルダ構造をできるだけフラットにしました。これで、Windows でのファイル名が長すぎという git clone 時のエラーが少なくなるはずです。
 そのあと、Webpack の Config を修正して、transpile できるようにします。こちらは主に、loader の変更です。新しい Babel では、stage や、destructuring などの ES2015 フェーチャーを個々のモジュールに分けたので、preset に ES2015とReactを設定しなければなりません。こちらは .babelrc に追加します。jest も Babel loader を使うので、rc ファイルに設定したほうがいいです。そのあと、使っている ES2015 のフェーチャーを plugin に追加します。主に、destructuring になります。
 これで、transpile は通るようになります。ブラウザーで Web App をロードすると、いろんなエラーが出てきます。
 − App を DOM に render するとき、ReactDOM.render を使います。
 − getDOMNode() が削除されたので、ReactDOM.findDOMNode() に変更する必要があります。こちらは native の DOM Node div などを ref を入れると、自動的に DOM node の reference になるので、これはかなり便利になります。
 − props は完全に readonly になるので、過去の悪いコードを直しないといけません。
 − DOM node にサポートしない属性もエラーになりますので、こちらを props などの object から取り出して、設定する必要があります。例えば、contentKey とか自分で過去使っていた prop などに対して、 {...props} を使うところを { contentKey, ...others } = this.props をして、{...others} のみ React Component に渡します。
 − React Component は owner が必要とかのエラーは複数の React.js バージョンが存在したからです。過去の Third Party lib 中の React.js バージョンをチェックした方がいいです。
 − PureRenderMixin や classSet などの lib は React.js から分離されたため、個別に require する必要があります。
 こちらのエラーを直すと、基本的に Web App は動きます。

 一番大変なのは jest での Unit Tests の修正です。 setProps や、getDOMNOde() などもう使えないので、一括で findDOMNode() に変更したりして、動かない場所や、エラーになるところを一つ、一つ直す必要があります。こちらはほぼ一週間かかりました。(全部 1022 個 Unit test case)。
 なお、airbnb から enzyme というライブラリーが出てきたので、こちらをこれから使う予定です。jest よりかなり使い易いです。
 まぁ、全体的に見ると、そんなに手間をかかることではないので、早めにアップデートしたほうがいいかもしれません。

 それでは。

2016年9月10日土曜日

Web, mobile App と Restful API

 最近、作ってるアプリは Restful API を採用されました。こちらは二つの Layer があります。Web Layer と App Layer。具体的に、App Layer はデータを保存したり、処理するだけです。Web Layer は実際の Web アプリやモバイルアプリにコミュニケーションします。
 この二層 Layer は一見的に必要ないと思われてるかもしれません。ただ、API を使うとき、Web アプリとモバイルアプリの間に要求が違うときがあります。この場合、Web layer でその違いをカバーできます。さらに、JSON フォーマットの Data Contract は Web Layer で固めて、App Layer  はほぼ自由に変更できるようになります。
 例えば、Web の場合、通常ログイン状態は保持できないし、セッションタイムアウトもあります。モバイルの場合、基本的にログイン状態にあります。それで、フリーに見れるコンテンツとログインで見れるコンテンツをコントロールする必要があります。ただ、一旦ログインすると、もう扱うデータが同じになります。これは Web Layer と App Layer を分ける理由の一つです。
 もう一つの理由としては、今 AWS や Azure などの Cloud プラットフォームが使い易くなります。App Layer は自分の会社に配置して、Web Layer はAWS などを使います。App Layer も他の内部のシステムにも利用できますし、データも基本的に自社にあるから、他の会社に保存して、漏れるとかの心配も少ないでしょう。
 
 Web Layer と App Layer の間も基本的に HTTP Restful API になっています。Web Layer はアプリとの JSON Data Contract を定義して、DTO などは基本的に変更しにくいです。その後ろに存在する App Layer との間がデータのやり取りですので、変更は頻繁にあるかもしれません。アプリのバージョンが複数サポート必要があるとき、さらに使い易いです。
 それでは。

2016年8月28日日曜日

CSS Animation, Focus と Accessibility

  先日、あるアコーディオン的な Form を作って、CSS で slide up / down アニメーションをつけました。実際 CSS animation を使うとき、要素の display: none から display: block に, visibility: visible から visibility: hidden を変更すると、アニメーションが実行されません。現在 CSS animation はある数字から、次の数字までしか動きません。Height の場合、0 から 200 までアニメートできますが、0 から auto まではできません。
 では、なぜ jQuery animate 関数を使わないかと、CSS の方が効率がいいし、面白いからです。Chrome の FPS ツールでみると、CSS の場合、主に 50 FPS に一定していますが、jQuery animate は、JavaScript を実行しているので、FPS 一定ではないです。(https://greensock.com/js/speed.html)
 それで、display: none -> block の代わりに、maxHeight: 0 -> 200px を css transition でアニメートするようにしました。maxHeight 0 となっても、実際その要素は DOM に存在していますので、Screen Reader は認識しています。さらに、そのエリアに Form <input /> があるため、Tab Stop も発生しています。
 Focus が見えないところに行くのは大変良くないことです。ユーザーが Tab キーをおして、しばらく Focus はどこにあるかわからなくて、結構迷うようです。
 では、css animation を使うとき、accessibility について実装方法としては幾つかコツがあります。
 まず、<input /> みたいな Form 要素に対して、tabIndex を使って、 tab order を変更します。0 から -1 にします。0 の場合は、tab order をブラウザーを任していますが、-1 の場合、JavaScript の setFocus() 関数を使う必要があります。これで、ユーザーの Tab キーはその要素をスキップするようになります。
 次、aria-hidden を使って、見えない部分を Screen Reader から隠します。aria-hidden を true にすれば、すべての Screen Reader が読まないようになります。
 具体的に:
    <form aria-hidden={isOpen ? false : true}>
        <input tabIndex={isOpen ? 0 : -1} />
    </form>
 にするだけです。

 これで、ユーザーの Tab Stop が Form Hidden の場合、そのエリアの <input /> などに行かないように、矢印キーを使っても、その部分が読まないようになります。アニメーションは maxHeight を使って、開いたり、閉じたりできます。

 Accessibility について、いいコースがあります。英語ですけど。。。
    https://www.udacity.com/course/web-accessibility--ud891

 それでは。

2016年8月6日土曜日

React.js Component Wrapper

 先週、pre-loaded データを使って、Component を render する代わりに、ajax を使って、データロードして、そのあと、 Component を render する機能が出てきました。この機能を実現するために、Wrapper Component を作ったら、簡単にできました。
 具体的には autoLoadingComponent を作って、その中に、state を持たせて、componentDidMount の中に、ajax call を呼び出して、callback には setState() を読んで、state を更新します。この state をベースに元の Component に props として渡します。
 そうすると、state が更新するたびに、元の Component が re-render されますので、auto load 機能が実現できます。簡単な例として:

 autoLoader = React.createClass({
      mixin: [pureRenderMixin],
      getInitialState: function () {
        return {
           data: null,
           loading: true
        };
      },
      componentDidMount: function () {
         // ajax call to get data
         getJson(url, this.handleResponse);
      },
      handleResponse: function (response) {
          this.setState({
            data: response,
            loading: false
          });
      },
      render: function () {
         if (this.state.loading) {
           return <loading />;
         } else {
           return <component data={this.state.data} />;
         }
      }
   });

 これで、過去の Component も再利用できますし、どんなものでも auto load 機能がつけられます。
 さらに、Redux を使ってる場合、Redux.connect() という関数があります。この関数も同じ考え方で、state を持ってる Wrapper を作って、過去の Component を自動更新できるようにします。その中も subscribe などの biolaplate コードもいっぱい入ってます。
 
 それでは。