文章出處

這里只是調侃一下,“杏仁”其實指的是almond,requirejs作者的另一個開源項目,它的定位是作為requirejs的一個替代品。

本文概要

1. 使用場景
2. 打包例子:未使用almond
3. 打包例子:使用almond
4. 如何暴露公共API
5. 限制 & 支持的特性
6. 寫在后面 & demo下載

 

使用場景

什么情況下需要使用almond呢?假設你手頭有個基于requirejs的小項目,所有業務代碼加起來就幾十K(壓縮后可能更小).出于性能優化的考慮,你可能在想:如果能夠去掉requirejs的依賴就好了,畢竟,gzip后的requirejs還有大概20k(2.1.6版本)。

almond就是為了這個目的而誕生的,開發過程,你可以照常使用requirejs來管理你的依賴,而到了打包上線階段,替換成almond就行了。gzip后的almond只有大約1k,優化幅度相當大。

例子:未使用almond

這一小節主要舉個requirejs+r.js打包的例子,下一小杰會在本小節的基礎上,通過almond進行進一步的優化。代碼很簡單,掃一下就可以了
目錄結構如下:

demo.html
build.js
js/
js/main.js
js/cookie.js
js/util.js

demo.html

<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>demo</title>
</head>
<body>
<h1>簡單的requirejs例子 - almond</h1>
<script type="text/javascript" src="js/require.js" data-main="js/main-built.js"></script>
<!-- <script type="text/javascript" src="js/main-almond-built.js"></script> -->
</body>
</html>

js/main.js

requirejs.config({
    baseUrl: 'js'
});
require(['cookie', 'util'], function(Cookie, Util){
    Cookie.say('hello');
    Util.say('hello');
});

js/cookie.js

define([], function(){
    return {
        say: function(msg){
            alert('cookie: '+msg);
        }
    };
});

js/util.js

define([], function(){
    return {
        say: function(msg){
            alert('util: '+msg);
        }
    };
});

用r.js打包

首先,在build.js里聲明打包的配置

({
    baseUrl: "js",
    name: "main",
    optimize: "none",
    out: "js/main-built.js"
})

然后,下載打包工具r.js

npm install -g requirejs

最后,通過r.js打包

r.js -o build.js

恭喜!可以看到js目錄下生成了打包后的文件main-built.js

js/main-built.js


define('cookie',[], function(){
    return {
        say: function(msg){
            alert('cookie: '+msg);
        }
    };
});
define('util',[], function(){
    return {
        say: function(msg){
            alert('util: '+msg);
        }
    };
});
requirejs.config({
    baseUrl: 'js'
});
require(['cookie', 'util'], function(Cookie, Util){
    Cookie.say('hello');
    Util.say('hello');
});

define("main", function(){});

運行demo

為了檢驗打包后的結果是運行的,我們需要到瀏覽器里驗證一下。首先我們要把demo.html里的資源引用修改下

<script type="text/javascript" src="js/require.js" data-main="js/main-built.js"></script>

在瀏覽器里打開demo.html,看到下面的彈窗,搞定

Alt text

例子:使用了almond

我們看到,上面的例子打包后生成了main-built.js,gzip后看下文件多大

gzip main-built.js

可以看到只有174B,這種情況下,在頁面中引用requirejs有點不劃算,這個時候我們就要引入almond了

-rw-r--r-- 1 user staff 174B 4 20 22:03 main-built.js.gz

很簡單,首先下載almond,并放置到js目錄下

然后,運行下面命令,通過r.js + almond生成打包后的文件main-almond-built.js

r.js -o baseUrl=js name=almond include=main out=js/main-almond-built.js wrap=true optimize=none

js/main-almond-built.js

/**
 * @license almond 0.2.9 Copyright (c) 2011-2014, The Dojo Foundation All Rights Reserved.
 * Available via the MIT or new BSD license.
 * see: http://github.com/jrburke/almond for details
 */
// almond的代碼篇幅略長,這里略過...

