要約
- 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の使い方が違う。(規格とはなんだったのか)
すごく文句をつけたいところだけど、ブラウザの力だけではどうにもできなかったのかもしれないし、規格を捨ててでも同等の機能を実装するには、きっと仕方がないことだと思いながら使うことにする。
// 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はこうする
<!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とライブラリを使って「ビルド」する形にしたいか、実装を選んで使い分けましょう、ということかと思う。