応天の門 を読んだ

読んだ。

応天の門 1巻 (バンチコミックス)

応天の門 1巻 (バンチコミックス)

在原業平菅原道真のコンビが怪事件を解決していくサスペンス物。在原業平が持ってきた事件を菅原道真がロジカルに解決する、平安朝が舞台の探偵ガリレオといったところだろうか。

高専の古典の講義で伊勢物語をやったときに先生が、在原業平を「平安一のプレイボーイ」と解説していたのを思い出した。それぐらい在原業平が女好きに描かれている。

年末年始の休暇中に読んだ本

炬燵に入り、みかんを摘みながら読んだ。

サピエンス全史(上)文明の構造と人類の幸福

サピエンス全史(上)文明の構造と人類の幸福

サピエンス全史(下)文明の構造と人類の幸福

サピエンス全史(下)文明の構造と人類の幸福

人類がなぜ繁栄したかを壮大なスケールで語る一冊。集団で虚構・神話・空想を信じることができるようになった認知革命に始まり、農業、書記体系、貨幣、宗教、科学と話が進んでいく。
この本の面白さは、自分の先入観や常識が覆され、違った視点で物事を眺める体験ができることにある。自分が当たり前のように善だと信じていたもの、例えば、自由主義や資本主義が、あくまでひとつの虚構に過ぎないものだと認識させられる。

また、一般的に良かったこととして記述されがちな狩猟から農耕への移行を、人類にとっては実はそれほど利はなく、小麦が種の繁栄のために逆に人類を支配した、という主張も面白かった。

若者をターゲットにお金との付き合い方が書かれている本。単純にお金の話だけでなく、少子高齢化や、それに伴う公的年金の負担増といったテレビが煽る先行きの暗い話を数字と事実で分析する過程を通して、メディア・リテラシーの重要性も説く。

量子コンピュータが人工知能を加速する

量子コンピュータが人工知能を加速する

量子コンピューターの方式の一つである量子アニーリング法とその実現方法、さらにはディープラーニングにどのように応用されるかを噛み砕いて説明している。

TypeScript で書いている Node.js サーバーをファイルが変更されたときに自動で再起動したい

題の通り。

TypeScript に慣れるために、TypeScript でちょっとした Node.js サーバーを書いていたときのメモ。

GitHub - TypeStrong/ts-node: TypeScript execution environment for node で TypeScript のコードを直接 Node.js で動かすことができるのだけど、.ts ファイルの変更の度にプロセスを落として、またコマンドを実行して... というのが面倒だったので、自動で再起動させる方法を調べた。

ts-node の Issue を眺めたかんじだと、onchange という npm でインストールできるコマンドを使って、ファイルの変更を検知して再起動すればよいのではとのこと。以下のような npm scripts のタスクを定義して、呼び出すようにする。

  "scripts": {
    "server:dev": "onchange server.ts -i -v -- ts-node server.ts"
  },

ふしぎの国のバード を読んだ

読んだ。

明治初期にイギリス人の探検家 イザベラ・バード が日本を探検した際の実話を基に書かれた漫画。当時の日本の風景や庶民の生活が描かれていて面白い。明治初期は、300年続いた鎖国が終わり、日本がグローバリゼーションの影響を著しく受けた時期と言える。その時期に失われた何かを知るきっかけとなる作品ではないだろうか。

2016年のふりかえり

今年も残すところあと少し。今年のふりかえりです。

去年のふりかえりはこれです。 2015年のふりかえり - kitak.blog

仕事

去年に続き、ウェブフロントエンド中心に JavaScript のコーディングなど。サービスや大きめの機能をいくつかリリースできたのと、その中で大量のオブジェクトやトラフィックを扱う案件をこなすことができて、ひとつ自信に繋がったような気がします。自己否定がちょい強めなので、ひとつひとつ形にしていって肯定感を高めていきたいところ。

前半、Java や Spring Boot ( Spring MVC ) の勉強をしていて、正直仕事や趣味でそれらをがっつり書くことはなかったんですが、上半期の仕事でデバッグをするときに抵抗なくサーバーサイドのコードを読んで、問題特定に役立てることができたので、やっておいてよかったかな、と。

