2015/10/13

r.js

用了一陣子 requirejs,之前都使用一些奇淫巧技讓每個頁面可以依照相依性導入各自頁面的 javascript,但其實這只達到了 requirejs 的非同步載入而已,檔案一多病沒有減少 request,requirejs 最強大的功能應該是他的 r.js 功能,他可以把相依性依照你設定的方式載入,並且合併成一個檔案,今天來示範一下我現在的布局。

目錄結構

- js/
 - build/
 - jquery/
 - src/
 - tool/

將所有的 javascript 檔案放在 js 目錄下,使用了四個目錄:

  • build/ (compiler 過後的檔案)
  • jquery/ (jQuery 相關檔案)
  • src/ (compiler 前的檔案)
  • tool/ (一些共用的工具檔案)

今天要示範我們要在 index.html 引入 index.js,index.js 要包含 jqueryjquery.formtools/func.js,並且依照相依性載入,首先我們建立 js/build.js

js/build.js
({
    baseUrl: './',
    paths: {
        'jquery': 'jquery/jquery.min',
        'form': 'jquery/jquery.form'
    },
    shim: {
        'form': ['jquery'],
        'src/index': ['form']
    },
    waitSeconds: 20
})

build.js 就是所有要 compiler 檔案的預設檔案,可以設定路徑、相依性等相關規範,我在這邊會將所有跟 jquery 相關的 plugin 都 depends on jquery,這樣當我各個 js 隨便調用任一個 jquery 的 plugin 時就會預載 jquery,接下來我們建立 src/index.js

src/index.js
requirejs(['tool/func'], function(func) {
    $(function() {
        func.init();
    });
});

我把 plugin 的調用寫在 build.js 裡面,工具的調用寫在各自的 js 裡面,這樣彈性變很大。

tool/func.js
define(function() {
    return {
        init: function() {
            console.log('func');
        }
    }
});

func.js 放個簡單的 funtion 讓 index.js 測試調用,接下來我們執行 r.js

$ r.js -o build.js name=src/index out=build/index.js

Tracing dependencies for: src/index
Uglifying file: D:/req/js/build/index.js

D:/req/js/build/index.js
----------------
D:/req/js/jquery/jquery.min.js
D:/req/js/jquery/jquery.form.js
D:/req/js/tool/func.js
D:/req/js/src/index.js

r.js 透過 build.js 執行了 src/index compiler 到 build/index.js,並且是依照我要的 order,接下來將結果放到 index.html 裡面。

index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>r.js</title>
    <script data-main="js/build/index" src="js/require.js"></script>
</head>
<body>

</body>
</html>

執行網頁後在 console 得到 func 的 output,如果東西在開發階段,可以加一個參數讓 compiler 的檔案不作最佳化, $ r.js -o build.js name=src/index out=build/index.js optimize=none,這樣就可以方便除錯了。

假設我們今天編譯了一個公用的工具,一旦你有修改到那隻工具,就要面臨每個檔案都必須重新編譯的問題,我們可以另外設一個 config 檔案來做群組的編譯。

builds.js
({
    paths: {
        'jquery': '../jquery/jquery.min',
        'form': '../jquery/jquery.form',
        'init': '../tool/func.js',
    },
    shim: {
        'form': ['jquery'],
        'src/index': ['form']
    },
    baseUrl: './',
    appDir: 'src/',
    dir: 'build/',
    waitSeconds: 20,
    modules: [
        {name: 'index'},
        {name: 'other'}
    ]
})

設定完畢後執行 r.js -o builds.js,就會將 modules 裡面的內容全部重新跑一遍。

沒有留言: