LoginSignup
11
12

More than 5 years have passed since last update.

ブラウザ、Node.jsで両方使えるjavascriptをgruntで自動化

Last updated at Posted at 2014-05-30

実際にはどれだけの需要が有るか分からないけど、gruntのモジュールを作成してみました。

ブラウザとNode.jsで両方使えるjavascriptを記述するのに、ここここここにも投稿があるんですが、今回gruntとRequireJSでやってみたらすっげー楽なんじゃないか?と思ってモジュールを作ってみたので公開します。

github - grunt-m2r

何が楽なの?

普通にNode.js側のコードだけを記述すれば、ブラウザ側のコードに変換しちゃいます。
先のような投稿のハックは不要(になるはず?)です。
しかも、クライアントでもモジュール毎にファイルを作成できるし!管理も楽!

使い方

readme.mdじゃなくて、次の手順で体験したほうが理解が早いです。
手順どおり打てばいいだけなんですが、mac環境であることを前提にしています。
(winの方は申し訳ない)

  1. まず何はともあれ、gruntを使えるようにします。
  2. 空のディレクトリを適当に作成しそこに移動
    • mkdir tutorial
    • cd tutorial
  3. 今回公開しているモジュールのgrunt-m2rをnpm経由でインストール
    • npm install grunt-m2r
  4. node_modules/grunt-m2rのexampleフォルダの中身を先のディレクトリに複製
    • cp -r ./node_modules/grunt-m2r/example/* .
  5. 必要モジュールをインストール
    • npm install
  6. gruntを走らせてみる
    • grunt
  7. index.htmlをブラウザで開く
  8. コンソールを確認する
    • chromeならoption + command + j
    • foo say hellobar say helloが表示されていると成功!!!

解説

libにはnodeのjsがsrcにはブラウザのjsが配置されています。
lib以下のファイルを更新後に、gruntを走らせるとsrcフォルダが作成されファイルが変換されます。
foo.jsとbar.jsが作成されているはずです。
index.htmlはRequireJSを使用してmain.jsから順にsrc/foo.js,src/bar.jsを呼び出しています

一方node側でも動作させてみたい場合は、サンプルではapp.jsをエントリポイントとして作ってあるので、node app.jsとしてみるとブラウザと同じ表示がされると思います。

変換処理自体は単純です。
+ ファイルにコメント/*grunt-m2r*/がある場合は変換できるファイルと判別します
+ var foo = require('foo');の記述があったら、ひたすらRequireJSの事前読み込みモジュールに設定
+ exports.bar = ...とかあるなら、最後にreturn exports;を追加
+ もしくはmodule.exports = baz;return baz;にする

コレくらいしかしていません。

自動変換でもっと楽に

もし、nodeの方のjsを更新するたびに、自動的にブラウザ側のjsを変換したい場合はwatchを有効にすると手間いらずです。

  1. Gruntfile.jsのtaskでwatchを有効にする
    • manualの行をコメントアウト
    • autoの行のコメントをはずす
  2. index.htmlの自動リロードを有効にする
    • livereload.jsのスクリプトのコメントアウトをはずす
  3. gruntを走らせる
    • grunt
  4. 終了する場合はCtrl+c

これで、ブラウザを開いたままnodeの変更すると、ブラウザの方まで自動更新されます
ただ、変換対象のファイルが増えてくると、gruntがどんどん重くなるので、自動更新は程々がよさそうかな?

nodeの標準モジュールは使えない?

このままじゃ、nodeの標準のモジュールをクライアントで使用出来ません。
さすがに、全部移植なんて無理なのであきらめます。
でも、いくつか便利なものは使いたいなーと思ってeventsとutil.inheritsだけ移植してみました。
ここら辺は付け焼き刃なので、utilはinherits以外は実装していません

それぞれ、util.js, events.jsをsrcフォルダに入れるだけで、ブラウザでも
EventEmitterを継承する事ができるようになります。
ただし、簡略して記述しないでください。

// これは無理
var EventEmitter = require('events').EventEmitter;
require('util').inherits(Klass, EventEmitter);

grunt-m2rのコンパイラがそこまでは頭は良くないので、次のようにお願いします

// これはOK
var events = require('events');
var util = require('util');
util.inherits(Klass, events.EventEmitter);

さいごに

例のごとく、テストが不十分です。不具合はissueを入れてくれると助かります。
あと、m2rの意味はmodule to requirejsです。
gruntのモジュールを作るのは初めてでしたので、いろいろ戸惑いました。
grunt-pluginの作り方と解剖
がすごく参考になりました。fnobiさんありがとう!
RequireJSも今までは採用していなかったのですが、gruntと一緒に使うことで楽になるので、本格的に使ってみようかな。

追記

(2014/6/3)モジュールのバージョンアップに伴い、記事を修正しました
(2014/6/22)モジュールのバージョンアップに伴い、記事を修正しました

11
12
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
11
12