去年も同じことを書いていた気がするんですが、やることを限定しすぎているような気がするので、そこは来年の課題。

アウトプット

発表

Vue.js meetup で発表しました。 Vue.js Tokyo v-meetup="#1"でLTしてきた、と発表からカットしたMVVMのあれこれ - kitak.blog
これ一回だけだったので、うーむ...というかんじです。スライドにまとめるのは自分自身の理解のためにも良いので、居酒屋で酒を呑みながらカジュアルに発表するようなのを定期的にやりたいね、と同じことを考えている人と話していたり。

執筆

gihyo.jp で Vue.js の入門記事を執筆しました。執筆の機会をいただきありがとうございました。

gihyo.jp

ブログ

特に明確な目標があったわけではないんですが、週に1回はブログを更新するように意識していました。気分が乗らないときは、とりあえず続けばいいやぐらいの気持ちで漫画やドキュメンタリーの感想を書いたり。
書いた記事のうち、何個かホットエントリ入りして、たくさんの人に読んでもらえたのがうれしかったです。

生活

風邪をひくことが多い一年でした。下半期は、一ヶ月半に一回くらいのペースで風邪をひいていたように思います。運動不足で、体重が増えているのもありますし、来年はもっと健康に気を使いたい。 外は寒いですが、とりあえずウォーキングから始めて、引っ越したら近くのジムに通おうかな、と思っていたり。

上でも書きましたが、来年、会社のオフィスが新宿に移転するので、それに合わせて引っ越す予定です。今のところ、祐天寺、中目黒、新宿御苑、代々木あたりを考えています。

去年に引き続き、浮いた話は全く無いので、そこは来年も引き続きがんばりましょう。

2016年に使った&来年使いそうな JavaScript 関連のものと所感

2016年に使った&来年使いそうな JavaScript 関連のもの

以下のカテゴリでなんとなく書いてみます。去年と比べて大きく変わらないかんじです。動きの早かった 2, 3年前から、年々、動きはゆっくりになってきているというのが個人的な印象。

トランスパイラ

2016年に使った:

Babel。各ブラウザの JavaScript エンジンで ES2015~ES2017 の実装が進んでいるので、関わっている案件のブラウザのシェア次第なところもありますが、ES2015~ES2017 の仕様だけトランスパイルしたいのであれば、再来年あたりから要らなくなるんじゃないかな、という気持ち。

来年使いそう:

静的型付けがメインで、ES20XX から ES5 へのトランパイルは副次的ですが、TypeScript。先日、久しぶりに触ったら( v2.1 )、v1.6 か v1.8 の頃に触って微妙だな、と思った諸々が改善されていました。

  • サードパーティの型定義ファイルの取得がそれ用のツールではなく npm でできるようになった
  • 別ファイルに定義された型情報を参照するために reference タグを書く必要がなくなった
  • async/await を es5 target でダウンパイルできるようになった ( 以前は、いったん es2015 に変換した後に babel でさらにトランスパイルをしないとダメで、ビルドチェーンが複雑になるからスルーしていた )
  • targetに esnext, es2015, es2017 が指定できるので、型宣言だけ抜いた JavaScript ファイルが生成できる。やめたくなったらすぐにやめれる
  • Visual Studio Codeとの連携が良くできている ( 最近 Visual Studio Code 使っているので )

ビューライブラリ/フレームワーク

2016年に使った:

Vue。既存のサービスでのちょっとした UI の実装から、SPA のフルスクラッチの実装まで幅広く使いました。良さは色々あるんですが、以下の3点が大きいです。

  • 上で書いたようにライブラリとしてのスケーラビリティが高い
  • API がシンプルで学習コストが低い
  • API や 新しいバージョンへの移行のドキュメントがしっかり整備されている

周囲だと React , Redux を使っている人もちらほら。React、良いと思うんですが、今の会社のワークフローだと HTML を JSX に手で書き換える作業が発生するので、個人的にそれがつらいので選択していません。( React に限らず、Vue も含めたコンポーネント指向のライブラリを使うとどうしても二度手間感が否めないワークフローなので、来年はそこを改善したい、と思っていたり )
今年の9月末にリリースされた Vue v2.0 で パフォーマンス改善 & Server Side Rendering もできるようになったので、特別 React を選ぶ理由がなくなったというのもあります。

