使用GruntJS構建Web程序 (1)
Gruntjs是JavaScript項目的構建工具,也是基於node的一個命令行工具。不少開源JS項目都是使用它搭建。如jQuery、Qunit、CanJS等。它有如下做用
- 合併JS文件
- 壓縮JS文件
- 單元測試(基於QUnit)
- 一句話:徹底自動化(automation)
如下是它的安裝過程。
1、安裝node
參考nodejs入門 (最新的node會自動安裝npm)
2、安裝grunt命令行工具grunt-cli
使用-g全局安裝,這樣能夠在任何一個目錄裏使用了。命令: npm install -g grunt-cli
須要注意的是在linux或mac下有時會報沒有權限的錯誤,這時須在前面加一個sudo,
安裝後,能夠查看改工具的版本。命令: grunt -version
3、安裝grunt及其插件
進入到某項目根目錄,使用命令: npm install grunt --save-dev
此時,再查看grunt版本會多了一個4.0,以下
至此,安裝完畢。
使用GruntJS構建Web程序 (2)
前一篇記錄了Grunt的安裝,這篇介紹下怎麼使用Gruntjs來搭建一個前端項目,而後使用grunt合併,壓縮JS文件。
大概有以下步驟
- 新建項目Bejs
- 新建文件package.json
- 新建文件Gruntfile.js
- 命令行執行grunt任務
1、新建項目Bejs
源碼放在src下,該目錄有兩個js文件,selector.js和ajax.js。編譯後代碼放在dest,這個grunt會自動生成。
2、新建package.json
package.json放在根目錄下,它包含了該項目的一些元信息,如項目名稱、描述、版本號,依賴包等。它應該和源碼同樣被提交到svn或git。 如今的項目結構以下
package.json內容需符合JSON語法規範,以下
1
2
3
4
5
6
7
8
9
10
|
{
"name" : "Bejs" ,
"version" : "0.1.0" ,
"devDependencies" : {
"grunt" : "~0.4.0" ,
"grunt-contrib-jshint" : "~0.1.1" ,
"grunt-contrib-uglify" : "~0.1.2" ,
"grunt-contrib-concat" : "~0.1.1"
}
}
|
devDependencies中的grunt在前一篇已經安裝了,grunt-contrib-jshint/grunt-contrib-uglify/grunt-contrib-concat則沒有安裝。三個分別對於三個任務(task)
- grunt-contrib-jshint js語法檢查
- grunt-contrib-uglify 壓縮,採用UglifyJS
- grunt-contrib-concat 合併文件
此時,打開命令行工具進入到項目根目錄,敲以下命令: npm install
再查看根目錄,發現多了個node_modules目錄,包含了四個子目錄,見圖
3、新建文件Gruntfile.js
Gruntfile.js也是放在項目根目錄下,幾乎全部的任務都定義在該文件中,它就是一個普通的js文件,裏面能夠寫任意js代碼而不只侷限於JSON。和package.json同樣它也要和源碼同樣被提交到svn或git。
Gruntfile.js由如下內容組成
- wrapper函數,結構以下,這是Node.js的典型寫法,使用exports公開API
123
module.exports =
function
(grunt) {
// Do grunt-related things in here
};
- 項目和任務配置
- 載入grunt插件和任務
- 定製執行任務
該示例完成如下任務
- 合併src下的文件(ajax.js/selector.js)爲domop.js
- 壓縮domop.js爲domop.min.js
- 這兩個文件都放在dest目錄下
最終的Gruntfile.js以下
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
|
module.exports = function (grunt) {
// 配置
grunt.initConfig({
pkg : grunt.file.readJSON( 'package.json' ),
concat : {
domop : {
src: [ 'src/ajax.js' , 'src/selector.js' ],
dest: 'dest/domop.js'
}
},
uglify : {
options : {
banner : '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
},
build : {
src : 'dest/domop.js' ,
dest : 'dest/domop.min.js'
}
}
});
// 載入concat和uglify插件,分別對於合併和壓縮
grunt.loadNpmTasks( 'grunt-contrib-concat' );
grunt.loadNpmTasks( 'grunt-contrib-uglify' );
// 註冊任務
grunt.registerTask( 'default' , [ 'concat' , 'uglify' ]);
};
|
4、執行grunt任務
打開命令行,進入到項目根目錄,敲 grunt
從打印信息看出成功的合併和壓縮並生成了dest目錄及指望的文件,這時的項目目錄下多了dest,以下
ok,這裏介紹了2個常見任務concat和uglify,jshint等沒有介紹。Gruntfile.js裏的代碼也沒有一一解讀,感興趣的同窗可在gruntjs的官方文檔找到。
以上內容,應該沒有侵犯大嬸們的版權吧,真的sorry,我其實就是個接地氣的屌絲,政治也沒學好,此外,萬分感謝上面這位sandy大神解決了個人問題,還有第一篇文章的那個英雄,感謝上帝,感謝佛祖,感謝cctv,感謝mtv,感謝中國氣象臺...這塊有啥問題,你們一塊兒切切搓搓哈...
原本廢話說完了,發現漏掉一個很重要的,其實spm也罷 grunt也好,我的以爲難點還在配置,最近在重構公司前端的架構,研究這個seajs的東東,上面的那個grunt的確好使,下面把我找到的這個文章也粘貼過來,裏面的配置很全,感受挺重要..
欲練此功,看來不自宮也是能夠的,哈哈....這下沒了,該吃午餐嘍。。走啦
附帶:關於spm的說明,感受挺細的...網上真的很難查 啊啊啊啊啊啊....來者都是客,分享給你們
緊縮JS文件
只需要履行這個號令便可
spm build xxx.js
這時辰你將得到一個緊縮過的__build/xxx.js文件
歸併JS文件
如果將JS文件中require的其餘模塊都歸併到這個文件中,咱們能夠加上--combine參數
別的記得這時辰必須傳遞--app_url參數,用於生成module的id,如
spm build xxx.js --combine --app_url http://x.com
你將與上方同樣得到一個__build/xxx.js文件,然則這個js中require的模塊也都歸併在這個文件中了
歸併JS文件的規矩
通常說來,前端優化時,並不是連接數越少越好,對於通用JS類庫,由於在多個頁面中都邑被引用,零丁加載能夠哄騙到瀏覽器緩存
spm在歸併時,也推敲到了這種景象,是以它遵照如許一個規矩,即只歸併require的「相對標識」的模塊,而不歸併require的「標識」的模塊
對「相對標識」和「標識」不懂得的拜見http://seajs.com/docs/zh-cn/module-identifier.html
爲何是如許一條規矩呢?由於seajs的做者推薦應用如許一條規矩來require模塊:
「推薦應用 require(""xxx"") 這種體式格式引用通用類庫,應用 require(""./xx"") 或 require(""../path/to/yy"") 引用營業模塊」
因此,spm在歸併時,不會歸併通用類庫的模塊,而判定是不是通用類庫的根據就是「相對標識」與「標識」,是以這也請求咱們在書寫代碼時,需要遵照以上的規矩
強迫歸併通用類庫
某些特別景象下,咱們將通用類庫也歸併進來,固然最簡單的辦法就是在代碼中應用「相對標識」來require通用類庫,不過這個辦法其實太蠢
而且spm也有響應的處理懲罰規劃,咱們需要添加--combine_all參數,然則這時辰咱們還必須傳遞--base_path參數,指定通用類庫地點的文件夾,也就是seajs的base路徑
號令參考以下
spm build xxx.js --combine_all --app_url http://x.com --base_path ./lib/
輸出文件路徑
默認景象下,spm會把文件輸出到當前文件同級的__build子文件夾下,在以上幾點的例子裏面已經看到了
spm也支撐用--out_path參數自定義路徑,而且如果有同名文件的話會主動覆蓋,這點在安排時辰作主動化調換頗有效
號令參考以下
spm build xxx.js --combine --app_url http://x.com --out_path .
以上號令會將當前的xxx.js調換爲歸併後的
app_path參數
以上的評論辯論,都是假設JS文件位於「根」下面,也就是說
假設js在文件體系的目次爲D:projectxxx.js,而未來安排後,接見路徑爲http://x.com/xxx.js
那麼進入D:project目次,履行spm build xxx.js --combine --app_url?http://x.com號令,這時辰build出的文件是沒有題目的
下面推敲一下錯雜的景象:
假設js在文件體系中位於D:projectjavascriptxxx.js,而安排後,接見路徑爲http://x.com/javascript/xxx.js
那麼如果咱們進入D:projectjavascript目次,履行上述一樣號令,這時辰build出的文件是有題目的,哪裏有題目呢?打開build出的文件一看就知道了
通常這時辰文件中define的id語句是如許的
define("http://x.com/xxx.js", //省略
明顯這是有題目,咱們指望編譯出的id應當是http://x.com/javascript/xxx.js,假設路徑再深一點,如果存在兩個同名而目次不合的js,就會存在define id反覆了
那麼如何解決呢?我發明spm還供給一個--app_path參數,測驗測驗履行如下號令,將項目標「根」路徑作爲--app_path參數
cd D:project
spm build javascriptxxx.js --combine --app_url http://x.com --app_path D:project --out_path .
這時辰由於out_path爲. 因此xxx.js已經被調換掉了,打開闢明define id正確無誤,是http://x.com/javascript/xxx.js
這是由於當傳遞了--app_path參數時,spm管賬算要歸併的js文件的路徑與這個路徑的相對路徑,舉例來講,就是策畫出D:projectjavascriptxxx.js與D:project的相對路徑,也就是javascriptxxx.js,而後將這個路徑再與--app_url參數鏈接,做爲define的id
重視:然則這裏有個題目,如果不指定--out_path時,spm會失足,由於這時辰--out_path默認爲D:projectjavascript_buildjavascript,而彷佛spm只能新建_build文件夾,對於下級文件夾不會再新建,因此會報錯
應用build-config.js
如果不在敲號令時辰傳那麼多東倒西歪的參數,能夠將這些參數寫在build-config.js裏面,以下
module.exports = {
"base_path": "../", "app_url": "http://x.com", "app_path": "../../" };
當你在某個目次下履行spm build號令時,spm會主動尋找當前目次下有沒有build-config.js文件,如果有則將內容解析爲參數
固然如果你不喜愛這個名字,你還能夠在履行spm號令時,用--config指定build設備文件
loader_config參數
如果你在某個js文件中,應用了seajs.config作了alias的設備,則打包時,需要傳遞--loader_config參數,將文件傳給spm