Next.jsライクなReact Routerを作ってみた

今年の5月ごろにOSSなJSライブラリとして非同期対応をしたReact Routerを実装して公開しました。
その時の気持ちやモチベーションをまとめたに記事なります。
今まで技術的な勉強をしたとしてもオープンな場にはアップせずにいましたが、一つの挑戦としてJSライブラリの公開まで行いました。

私自身はサーバサイドエンジニア(PHP)なので、フロントエンドはチョットデキル程度です。
そのため、至らないところや「すでに似たライブラリあるよー」など、アドバイスを頂けるとうれしいです！

# React Routerの何が不満だったのか
+ サーバサイドエンジニアとしてReact Routerの処理の流れが不満でした
    + URL変更をキャッチ
    + URLにマッチしたViewを表示
    + Viewを表示後、APIに問い合わせしてデータをロード
    + ローディング画像でロード中をアピール
    + ロード完了でStateを更新
    + Viewを更新
    + やっと完成した画面に！
+ 理想の処理はサーバサイドの再現
    + URL変更をキャッチ
    + APIに問い合わせしてデータをロード
    + [nprogress](https://github.com/rstacruz/nprogress)でさらっとプログレスバーを表示
    + ロード完了でStateを更新
    + URLにマッチしたViewを表示
    + すでに完成した画面に！
+ 理想のサイト
    + [GitHubのリポジトリ](https://github.com/oneut/async-react-router)
    + [amakan](https://amakan.net/)
+ Next.jsは機能がもりもり過ぎた
    + async/awaitで管理できるのはとてもうれしく、これでいいのでは！？と思ったが、SSR前提はつらい
    + Next.js v2.0の時に作ったので、変わっているかも。

**=> Next.jsライクなReact Routerを作るっきゃない！**

# できあがったもの
Next.jsライクに非同期処理を扱えるReact Router、その名も「async-react-router」
※Next.jsと比較するとネーミングが地味。

https://github.com/oneut/async-react-router

# 特徴
+ Next.jsライクに初期値が取得可能
    + `getInitialProps()`あります！
+ async/awaitサポート
+ [path-to-regex](https://github.com/pillarjs/path-to-regexp)でURLパラメーターをサポート
+ [history](https://www.npmjs.com/package/history)でブラウザ履歴をサポート
    + Browser History
    + Hash History
    + Memory History
+ SSRサポート
+ [rxjs@5.x.x](https://github.com/Reactive-Extensions/RxJS)に依存
    + async/awaitで管理しているので整合性を保つために導入
+ React Routerには非依存
+ Reduxやflux-utilsなどのFluxライブラリにも非依存

# デモ

4つのデモを作成。

+ [Basic Example](https://oneut.github.io/async-react-router/basic/)
+ [Redux Example(Hacker News)](https://oneut.github.io/async-react-router/redux/)
+ [flux-utils Example(Hacker News)](https://oneut.github.io/async-react-router/flux-utils/)
+ [SSR](https://github.com/oneut/async-react-router/tree/master/examples/ssr-with-redux) ※cloneしないと試せないので、README.mdへのリンク

# ものすごく参考にしたリポジトリ
+ [next.js](https://github.com/zeit/next.js/)
+ [react-router](https://github.com/ReactTraining/react-router)
+ [react-enroute](https://github.com/tj/react-enroute)
+ [enroute](https://github.com/lapwinglabs/enroute)

# 作ってわかったこと
+ npmjs.comにアップするのが簡単
    + `npm publish`と入力して、Enterをッターン!
+ SaaSと連携すると一人で開発していても寂しくない
    + [Travis Cl](https://travis-ci.org/)
        + CI環境
    + [Coveralls](https://coveralls.io/)
        + テスト
    + [Code Climate](https://codeclimate.com/)
        + コードの品質チェック
    + [David-DM](https://david-dm.org/)
        + 依存パッケージチェック
+ SaaSのバッジつけるの楽しい
    + OSS感が出てモチベーションがあがる
+ デモづくり楽しい
    + 普段使わないライブラリをめっちゃ試せる
        + [react-scripts](https://www.npmjs.com/package/react-scripts)便利
            + さくっとreactアプリケーション作れる
        + [lru-cache](https://www.npmjs.com/package/lru-cache)便利
            + さくっとキャッシュできる
            + フロントエンドでもメモリキャッシュが簡単にできて面白い
+ webpackが難しい
    + SSRのデモで、本番環境と開発環境を一つの環境で完結できるように構築してみたが、すごいしんどい。
        + 魔改造している感ある。
        + 完成形がなかなか見えない。
    + 費やした時間が、webpack＞＞＞＞越えられない壁＞＞＞＞ライブラリ実装
+ babel-nodeやbabel registerは本番環境では使ってはいけない
    + [babel-node](https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/user-handbook.md#babel-node): Note that this is not meant for production use.
    + [babel register](https://github.com/thejameskyle/babel-handbook/blob/master/translations/en/user-handbook.md#babel-register): Note that this is not meant for production use.
+ [npmのあまり知られてない機能](http://yosuke-furukawa.hatenablog.com/entry/2014/06/10/100410)を知れた
    + `npm publish`でのタグ管理でとてもお世話になりました
+ READMEを英語で書くのが難しい
    + 英語能力の低さを痛感できる
    + ライブラリを知らない人に向けて書くので、そもそも日本語でまとめるのも難しい
+ :star: Starがつくとめっちゃうれしい！

# 課題
+ READMEで、Attentionを書いて予防線を張っている
    + メンタルが豆腐
+ SSRのデモがごり押し
    + 動作するけど調整が必要。webpack・・・。
+ 本番導入はしていない
    + 趣味で作った程度で終わっている。
+ undocumentなAPIがある
    + 実装に比べてドキュメントへのモチベーションが低い・・・。

# まとめ

ダウンロード数やスター数を見てもあまりOSSとして貢献はできていませんが、世の中にOSSなライブラリとして公開するのはとても新鮮で良い経験でした。
versionも1.0までにしたので、最低限の目標にしていた実装まではやりきることができました。
少しずつですがOSSに貢献できるように今後もエンジニアとして頑張っていければと思います。
来年も一年がんばるぞい！