やってみる

アウトプットすべく己を導くためのブログ。その試行錯誤すらたれ流す。

require.jsの使い方(最小コード)

すぐに使える短いコードを書いた。

成果物

方法

1.CDN

要ネット接続。require.jsをネットから取得するためローカルに配置せずに済む。

  • index.html
  • app.js
  • src/
    • main.js
    • sub.js
<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>require.js CDN</title>
    <script data-main="app.js" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.5/require.min.js"></script>
</head>
<body></body>
</html>
requirejs(['js/app/main.js']);

js/app/mian.js

define(function(require, exports, module) {
    var sub = require('js/app/sub');
    sub.print("MESSAGE!!");
});

js/app/sub.js

define(function() {
    return {
        print: function(msg) {
            alert(msg);
            console.log(msg);
        }
    };
});

2.Local file

3.ES6 class

require.jsの使い方まとめ

require.jsを使ってモジュール化する方法。

成果物

モジュール化とは

モジュール化とは、別ファイルに分割することである。

require.jsとは

require.jsとは、モジュール化するためのライブラリである。

require.jsの使い方

公式サイトのAPIリファレンスを参照した。

これさえあればいい

  • 1.最小コード
  • 2.ベストプラクティス
  • 3.外部ライブラリ使用

こんなときどうする?

  • 4.JSONP受信
  • 5.循環依存

こんなときどうする?

  • 4.テキストファイル受信
  • 5.DOM読込完了待機
  • 6.国際化(i18n)

こんな書き方もできる

  • 6.テキストファイル受信

最小コード

1. HTML内

index.html

<html>
<head>
<script>alert("JavaScript!!");</script>
</head>
</html>

HTML内にJSが混在。JSが極小でコードを変更しないなら問題も少ない。

2. 外部ファイル化

index.html

<html>
<head>
<script src="main.js"></script>
</head>
</html>

main.js

alert("JavaScript!!");

HTMLとJSを分離してスッキリ。でも……

JSからJSを呼び出せない

JSコードの規模が大きくなると、JSファイルを複数に分割したくなる。なのにJSには外部呼出する言語仕様がない。(現在はimport文がある)

index.html

<html>
<head>
<script src="main.js"></script>
</head>
</html>

main.js

class Human {
    constractor(name=null) { this._name = name; }
    Speak() { alert(this._name); }
}
const h = new Human();
h.Speak();

クラス定義と呼出を別ファイルに分離したいのに……。

3. 順序呼出

JSのファイル分割はできる。ただ、苦肉の策である。HTMLの<script>タグでJSコードを順に呼び出すことになる。

index.html

<html>
<head>
<script src="Human.js"></script>
<script src="main.js"></script>
</head>
</html>

main.js

const h = new Human();
h.Speak();

Human.js

class Human {
    constractor(name=null) { this._name = name; }
    Speak() { alert(this._name); }
}

依存順序を把握せねばならない

呼出の順序が重要である。main.jsではHumanを使用しているので、main.jsをロードする前にHumanを定義してあるHuman.jsをロードせねばならない。さもなくば参照エラーになる。

<script src="Human.js"></script>
<script src="main.js"></script>

もしJSコードの依存順序を変更することになれば、それに伴いHTMLの<script>タグ順序も変更せねばならない。開発者はJSコード全体の依存順序をすべて把握している必要がある。これは規模が大きくなると非常に苦痛である。

HTMLを変更せねばならない

JSのファイル名やパスが変更されるとsrc属性値を変更せねばならない。

JSの変更なのにHTMLファイルを編集するのだ。リビジョン管理するときの対象ファイルにHTMLが入ってしまう。

4 DOMでscriptタグ追加

JSコード内でHTMLへ<script>タグを動的に追加する方法もある。

コード自体はJSで書けるので、HTMLファイルを修正する必要は最小限で済む。ただ、依存する順序に沿ってロードせねばならない問題は残る。

index.html

<html>
<head>
<script src="jsloader.js"></script>
</head>
</html>

jsloader.js

function Load(path) {
    var script=document.createElement('script');
    script.setAttribute("src", path);
    document.body.appendChild(script);
}
Load("Human.js");
Load("main.js");

5. require.js

require.jsというライブラリを使う。依存順序を気にせず書ける。

ただ、ライブラリ固有の表現や設定をせねばならない。

index.html

<!DOCTYPE html>
<html lang="ja">
<head>
    <meta charset="utf-8">
    <title>require.js</title>
    <script data-main="app.js" src="js/lib/require/require.min.js"></script>
</head>
<body></body>
</html>

他のライブラリを使うときは以下のようにrequire.configを設定する。

app.js

require.config({
    paths: {
    'text': 'js/lib/require/text',
    'jquery': 'js/lib/jquery/jquery-3.3.1.min',
    }
});
requirejs(['js/app/main.js']);

js/app/main.js

define(function(require, exports, module) {
    var sub = require('js/app/sub');
    var $ = require('jquery');
    sub.print("ABC");
});

js/app/sub.js

define(function() {
    return {
        print: function(source) {
            alert(source);
        console.log(source);
        }
    };
});

6. ES Module

ES6からimportexport文が言語仕様に加わる。

ついにJavaScriptは標準でモジュール化できるようになった。

しかし、使える環境は限られる。ES Moduleを実装したブラウザは新しいものだ。Linuxは古いOSだと、ES Moduleを実装した新しいブラウザに更新できない。たとえばRaspbian8.0(Jessie)。

それの何が問題か?

  • JSの依存関係なのにHTMLでしか記述できない
    • HTMLの内容は変更しないのに、HTMLファイルを修正せねばならない
      • モジュールができるたびに
      • JSファイル名が変更されるたびに

呼出順序が

しかし、JSファイルから別のJSファイルを呼び出せない! 苦肉の策としてHTMLから順に呼び出す。

前回まで

私の環境Raspbian8.0ではimportが使えない。Raspbian8.0(Jessie)ではChromium56までだが、import,exportサポートはChromium61以上。

そこで、require.jsを使ってみた。

今回

もっと簡単に書きたい。require.jsの使い方を研究してみる。

  • require(){...}
  • define({...})
  • define(function () {... return {...};})
  • define(["./foo", "./bar"], function(foo, bar) {... return {...};})
  • define(["./foo", "./bar"], function(foo, bar) {... return function(){...};})
  • define(function(require, exports, module) {... return {...};})
コード概要 説明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(); }});|1.3.8 Circular Dependencies 循環参照 | | | |

require(){...}

require(['foo'], function(foo) {

});