クライアントサイドJS・サーバサイド間の設定の共有について

  • 8
    いいね
  • 0
    コメント
この記事は最終更新日から1年以上が経過しています。

ここのところ、クライアントサイドJSとサーバサイドで設定の共有をしたいなと思うことがよくあった。拙いながらその方法について考えてみた。

やりたいこと

├── app
├── config
│   ├── production
│   │   ├── public.json
│   │   └── private.json
│   ├── staging
│   │   ├── public.json
│   │   └── private.json
│   ├── public.json
│   └── private.json
├── public

まず、サーバサイド(ここではappディレクトリ以下)とクライアントサイド(ここではpublic以下)で設定を共有したいこと自体はよくあると思う。

ユーザーがコンテンツを投稿できるようなアプリケーションの場合、たとえばユーザーの投稿数の制限だとか、文字の最大数の制限だとか、バリデーション周りで頻出する。

それで別々に設定を書くだとか、設定をサーバサイドからHTTPリクエストで受け取るだとかは、あまりスマートじゃないと考えていて、クライアントサイドはBrowserifyとかWebpackでJSONファイルをrequireするような形で読み込めればいいと思った。

設定の中には、DBへ接続する情報だとか、OAuth認証のConsumer Keyだとか、クライアントサイド側には渡したくない設定もあって、これはprivate.jsonのような形で別々にする必要がある。

また、設定は環境によって変えたいことが当たり前なので、環境ごとにディレクトリを作り、production/private.jsonのように分けておけるといいと思った。

やり方

実装としてはこうなった。下記リポジトリを参照。

axross/config_management_sample | Github
https://github.com/axross/config_management_sample

// returns default config
// var CONFIG = require('../config')();

// returns production config
// var CONFIG = require('../config')('production');

// also
// var CONFIG = require('../config')(process.env.NODE_ENV);

// for client-side js
// var CONFIG = require('../config/bundle.json');

色々融通を利かせてるうちにindex.jsのコードが長くなってしまったけど、それなりっぽくなったかなって感覚はあって、たとえばNode.js側からはvar CONFIG = require('./config')(process.env.NODE_ENV)って具合に呼べるようにできた。

また、いずれpublicprivateだけではなく、フィールドやファイルを分けたくなるシーンも発生するような気がしたので、同じ階層にある別名のJSONファイルは、ファイル名を大文字化した上で設定の中に巻き込むようにした。

クライアントサイド向けにJSONファイルを書き出しているのは、Privateな設定を隠すのと、Browserifyとかでこのindex.jsもバンドルされるのは気持ち悪いなと思ったから。

クライアントサイドでの実際の使い方としては、gulpのビルドタスクなどでconfig.generateBundle('production', function() { ... })のように実行してやる。

すると、bundle.jsonが生成されるので、これをrequireするようにすればよい。

また、Webpackの場合、別途JSONローダーが必要になるんだけど、そのJSONローダーを使ってどうやってもJSONファイルが読み込めなかったので、Webpackを使うならmodule.exports =という文字を先頭に足して、JSONではなくJavascriptファイル化してやる必要がある。

問題かつ本題

設定の共有こそできるものの、クライアントサイドとサーバサイドで設定にアクセスするAPIが違うのは気持ち悪い(サーバーはrequire('./config')、クライアントはrequire('./config/bundle.json'))。

これを解決できるうまい方法があったら教えてください。

この投稿は JavaScript Advent Calendar 201412日目の記事です。