来年使いそう:

今年と同じ感じ。新しいライブラリを実戦で使うことは今のところなさそうですが、Shadow DOM v1 や Custom Element v1 の実装が ChromeSafari で進んでいる背景も踏まえつつ、https://github.com/skatejs/skatejs のような WebComponent のAPIを薄くラップしたライブラリはウォッチしておこうと思っています。

モジュールバンドラ

2016年に使った:

Browserify。それなりの規模のプロジェクトだと生成されるファイルサイズが大きくなる以外は不満はなく。ビルドにかかる時間も watchify を使えばだいぶ短くできます。ただ、開発が活発ではなくなっているのと、モジュールバンドラとしては Webpack を使う人が増えて、Browserify を使う人が減ってきているような気がするのが気がかり( ソース: The State of Front-End Tooling 2016 - Results - AshleyNolan.co.uk - Blog and Portfolio for Ashley Nolan )。

来年使いそう:

Browserify でもまだ困らないとは思うんですが、Webpack2 を検討しています。理由はビルドにかかる時間が短い、コード分割(と動的ローディング)、Tree Shaking で生成されるファイルのサイズを減らせるというあたりです。ただ、先日のブログ( JavaScript のサイズを減らすことと効率良くキャッシュさせるためのメモ - kitak.blog )の最後に書いたようにツールの自由度が高く plugin と loader の使い過ぎが後々の負債に繋がりそうな予感がするので、いったんは JavaScript のモジュールバンドラとして使い、stylesheet や画像は扱わないつもりです。

スクランナー

2016年に使った:

npm-scripts(yarn run も含む)。npm run ほにゃらら で browserify のコマンドを実行したり、コマンドをパイプで繋いだり、複雑になってきたら JavaScript で書いたスクリプトを node で実行したり、シェルスクリプトを実行しています。

数年前からあるプロジェクトや一部のタスクは Grunt を使ってます。Grunt、今でもメンテはされているので、使っている Grunt プラグインが全くメンテされなくて業務に支障が出るとかがないのであれば、既存のプロジェクトで急いで違うツールに乗り換える必要はなさそうです( 時間があれば乗り換えてもよさそうですが )。

来年使いそう:

多分、これまでと変わらず。

パッケージマネージャ

2016年に使った:

Yarn。リリース日に触ったらパッケージを git リポジトリの url で指定すると動かなくて、しばらく様子見していたんですが、一ヶ月ぐらい前に触ったら修正されていて、それ以来使っています。体感ですが、パッケージのインストールが非常に速い。その他、npm の生成する package.json と互換性があったり、バージョン固定の仕組み( npm shrinkwrap はバグやハマりどころが多かった )など、諸々鑑みて、使わない理由がない。

来年使いそう:

多分、今年と変わらず。

スティング

2016年に使った:

あんまりこだわりがないので昔から使っている Karma(テストランナー) + Jasmine(テスティングフレームワーク) + PhantomJS。

来年使いそう:

来年使うものというより、よっぽど強い理由がないのであれば、使っているビューライブラリやフレームワークが、自身のテストに使っていたり、ドキュメントで推奨しているものを使うのが無難だと考えています。

所感

最近、心の中でふつふつと思っていたことです。

動き早い?

冒頭にも書きましたが、年々、落ち着いてきているような気がします。今年に関して言うと、去年から耳にしていた・ある程度使われていたものが今年になって、改善・改良されて、さらに使われるようになったというところではないでしょうか。それは、The State of Front-End Tooling 2016 - Results - AshleyNolan.co.uk - Blog and Portfolio for Ashley Nolan の結果にも現れています。

とはいえ、上で書いたカテゴリだけでも 6つあって(他にも色々 Lint とかあるんですが ESLint が当たり前になっているので省きました)、JavaScript を普段書かない人からすると、学ぶべきことがたくさんあるように感じる、適当にググったら、過去に広く使われていたものや「それぞれのツールを組み合わせてみた」みたいな記事が大量に出てきて、あたかも動きが早いように感じるのではないでしょうか。

