JavaScriptでよく見る`var hoge=require('hoge')`ってなに？


要約
-----
- JavaScript界隈で`require`をよく見るので使いたかったが、ブラウザ上でどうすれば使えるかわからなかったので調べた
- `require`はCommonJSという規格で決まっている
- Require.JSであればブラウザのみで`require`の仕組みを享受できる事が分かった
  - ただし、`var hoge=require('hoge');/* use hoge code */`というCommonJSの規格通りにはかけず、`require(['hoge'],function(hoge){ /* use hoge code */});`という形で書く必要がある。残念に思う。

背景
-----
最近、ちょっと動きがあるWeb画面を書いており、JavaScriptのコードでちょっと便利なライブラリがないかな？と調べたりしていると、まさしくこれがやりたかった！というものは見つかるけど大半はいきなり`require('...')`という記述で始まる。実際にその通り書いても「requireなんて関数はない」とか言われるし、使おうとしてもnodejsを入れないといけないみたいな雰囲気の情報しか出ない。ブラウザで動かしたいだけなのに。

自分の中でJavaScriptはブラウザのための言語だという認識が強かったのもあり、htmlファイルにscriptタグ書いてその中にコードをコピペしてブラウザで開けば動くものだと思っていたが、最近はどうも違うらしい。

歴史(適当)
------
今日、nodejs(v8?)のおかげでブラウザ以外でも実行できる環境が出てきた。今後クライアントサイドでもサーバサイドでもJavaScriptが使われるのだから、`require`など共通で使える便利なものはCommonJSという規格で定めていきましょう、ということになったらしい。

requireとは？
-----
`require`はCommonJSの規格のModulesを構成する1つとして定義されている。`require`はhtmlファイルのscriptタグに相当する処理を、JavaScript内だけで出来るようにしてくれるものに見える。(実際は名前空間とかあるのだろうから、そこまで単純ではないとは思うけど。)
Javaでいうimport、Perlでいうuse、Cでいう#includeに相当するものだと思う

requireの実装はどこにある？
------
CommonJSは規格だけで、実装は提供していない。絵に描いた餅で。
ブラウザで使えるrequireの実装はどこにあるのか？というと、いろいろある。

- Require.JS
- browserify
- Webpack

細かく調べればもっとあるんだろうけど、とりあえずここまで。ユーザが勝手に規格を実装すれば作れてしまうからキリがない。

で、上の3つのうち、browserifyとWebpackはrequireを使ったコードに対して「ビルド」を行う形で使う。ビルドではコード中のrequireというものを見つけていい感じにコードを組み替えて、requireでライブラリの機能を取り込んだのと同等なコードを出してくれる模様。あとはブラウザでビルド済みのコードをscriptタグで読み込めばOKという形だ。最近はWebpackがよさそうな感じがする。ビルドがbrowserifyより早いと聞いただけだけど。

でもbrowserifyとWebpackはNode.js導入が前提らしい。ブラウザでちょっと動作確認できればいいのに。よって、却下。(※プロダクトで使うなら使った方が良いと思います。)

そして最後に残った一番上のRequire.jsはブラウザさえあれば動作する。やった！

遊ぶ
------
サンプルとしてReact.jsでhello worldするのを`require`を通してやってみたい。

まずRequire.jsをgetしてきて`build/require.js`へ配備しておく。
次に、React.jsもgetしてきて`build/react.js`へ配備しておく。
次に、React.jsを扱うコード`build/hello.js`を書く。
最後に、hello.jsを扱うコード`hello.html`を書く。

ただ、ここで少し悲しいお知らせがある。CommonJSで決めたrequireの使い方と、Require.JSの使い方が違う。(規格とはなんだったのか)
すごく文句をつけたいところだけど、ブラウザの力だけではどうにもできなかったのかもしれないし、規格を捨ててでも同等の機能を実装するには、きっと仕方がないことだと思いながら使うことにする。

```js:build/hello.js
// var React = require('react'); // ... とはかけない。恨むならRequire.jsを恨め。

// 第1引数のarrayで読み込むライブラリを並べて、第2引数のfunctionで受ける。
require(['react'], function(React){ // require.jsを使わない場合ここの行を削除
	var App = React.createClass({displayName: "App",
		render: function(){
			return (
				React.createElement("p", null, "Hello React")
			);
		}
	});

	React.render(
		React.createElement("h1", null, React.createElement(App, null)),
		document.getElementById('app')
	);
}); // require.jsを使わない場合ここの行を削除
```

これをブラウザで呼びたいので、htmlはこうする

```html:hello.html
<!DOCTYPE html>
<html>
  <head>
    <title>Hello React!</title>
  </head>
  <body>
     <div id="app"></div>
    <!-- require.jsを使う前はこんな感じ
    <script src="build/react.js"></script>
    <script src="build/hello.js"></script>
    <!-- -->
    <!-- require.jsを使うときはこんな感じ -->
     <script data-main="build/hello" src="build/require.js"></script>
   <!-- -->
  </body>
</html>
```

`data-main`属性に呼び出したい処理を書いて、`src`属性にはrequire.jsを指定する。require.jsは`data-main`属性で指定したファイル(今回は`build/hello.js`)を読み取り、さらに内部でrequireされているファイルを読み取ってくれるらしい。今回はReact.jsのみしか読んでいないのでその動きまでは見れないけど。

また、`hello.html`と`hello.js`のコメントアウトしている箇所にある通り、該当行を修正するとrequire.jsを使わない形に出来る。

あとはブラウザだけで手軽にやりたいか、nodejsとライブラリを使って「ビルド」する形にしたいか、実装を選んで使い分けましょう、ということかと思う。