6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

JavaScriptAdvent Calendar 2014

Day 12

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

Posted at

ここのところ、クライアントサイド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'))。

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

6
6
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
6

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?