define("cookie",[],function(){return{say:function(e){alert("cookie: "+e)}}}),define("util",[],function(){return{say:function(e){alert("util: "+e)}}}),requirejs.config({baseUrl:"js"}),require(["cookie","util"],function(e,t){e.say("hello"),t.say("hello")}),define("main",function(){});

同樣,在修改修改main.js的鏈接后,在瀏覽器里訪問demo.html,done!

<script type="text/javascript" src="js/main-almond-built.js"></script>

Alt text

看下gzip后的main-almond-built.js多大,只有1.6k!

-rw-r--r--  1 user  staff   1.6K  4 20 22:34 main-almond-built.js.gz

通過配置文件打包

上面打包的命令行有點長,對于樓主這樣對命令行有恐懼癥的人來說,還是比較習慣寫個配置文件,命令行則越簡短越好

build-almond.js

({
    baseUrl: "js",
    name: "almond",
    include: "main",
    out: "js/main-almond-built.js",
    wrap: true
})

接下來就很簡單了,很短的一行命令

r.js -o build-almond.js

暴露公共API

上面的例子,如果沒有加上wrap: true這個選項,打包后生成的文件,你是可以訪問到之前的定義的模塊的,比截圖所

Alt text

但加上wrap: true后就完全不一樣了,因為所有的代碼都會被包在一個匿名的閉包里,大致如下

(function () {
    //almond will be here
    //main and its nested dependencies will be here
}());

此時就訪問不到之前定義的模塊了,包括require都成了匿名函數里的一個局部變量
Alt text

這種情況下,如果我們想要訪問模塊里的方法,該怎么做呢?可以修改下配置文件

build-almond-frag.js

({
    baseUrl: "js",
    name: "almond",
    include: "main",
    out: 'js/main-built-almond-public.js',
    wrap: {
        startFile: 'js/start.frag.js',
        endFile: 'js/end.frag.js'
    }
})

js/start.frag.js

(function (root, factory) {
    if (typeof define === 'function' && define.amd) {
        define([], factory);
    } else {
        root.Main = factory();
    }
}(this, function () {
    //almond, and your modules will be inlined here

js/end.frag.js

    return {
        cookie: require('cookie'),
        util: require('util')
    };
}));

打包

r.js -o build-almond-frag.js

生成的文件結構如下

start.frag
almond.js
modules for your lib, including 'main'
end.frag

現在,可以在瀏覽器里繼訪問我們暴露的API了
Alt text

一些限制 & 支持的特性

毫無意外,almond只是支持了requirejs功能的子集,所以,在使用前需要了解下它的支持哪些特性,有哪些限制。

限制:

  • 需要將所有的模塊打包成一個文件
  • 不支持模塊動態加載
  • 只能調用一次requirejs.config()(原來可以調用兩次??)
  • 不能通過var require = {};傳遞配置參數
  • 不支持多版本/上下文
  • 不要使用require.toUrl()require.nameToUrl()
  • (不了解packages,直接附上原文了)

    do not use packages/packagePaths config. If you need to use packages that have a main property, volo can create an adapter module so that it can work without this config. Use the amdify add command to add the dependency to your project.

支持的特性

  • 使用相對路徑的依賴(dependencies with relative IDs.)
  • define('id', {}) definitions.(不知道腫么翻譯)
  • define(), require() and requirejs() 調用。
  • 符合這樣特性的插件:能夠將資源內聯進打包優化后的文件,并通過同步的方式訪問內聯后的資源。比如text插件CoffeeScript插件

寫在后面

本文簡單介紹了下如何通過almond對依賴requirejs的項目進行進一步的優化。當然,almond也存在著一些限制,比如無法動態加載模塊、只能將模塊打包成一個文件等,具體的可以參考這里。是否在打包階段使用almond替代requirejs,得看具體場景,這里就不展開,后面有時間再簡單介紹下。

demo下載


文章列表


不含病毒。www.avast.com
arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()