Redux(react-redux)における適切な配列要素の更新
2021年8月23日…
本稿は、Angular JS 1.4.xを使用した際の感想となっている。2016年9月29日現在、少し前にAngular JS 2が正式リリースされ、今現状はAngular JS 1.5.xとAngular JS 2が混在している状況だ(少し違うかもしれないが、移行期間という意味ではPython 2.7系とPython 3系の問題と似ているかもしれない。とにかく、結構中身が異なる正式リリースのメジャーバージョンが混在している)。Angular 2系では、本稿で触れているAngular JS 1系の特徴であった双方向データバインディングは撤廃され、データバインドは単方向になっている。また、プログラミングのスタイルがReactや他モダンJavaScriptフレームワークが採用しているコンポーネント指向をならったものとなっている。Angular JS 2系と1系は正式が異なるものになるので、本稿はあくまで「Angular JS 1系を使った感想」と認識していただければと思う。なお、現状もAngular JS 1.5を使用して開発をおこなっているが、本稿に書いた感想から変わらず、使用感は良いと感じている。
フロントエンドでは、フレームワークの使用経験なしでこれまでjQueryしか扱ったことがなかったが、今回は個人レベルの製品開発でAngularJSを使ってみた。開発人数は僕一人で、提供APIがあり、それをフロントでよしなに処理して画面を生成するという要件であった。第一弾の実装で、jQueryで実装完了しているものがあったが、仕様が複雑化しそうな気がしていたので、jQueryからAngularでリプレースしつつ新規の機能を実装するということをした。
AngularJSはフルスタックフレームワークなので、よく比較されるReactよりは学習にかける時間は多いと思う。自分のメインの学習の教材は、AngularJS アプリケーションプログラミングという本だけで、本で紹介されているスクリプトをそのまま実際に打ってみて動作を試すという方法だった。詳細な学習時間は覚えていないが、おそらく休日丸々2日も使えばAngularJSのだいたいの概要を把握するには十分だったと思う。前提としては、JavaScript(といってもメインはjQuery)の開発経験が1年ほどあり、Node.jsをCRUDアプリを作るためにたまにいじっているくらいの下地があった。JavaScript関連技術の使用が日常的にある、くらいの人である(本業はインフラやってるのでコードを常には書いてないくらい)。
前提として、jQueryのDOM操作に辟易していたことが最大の理由である。以前の開発では、サーバサイドがJSONを吐き出し、フロントでよしなに処理をするという体制でやっていた。初心者二人の開発で、フロントエンドは技術選定からおこなっていたが、僕の初めての開発で、JavaScriptフレームワークという頭にはならず、安定した技術であり、なんでもいいからとにかく多くの知見が欲しかった。なので、JavaScriptで初心者といえば、ライブラリのjQueryに行き着くわけで、jQueryオンリーで実装をしていった。問題は最終的な調整を進めるうちに露呈した。ある時、ページロード時のDOM描画がもたつくことに気づく。DOM操作が多くなればなるほど、二次関数的に描画が遅れ、例えば、表組みの周りの線だけ描画されて、内部の項目が1秒くらい遅れて表示される、みたいなありがちな感じな状態が起きた。そういった場合になったときに、対処法のアイディアを思いついた。当時はあくまで、「jQueryでなんとかする」という頭しかなかったので、viewの生成を例えばこんな感じでしていた。
var html = '<div><h2>見出し1</h2><p>本文1</p><p>本文2</p><p>本文3</p</div>'; $('.content').append(html);
やりたいことは、とにかくDOM操作のコストを下げるがために、レンダリングしたい要素をそのままテキストとして変数に格納し、それをjQueryのappend 1回で対象のところに突っ込む、ということだ。これに行き着くまでは、僕はappendの構文を要素の入れ子分だけメソッドチェーンでつなげることをしていたのだ!これは、読む人を不快にしかしない、あげくDOM操作のコストが非常に高く、ブラウザの描画速度に悪影響しか与えていなかった。今振り返るととても恥ずかしすぎるのだが、言いたいことはjQueryはいくらでも実現方法があり、好きなように書けるのだが、それは丁寧であって丁寧ではないということ。生のDOMとの戦いを経て分かることもあるだろうと、良いように過去を振り返ってもいいのだが、それって無駄では?とも思えるのでjQueryをとりあえず大概にしろよと思うようになった。
とにかく、機能の実装に集中したいところでもDOMの操作をどう減らすか、なんてことを実装内容によっては考えないといけなくなることについて嫌気がさしていた、ということである。
jQueryが得意とする視覚的なエフェクトの話題はおいておくとして、現在のJavaScriptフレームワークの主流はDOMの上位に位置する、より抽象化された仮想DOMを操作して、「生のDOMは操作しない」という動きが多いように思える。最近よく聞くあたりだと、ReactやAngularJSがメジャーなフレームワークだと認識している。定量的な観測だと、GoogleトレンドによるJavaScriptフレームワークの比較結果がこちらだ。
上記の対象フレームワークは主観で選んだ。ということで、ReactかAngularJSが今後の主流になりそうだ、というのは人々の注目具合からすると間違いないように思える。ReactかAngularJSと選ぶ段階にきたところで、知見の多さ、それからviewだけではなく、ルーティングだったりとか、視覚的なエフェクトだったりとかある程度しっかりしたフレームワークが欲しかった。
これまでやっていた、メインはjQueryで処理を記述し、実装で足りない部分は作らずしてなるべく安定してそうなプラグインを探してそれを読ませたり…、この作業をなるべくなら一つのフレームワーク内のモジュールの導入だけで完結したかった。また、見落としがちで大きな問題として、何か実装上の問題があったら一部はjQueryで生DOMを使って操作をする、という最後の逃げ道が欲しかった。そういった選定基準があった際に、ReactではなくAngularJSが要件を満たしていた。知見の数でいうと、国内でもReactの記事よりもAngularJSの記事のほうが見つけやすく、書籍も少ないが、Reactよりもあった。あとは、AngularJSのモジュールがかなり豊富で、個人の開発では車輪の再発明は極力少ないほうが良いと思っているので、これは恩恵を授かれるのならそうすべきだと思った。
個人的には、Reactも十分に興味があり、参考書も購入してみたので、これはやることは必至なのだが、要件的に必要な条件を満たしているAngularでまずはやってみようとだけである。
AngularJSの良いところは、 MVWというくらいに、とにかく「何をする?」というところに常にフォーカスして開発ができたことだと思う。jQueryの何かをするためのコード、みたいなものはなかった、もしくは意識せずに開発できたと思う。そういえば、何かをするためにclassやidを振って、その要素を明示的に操作する、ということは一切なかった。jQueryはviewの変更に特化しているわりには、仕様変更にとても弱いと思っている。理由は、jQueryはセレクタで対象のDOMを明示的に指定する必要があるからだ。これが箇条書き要素が下に一つずれただけでも大変、というのがjQueryだろう。だが、AngularJSでやっていて、仕様変更が2回ほどあったが、そういったことは一切感じなく、仕様変更に強い枠組みを有していると感じられた。
$scope要素を介して、テンプレートエンジンとコントローラー側の処理が密接に結びついていることで、この恩恵で簡単なものはすぐに実装できた。あとは、たいがいやりたいことを調べたら知見があるし、ドキュメント自体もちゃんとバージョンごとに整備されている。ドキュメントには簡単な例文もついているのでかなり助かった。
個人的に地味に感動したのが、ng-cloakだ。これは何をするものかというと、指定した対象DOM以下のツリーに対し、レンダリングが完了し次第表示するという制御である。jQueryだとこのあたりの制御はしていなかったし、僕はやり方を知らなかった。当たり前のように、ページロード時のレンダリングのケアがあることに驚いたのと、実際に使ってみて恩恵がかなり多かったことに感動を覚えた。仮想DOMとはいえ、レンダリングのタイミングとかある程度は要素ごとに遅延がしたり、何かしらのケアが必要なんだろうなあと覚悟はしていたが、簡単なCSSを書き、ng-cloakと要素に振るだけでその箇所が体裁が整っていない状態で表示させることができるという恩恵が大きかった。
AngularJSの悪いところは、バージョンによって、使い方が変わるのが激しい感じがあるということだ。しかも、メジャーバージョンではなく、マイナーバージョンのレベルで変わってくる。結構、ドラスティックに削除されたり、追加されたりが激しい模様。今回の製品では、1.4.8を使用してみたが、知りたいことを調べて日本語の記事で1.2の情報がヒットしたとしても、これが使い物にならず、結局公式の英文を眺めるということはよくあった。ただ、これは良い意味とも捉えられる。結局、盛り上がっているフレームワークで、積極的に悪い部分を見直したり、改良したり(改悪もあるのかもしれないが…)そういう動きが全体的に見て活発だ、と捉えることもできる。
あとは、開発中に気になったのが、AngularJSの特徴でもあり、便利な双方向データバインディングこそが、やりたいことの邪魔をすることがあるということだ。双方向データバインディングとは、view側とロジック側で$scope要素を介して密接に値が紐付き、例えばロジック側であったデータモデルの変更によりviewが変更されるというものだ。これははっきり言って、複雑な処理をするときに邪魔になるケースがある。例えば、$scope要素の変更がロジック側にあり、それを察知してviewを変化させたくない、という時だ。これが概念上、$scopeを使えば、紐付くことが前提なので、対応策を練るのがとても面倒だった。結局、初めてのAngularJSでの実装ということと、仮に実現したとしてもあまり良い構成にならなそうと思ったので、この問題は放置し、視覚的なエフェクトでフォローして問題を暫定的に対処したことで止めた。まだ分からないが、双方向データバインディングこそが、たまにAngularJSが中規模〜大規模開発に向かない、と言われる所以なのかもしれないが、まだこれは感覚値程度なので明言はできない。ちなみに、この双方向データバインディングだが、現状のAngularJS1.xではメインの概念であるが、 AngularJS 2.xからは削除される概念である。
あとは、これは今回の開発で直面はしていないのだが、jQueryで組んだときに、例えばゴリゴリDOMをこねくり回し、視覚的なエフェクトを演出する、ようなものはAngularJSには向いてなさそう、というのが開発途中で調べていて散見できた。その分野については、高度なことをやる場合にはきっと生のJavaScriptで頑張るか、jQueryに頼るというのが筋なんだろうと勝手に想像している。
AngularJSは今回、初めての導入であったが非常に生産性が高く、驚いた。jQueryで書いたもののリプレースもだいたいjQueryで作っていた初期のものの工数の1/3以下であったと思ったし、とにかく一人でやる分には開発効率は高いと個人的には思った。
今後についての話でいうと、AngularJSはもちろん継続して学習し、メインの技術として使っていくし、新たにReactもやる。Reactのほうがviewの描画速度についてはAngularJSより優位だし、ng-reactなるモジュールもあり、決まったviewの描画があったらReactを使うという、AngularJS+React(ng-react?)の構成も面白いと思う。
また、AngularJSとReactではそもそも実現したい方向性や特性が違いすぎるし、そのあたりもコードを実際に書いてみてちゃんと理解したいので、そのためにはフロントエンド技術者・JavaScript技術者はAngularJSとReactをどちらも学び、使えるようにしておくべき、というのが僕の考え方だ。Reactには、Facebook公式でReact Nativeなるネイティヴアプリにも対応したフレームワークもあるし、Webアプリケーション以外のカバー範囲の汎用性ではReactが大変良さそうだな、と思っているところだ。これはFacebookのモバイルアプリケーションも利用実績があるし、期待値が高い。
とにかく、AngularJSもReactも、両者で今後どんどん人気が加速すると思うし、どっちが良いも悪いもなく、ケースバイケースで良い技術として扱われていくと予想している。
(広告)
※Angularの書籍です。本記事で取り扱ったAngular JSのメジャーバージョンアップ版のバージョン2以降のものです。
新品価格 |
プログラムを書きながらTranceを聴くのが良いですね。みなさんも聴いたほうがいいですよ、Trance。EDMよりハードトランスでしょ。
Discussion about this post