Node.js
RequireJS
reactjs
webpack

require()とは何か?何が便利なのか

More than 1 year has passed since last update.

問題提起

最近のJSのサンプルコードは、だいたい文頭に

var $ = require('jquery');

などとついていますが、このrequire()ってよくわからない。

具体的には、

  • どうやって使えばいいの?
  • 普通にscriptタグで読み込む場合とどう違うの?
  • 「require」でググっても英和辞典とかしかでないんだけど!

ということでざっと調べてみました。

require()とは何か?

commonJS

http://www.slideshare.net/terurou/common-js

以下、要約

そもそもの発端は、「Javascriptって良いよね。ブラウザ以外(ServerSide)でも使おうぜ」ということからだったらしいです。

しかし、scriptタグで読み込むこと前提だったので、HTMLがない(レンダリングエンジンがない)場合に外部ライブラリを参照する方法がない。。。
(さらに言えば、FileやNetwork、標準入出力など色々と不便。)

これじゃ困るということで、ServerSideの標準仕様を定めたのがcommonJS。

その中で外部ライブラリを参照する方法が、各JSファイルをモジュール化しておいて、使うときはrequire()で読み込むやりかた。

つまり、require()はcommonJSの仕様の一つであって、特定の実装・ライブラリを指しているわけじゃないようです。

node.js

ServerSideでJavascriptを使えるようにしたもの。

当然require()はあるが独自拡張しており、最近はcommonJSを無視しているとかなんとか。(ちょと古い?)

http://nodejs.jp/nodejs.org_ja/api/modules.html

http://meso.hatenablog.com/entry/20110626/1309082158

nodeにはnpmというパッケージマネージャがありますが、これでインストールしたものはrequire()で読み込めます。

RequireJS

http://requirejs.org/docs/commonjs.html

CommonJS defines a module format. Unfortunately, it was defined without giving browsers equal footing to other JavaScript environments. Because of that, there are CommonJS spec proposals for Transport formats and an asynchronous require.

commonJSの仕様はServerSideのために作られたはずなんですが、ClientSideでもrequire()を使いたい、ということで作られたライブラリ。

<script data-main="js/main.js" src="bower_components/requirejs/require.js"></script>

とすればmain.jsをentryPointとして動作するらしい。

webpack

http://ameblo.jp/ca-1pixel/entry-11884453208.html

Require.jsをもっとリッチにしたもの。

require()の対象をjsのモジュールだけでなく、

  • altJSのコンパイル
  • CSSやHTMLファイル取り込み
  • (bower経由などの)jsファイル取り込み

などができるようになっている。

Require.jsと比較すると、

  • Require.jsは、ブラウザ側で、個々のファイル(モジュール)を非同期に読み込むスタイル。
  • webpackは、サーバー側で依存関係を全て見て、一つのjsファイルを生成しておくスタイル。
    • (もちろん、sourceMappingされるので実行時デバッグも問題ない。)

似たものにbrowserifyというのがある。(webpackの方が高機能っぽいので検証してない。)

require()のメリット

require()は、jsをモジュール化する仕組みです。

従来のClientSideのJavascriptでは、scriptタグで読み込んでグローバルに転がしておくしかなかった。

一応MVCなどのパターンでjsファイルを分割するものの、各ファイルが密結合する(あるいはうっかり影響を与えてしまう)ことを防げなくて再利用性に乏しかった。

再利用しやすくなる。

モジュール化する、と同義ですね。

単体テストがしやすくなる。

外部依存をrequire()のみに限定することで、それ単体で動かすことができる。

require()の部分にMockを差し込むテストツールもある。
https://facebook.github.io/jest/

特にReact

コンポーネントをたくさん作って組み合わせていくスタイルなので、単体テストがやりやすいrequire()と非常に相性がいい。

http://facebook.github.io/jest/docs/tutorial-react.html#content

require()のデメリット。

  • 学習コストがかかる。
  • ブラウザで気軽に試せない。(Require.jsかwebpack/browserifyが必要)

とはいえ、node.jsでは既に一般的だし、グローバルに転がすのはイケてないので、もはや導入しない理由はない気がします。