5次元のカオス

南の島の学生がつらつらと日々を書き連ねます

require.jsを使ってみた

require.jsを使ってみた

以前のブログにて、

ユーザの体感速度について少しだけ書きました。

Webページの表示速度に対するユーザの反応について以下のような説が唱えられているそうです.

- 0-100ms : 早いと感じる
- 100ms-300ms:普通に感じる
- 300ms-1000ms:かなり重いと感じる

※ 許容できるのは約300ms程度まで

普段からWebページなどを作るにあたり、表示速度について頭を悩ませているのですが、

今回はjsの読み込み速度を改善してみようということで、require.jsを使ってみました.

以下、自分への健忘録としてメモ。

require.jsとは?

公式サイトより

RequireJS is a JavaScript file and module loader.
It is optimized for in-browser use, but it can be used in
other JavaScript environments, like Rhino and Node.
Using a modular script loader like RequireJS will improve
the speed and quality of your code.

英語むつかしいよぉ... ><

とりあえず要約すると、分割されたjsファイルを読み込むための環境だそうです。

これによって、開発時にはバラバラのファイルとして作ったjsファイルを本番環境では

1つのスクリプトタグで読み出せるようになります。

なぜrequire.jsを使うのか?

クライアントサイドjsを書く際に、jsのモジュールを分割して開発することが多いと思います。

(モジュールであったり、機能であったり分割する理由は様々あると思います)

headタグに以下のような感じでjsをたくさん読み込ませていることってありませんか?

(少なくとも僕はそうでした)

<script src=”js/main.js”></script>
<script src=”js/util.js”></script>
<script src=”js/module_1.js”></script>
<script src=”js/module_2.js”></script>
<script src=”js/page.js”></script>

このようにたくさんのscriptタグの書かれたhtmlファイルにアクセスするとき、

下図のようにファイルを1つずつ個別に読み込んでいくため、

読み込むjsの数が多ければ多いほど、webページの読み込みに時間がかかってしまいます。

f:id:pxp_ss:20131029142650p:plain

また、js同士で依存関係があった場合、読み込み順や、実行順も考慮しなければいけません。

少ないファイルの場合は、これでも十分かもしれませんが

ファイル数が多くなるほど、管理や速度が大変なことになってしまうことは目に見えると思います。

そこで、依存関係を解決し、分かりやすくjsの読み込みを管理するrequire.jsを使います。

実際にやってみた

環境情報

公式サイトより以下をダウンロード

  • RequireJS: version 2.1.9

また、ディレクトリ構成は以下の通りとなっています。

  • require-test
    • view
      • index.html
    • javascripts
      • lib
        • jquery
        • bootstrap.min
        • footerFixed
      • page
        • require.js
        • app-config.js
        • main.js
        • TestClass.js

※ 今回のブログではjsではなく、CoffeeScriptを使っています。

CoffeeScript -> jsへの変換はTRY COFFEESCRIPTからどうぞ

index.html

<html>
<head>
    <script src="../javascripts/lib/require.js">
    <script src="../javascripts/lib/app-config.js">
    <!-- data-main属性を使ってひとまとめに書くこともできる -->
    <!-- <script src="../javascripts/lib/require.js" data-main="app-config.js"></script> -->
</head>
<body>
    <p>Hello, World!</p>
</body>
</html>

適当なhtmlファイルを用意し、require.jsとその設定ファイルを読み込みます

app-config.coffee

do (require) ->
  require.config({

    # 作業ディレクトリの指定
    baseUrl : "../javascripts/page"

    # 作業ディレクトリに無いスクリプトファイルの読み込み
    paths : {
      'jQuery'            : "../lib/jquery"
      'bootstrap'         : "../lib/bootstrap.min"
      'footerFixed'       : "../lib/footerFixed"
    }

    # AMD非対応プラグインに対する依存設定
    shim: {
      'jQuery' : {
        exports : '$'
      }
      'bootstrap' : {
        deps : ['jQuery']
      }
    }
  })

  # リクエストを送信する
  require([
    'jQuery'
    , 'bootstrap'
    , 'footerFixed'
    , 'TestClass'
    , 'main'
  ], (jQuery, bootstrap, footerFixed, TestClass, main) ->
    console.log "require dane."
  )

require.configに読み込み先や依存関係を設定したあとに、

require関数でモジュールを読み出します。

※ require.configを設定する前にrequire関数を実行すると失敗します(当たり前)

※ require.configで設定できることをまとめている方がいらっしゃいました

requirejsのconfigを調べてみた

※ require.jsとjQueryを一緒に使うためにはすこし工夫がいるようです

RequireJSでjQueryを使う方法をまとめてみた

main.coffee

define(['jQuery', TestClass], ($, TestClass) ->
  $ ->
      testClass = new TestClass()
      console.log "Hello,World!"

      testClass.callHello()
)

依存関係のあるモジュールをdefineで定義することができます。

TestClass.coffee

define(['jQuery'], ($) ->
  class TestClass
    callHello : () ->
        console.log "Hello, TestCase.Class"
)

今までクラスを作る際に、window.NameSpaceみたいな感じにして、

他のファイルから呼び出していたのですが、依存関係を解決したので上のように書いてclassを返り値で渡してやることもできます

require.jsを使うことによるメリット

  • 読み込むjsファイルを管理しやすくなった

  • defineを書くことで、依存関係を明示的にできる

  • 見通しの良い統コードになった

  • htmlにscriptタグを追加しなくてもよくなる←

しかし ...

スクリプトタグはひとつにまとまったけど、

ファイルを1つずつ個別に読み込んでいくためにWebページの描画が重くなるという問題は

解決されていないのでは...? と思います

r.js

require.jsを使って設定したコードをミニファイし、オプティマイズするためのツール

複数あるファイルを1つにまとめるだけではなく、空白タブや変数名の最適化も行うもの

導入

npmでインストールできます

npm install -g requirejs

※ npm : node.jsのパッケージ管理ツール

実際にやってみた

いろんな方法があるようなのですが、いちいちコマンドを叩くのも面倒なので、

使いまわししやすいように設定ファイルを記述しました。

build.js

({
  out : './all.js',
  baseUrl:'./',
  name : 'app-config',
  mainConfigFile: "./app-config.js"
})

app-config.jsと同じディレクトリに配置します

また、オプションは以下の通りです

  • name: 最適化対象のJavaScriptファイル
  • out: 出力先のファイル名
  • baseUrl: JavaScriptファイルを読み込むパス
  • mainConfigFile: app-config.jsのパス

r.jsの実行

build.jsを配置したディレクトリまで移動し以下を実行します。

r.js -o build.js

特に問題がなければ、all.jsという名前で最適化後のjsファイルが出来上がっていると思います。

出来上がったall.jsをwebページで読み込みます.

僕が実際に作っていたwebサイトに適用してみました

- before

f:id:pxp_ss:20131029210555p:plain

- after

f:id:pxp_ss:20131029210551p:plain

require.jsを用いることによって、ページの読み込み速度が改善されているのが分かると思います

参考