記法がたくさんあって難しいので調べた。
モジュール化とは
モジュール化とは、別ファイルに分割することである。
require.jsとは
require.jsとは、モジュール化するためのライブラリである。
requireとは
requireとは、「必要とする」という意味の動詞。
やってみた
以前やってみたが、じつは他にも記法がたくさんある。
require.jsの使い方
公式サイトのAPIリファレンスを参照した。これを読めばマスターできるが、多すぎるので以下に抜粋する。
これさえあればいい
こんなときどう書く?
プラグイン
- 6.テキストファイル受信
- 7.DOM読込完了待機
- 8.国際化(i18n)
コード
構成
- index.html
- js/
- app.js
- lib/
- require/
- require.js
 
 
- require/
- app/
- main.js
- sub.js
 
 
main.jsからsub.jsを呼び出すのが狙い。
ファイル内容
index.html
<!DOCTYPE html> <html lang="ja"> <head> <meta charset="utf-8"> <script data-main="app.js" src="js/lib/require/require.js"></script> </head> <body></body> </html>
app.js
require(['js/app/main.js']);
main.js
define(function(require, exports, module) { var sub = require('js/app/sub'); sub.print("MESSAGE!!"); });
sub.js
define(function() { return { print: function(msg) { alert(msg); console.log(msg); } }; });
index.html
 data-main属性によりエントリポイントを指定している。
index.html
<script data-main="app.js" src="js/lib/require/require.js"></script>
特殊な記法だが、ほかにもいくつかパターンがある。この方法が最もスマート。
app.js
requireの設定をするときにmain.jsと分離しておきたいから用意した。たとえば以下のように分離する。
app.js
require.config({ paths: { jquery: "js/lib/jquery/jquery-3.3.1.min.js" } }); require(['js/app/main.js']);
main.js
define(function(require, exports, module) { var $ = require('jquery'); $("body").html("Hello jQuery !!"); });
main.js
CommonJS方式。
define(function(require, exports, module) {
 引数exports, moduleは使っていないので省略できる。
define(function(require) {
sub.js
define(function() {
 もし他のコードをインポートしたくなったらrequire引数を追加する。
define(function(require) { var $ = require('jquery');
 exports, moduleを追加してもいい。
define(function(require, exports, module) {
ES6 class
ES6のclassが実装されてるなら使うといい。
main.js
define(function(require, exports, module) { const Human = require('js/app/Human'); const h = new Human("Yamada"); h.Speak(); });
Human.js
define(function() { return class Human { constructor(name=null){ this._name = name; } get Name() { return this._name; } set Name(v) { if(v){ this._name = v; } } Speak() { alert(this._name); console.log(this._name); } }; });
sub.jsをHuman.jsに置き換えた。classをreturnしている。
モジュール化
require.jsでモジュール化するコードの記法は場合によってたくさんある。以下のうち1.3.5 Define a Module with Simplified CommonJS Wrapperの方法が最も汎用的だと思う。
| コード概要 | 説明URL | 
|---|---|
| require(){...} | 1.2 data-main Entry Point | 
| define({...}) | 1.3.1 Simple Name/Value Pairs | 
| define(function () {... return {...};}) | 1.3.2 Definition Functions | 
| define(["./foo", "./bar"], function(foo, bar) {... return {...};}) | 1.3.3 Definition Functions with Dependencies | 
| define(["./foo", "./bar"], function(foo, bar) {... return function(){...};}) | 1.3.4 Define a Module as a Function | 
| define(function(require, exports, module) {... return {...};}) | 1.3.5 Define a Module with Simplified CommonJS Wrapper | 
| define("foo/title", ["a/A", "a/B"], function(A, B) {...}); | 1.3.6 Define a Module with a Name | 
| define(["require", "./relative/name"], function(require) { var mod = require("./relative/name"); }); | 1.3.7 Other Module Notes | 
| define(function(require) { var mod = require("./relative/name"); }); | 1.3.7 Other Module Notes Better | 
| define(["require", "a"], function(require, a) { return function(title) { return require("a").doSomething(); }});or define(function(require, exports, module) { var a = require("a"); exports.foo = function () { return a.bar(); }; }); | 1.3.8 Circular Dependencies 循環参照 | 
| require(["http://example.com/api/data.json?callback=define"], function (data) { console.log(data); }); | 1.3.9 Specify a JSONP Service Dependency | 
比較
以下のうちAのほうが好ましい。特にインポートするファイル数が多くなると顕著。
インポート数1
A
define(function (require) {
    var sub = require('js/app/sub');
    return function () {
        sub.print();
    };
});
B
define(['js/app/sub'] , function (sub) {
    return function () { sub.print(); };
});
インポート数3
A
define(function (require) {
    var sub1 = require('js/app/sub1');
    var sub2 = require('js/app/sub2');
    var sub3 = require('js/app/sub3');
    return function () {
        sub1.print();
    };
});
インポートの追加や削除をするとき、行の編集だけで済む。
B
define(['js/app/sub1','js/app/sub2','js/app/sub3'] , function (sub1,sub2,sub3) {
    return function () { sub1.print(); };
});
インポートの追加と削除をするとき、配列と引数をそれぞれ編集せねばならない。カンマの編集や、配列と引数の位置を合わせねばならない。ミスしそう。可読性が低い。
循環参照
A, Bともに少し特殊な記述になる。
A
js/app/sub2.js
define(function(require, exports, module) {
    var sub1 = require("js/app/sub1");
    exports.foo = function () {
        return sub1.print(); // sub1.jsで本ファイルsub2.jsを参照する
    };
});
 sub2.jsでエクスポートしたい場合、exportsオブジェクトに生成する必要がある。(非循環参照の場合:エクスポートするオブジェクトはreturnで返していた)
B
js/app/sub2.js
define(['js/lib/require/require', 'js/app/sub1'] , function (require, sub1) {
    return function() {
        return require("js/app/sub1").print(); // sub1.jsで本ファイルsub2.jsを参照する
    }
});
 require.jsをインポートする必要がある。(非循環参照の場合:require.jsのインポートは不要だった)