実際のところ、全ての案件で上のカテゴリのツールやライブラリ全てが必要なわけではありません。極端な例をあげれば、公開期間が数週間のキャンペーンページだと、(マサカリ飛んできそうですが) jQuery 互換のライブラリを npm で入れて、ES5の仕様でシュッとコード書いて、ファイルを concat (これもいらなくなりつつある), uglify しておしまいということもあります。自分が必要なものを理解して、選んで使えばいいだけです。なので、コンテキストをすっ飛ばして「React, Redux, Webpack, ... このスタックでやっとけば間違いない!」 みたいな記事を見ると、眉をひそめたくなります。

個人的に、JavaScript やその周辺のことを学び始めた人が自分の作っているものや関わっている案件に対して、必要なものを適切に選ぶことができるガイドやYes/Noチャートのようなものが世の中に足りないんじゃないかな、と感じています。

あとは、2016年にJavaScriptを学ぶとこんな感じ – Medium Japan – Medium に書かれているような普段 JavaScript を書いている人がそうじゃない人に「イマドキはこれだから!」とその人がやりたいことに対して過剰なものを押し付けたり、不安を掻き立てるようなことをしないということですね...(自戒もこめて)

新しいライブラリ・ツールとの向き合い方

落ち着いてきているように感じるとはいえ、新しいライブラリやツールは次々と出てきます。そういったライブラリやツールとはどう向き合えばいいのか。個人的には次のような感じでやっています。

  • README を読んで、それが何を解決するかやどのカテゴリに属するかを考える
  • 良さそうであれば sandbox プロジェクトで試す
  • そのプロジェクトが作られて2, 3年未満の場合は2, 3年経つまで放置
  • 2, 3年経っていたら、それを使うことで生産性が数倍向上しそうか(ちょっと向上するぐらいだったらやめる)、その間にあったリリース内容やコミュニティの発展、直近のWeb標準やプロコトルの進化や発展で不要にならないか等を鑑みて実戦に投入するか判断

2, 3年というのは、けっこう適当なんですが、新しく出てくるツールは大抵 2, 3 年の内に消えているように思うので、2, 3 年生き延びたのであれば、今後も存続し、実戦で使うに耐えうるクオリティになっているだろうという考えです(yarn, 今年出てきたやつやんとツッコミ受けそうなんですが、package.json そのままで npm を置き換えればいいだけなので例外)。一時期、新しいものを使うのが正しいと思っていた時期もあったんですが、kintoneフロントエンド開発 モダン化への道 のスライドやロードマップ指向とエコシステム指向 - アンカテ を読んで、いわゆる中心部のレッドオーシャンを避けるようになりました。白洲次郎が、ツイードは2, 3年雨ざらしにして着ろと言っているように、JavaScript 関連のツール・ライブラリも2, 3年様子見するぐらいがちょうどいいんじゃないでしょうか(ツイード着たことないですが…)。

おしまい。

WebPagetest を使わずに Speed Index を算出する

題の通り。

WebPagetest を使うと、Speed Index というページのコンテンツがいかに速くレンダリングされたかの総合的なスコアが算出できます。Speed Index は、定期的にこのブログで取り上げていますが、算出方法の内容は https://github.com/t32k/webpagetest-doc-ja/blob/master/using-webpagetest/metrics/speed-index/index.md に詳しく書かれています。( Speed Index とは異なりますが、First Paint のタイミングを計測するための Web 標準は GitHub - WICG/paint-timing: A proposal for a Time To First Paint specification. で議論されているようです )

個人的な興味で、とあるウェブアプリの2つの実装方法のうち、どちらが速くレンダリングされるか調べたくなり、Speed Index が指標として適切だと判断しました。Speed Index を算出するために、WebPagetest のページを何回もポチポチやったり、API を呼んだりしてもよかったんですが、なんとなく WebPagetest のリモートのマシンではなく、ローカルのマシンのブラウザでページが表示されるのを見つつ、算出したかったという次第です。ようするに気持ちの問題です。

たまたま、https://github.com/GoogleChrome/lighthouse という Google が提供している Progressive Web App にアプリが即しているかチェックするツールで Speed Index を算出していることに気づいたので、コードを読んだり、grep して https://github.com/pmdartus/speedline を使って Speed Index を算出していることが分かりました。speedline の README に書かれている通りですが、Chrome の Timeline のレコードが記録された JSON を渡せば算出できそうです。なぜ、Timeline のレコードを使うのかは、Speed Index の算出方法を解説した記事の「描画イベントによるVisual Progress」を参照してください。

Timeline のトレースは、https://github.com/cyrus-and/chrome-remote-interface を利用して、Remote Debugging Protocol を喋ることで可能です。chrome-remote-interface は、2年前にこのブログでも紹介していました( chrome-remote-interface を試してみた - kitak.blog )。これ、2年前か…。 chrome-remote-interface を使った Timeline のトレースは、GitHub - paulirish/automated-chrome-profiling: Node.js recipe for automating javascript profiling in Chrome のコードを参考にしました。他にも CPU のプロファイルを取ったりといった各種パフォーマンスメトリクスの収集のサンプルコードがあるので、頭の片隅に置いておくとよさそうです。

Speed Index を算出する手順

材料が揃ったので、手順を示します。

適当に npm でプロジェクトを作成して(npm init)、chrome-remote-interface と speedline をインストールします(npm install chrome-remote-interface --save, npm install -g speedline)。グローバルにインストールしたくない場合は、--save でインストールして、npm-scripts から呼び出すようにしてください。

Debbuging port を開いて Chrome を起動します。Macだと、/Applications/Google\ Chrome.app/Contents/MacOS/Google\ Chrome --remote-debugging-port=9222 --user-data-dir=$TMPDIR/chrome-profiling --no-default-browser-check というコマンドです。

以下のスクリプトを用意し、node で実行します。

const fs = require('fs');
const Chrome = require('chrome-remote-interface');

const TRACE_CATEGORIES = ["-*", "devtools.timeline", "disabled-by-default-devtools.timeline", "disabled-by-default-devtools.timeline.frame", "toplevel", "blink.console", "disabled-by-default-devtools.timeline.stack", "disabled-by-default-devtools.screenshot", "disabled-by-default-v8.cpu_profile"];

const rawEvents = [];

Chrome(function (chrome) {
    with (chrome) {
        Page.enable();
        Tracing.start({
            "categories": TRACE_CATEGORIES.join(','),
            "options": "sampling-frequency=10000"  // 1000 is default and too slow.
        });
        Page.navigate({'url': '自分が Speed Index 値を算出したいサイトの URL に置き換える'})
        Page.loadEventFired(function () {
           Tracing.end()
        });

        Tracing.tracingComplete(function () {
            var file = 'profile-' + Date.now() + '.devtools.trace';
            fs.writeFileSync(file, JSON.stringify(rawEvents, null, 2));
            console.log('Trace file: ' + file);
            chrome.close();
        });

        Tracing.dataCollected(function(data){
            var events = data.value;
            rawEvents = rawEvents.concat(events);
        });
    }
}).on('error', function (e) {
    console.error('Cannot connect to Chrome', e);
});

トレースした内容が profile-1482725139003.devtools.trace のようなファイル名で保存されるので、speedline コマンドに食わせて Speed Index を算出させます。 (speedline ./profile-1482725139003.devtools.trace)

First Visual Change: 50 Visually Complete: 1586

Speed Index: 1177.4 Visual Progress: 0=0%, 50=77%, 161=17%, 330=17%, 1420=60%, 1507=72%, 1586=100%

Perceptual Speed Index: 440.0 Perceptual Visual Progress: 0=0%, 50=91%, 161=72%, 330=72%, 1420=73%, 1507=86%, 1586=100%

ヒストグラムを表示する場合は、speedline ./profile-1482725139003.devtools.trace --pretty

f:id:kitak:20161226191109p:plain

単純に算出された Speed Index だけ扱いたい場合は speedline の JavaScript API を以下のようなスクリプトで呼び出します。

const speedline = require('speedline');

speedline('./profile-1482725139003.devtools.trace').then((results) => {
  console.log('Speed Index value:', results.speedIndex);
});

意外と簡単にできました。何回か算出をおこないましたが、Timeline のトレースがうまくできないケースもあるようです(原因はちょっと不明)。今回はツールの使い方だけでしたが、算出方法を解説しながら、speedline のコードリーディングをしてもよさそうですね。