如今公認的JavaScript典型項目須要運行單元測試,合併壓縮。有些還會使用代碼生成器,代碼樣式檢查或其餘構建工具。javascript
Grunt.js是一個開源工具,能夠幫助你完成上面的全部步驟。它很是容易擴展,並使用JavaScript書寫,因此任何爲JavaScript庫或項目工做的人均可以按本身的須要擴展它。css
本文解釋如何使用Grunt.js構建JavaScript庫。Grunt.js依賴Node.js和npm,因此第一節解釋其是什麼,如何安裝和使用。若是你對npm有了解,那你能夠跳過這一節。第四和第五節講述如何配置Grunt和一系列典型Grunt任務。html
本文討論的代碼例子能夠在GitHub上訪問。前端
開始以前,咱們須要三個工具:html5
Node.js是一個流行的服務器端JavaScript環境。它被用來編寫和運行JavaScript服務和JavaScript命令行工具。若是你想進一步連接Node.js,你能夠查看Stack Overflow上相關的資料。java
Npm是Node.js的包管理工具。它能從中心倉庫下載依賴,解決大部分依賴衝突問題。Npm倉庫僅僅存儲Node.js服務器段和命令行項目。它不包含用於web和移動app相關的庫。咱們用它來下載Grunt.js。node
Grunt.js是一個任務運行工具,咱們用起構建咱們的項目。它在Node.js之上運行而且經過Npm安裝。git
你能夠直接從下載頁面或用其它包管理工具安裝node.js。安裝成功後在命令行輸入 node -v Node.js將輸出它的版本號。github
大部分安裝器和包管理工具將同時安裝Npm。在命令行輸入 npm -v 測試是否安裝成功。若是成功將輸出它的版本號。不一樣的系統可能安裝方式略有不一樣。web
下載和使用安裝腳本。
windows安裝器包含npm並會添加path變量。僅在你下載Node.exe或從源代碼編譯Node是才須要獨立安裝Npm。從這裏下載Npm的最新版zip壓縮包。解壓後賦值到Node.exe的安裝目錄。若是你願意,你也能夠放到任何位置,將其加入path變量便可。
安裝包中內建Npm。
瞭解Npm基礎操做對於使用和安裝Grunt.js都有幫助。這節僅包含接觸知識。更多細節能夠查看npm文檔。
本節將解釋下面的東西:
Npm是一個包管理工具,能夠從中心倉庫下載和安裝JavaScript依賴。安裝包能被用在Node.js項目或命令行工具。
項目一般在package.json文件內部列出其依賴和安裝插件。此外npm庫也能夠從命令行安裝。
每一個包能夠安裝在全局或本地環境。實際的區別是存儲位置和訪問方式。
全局安裝包被直接存儲在Node.js安裝路徑。他們之因此被稱爲全局,是由於他們能夠在任何地方直接訪問。
本地安裝將下載包安裝在當前工做路徑。本地安裝包只能從其所在目錄訪問。
本地安裝包被存儲進node_mudules子目錄。不管你使用什麼版本控制系統,你能夠將其添加僅.ignorefile 文件。
package.json文件包含npm項目描述。它老是位於項目的根目錄,而且包含項目名稱,版本,協議和其餘相似元數據。最重要的是,它包含兩個項目依賴列表。
第一個列表包含運行所須要的依賴。任何但願使用此項目的人必須安裝它們。第二個列表包含開發時須要依賴項。包括測試工具,構建工具和代碼樣式檢測工具。
建立package.json最簡單的方法是經過 npm install 命令。這條命令會以交互式提問一系列問題,並根據回答在當前工做目錄生成基本的package.json文件。只有名字(name)和版本(version)屬性是必須的。若是你不打算將你的庫發佈到Npm,你能忽略其他的部分。
下面的連接包含對package.json的詳細描述:
Npm寶能夠經過npm install 命令安裝。默認安裝到本地。全局安裝須要指定 -g開關。
不帶參數的 npm install 將在當前目錄或上層目錄查找 package.json 文件。若是發現,將會在當前目錄安裝全部列出的依賴項。
能夠經過 npm install <pkg_name@version> 命令安裝具體的npm包。這條命令將從中心倉庫找到指定版本的包,並將其安裝到當前目錄。
版本號是可選的。若是省略將下載最新穩定版。
最後,經過 --sace-dev開關不只能夠安裝包,還會將其添加到 package.json 的開發依賴中。
咱們將首先將Grunt.js添加進咱們的JavaScript項目。爲此咱們須要安裝兩個Grunt.js模塊:
提醒:最新的Grunt.js(4.0)再也不兼容之前的版本。一些老的教程和文檔再也不適合新版Grunt.js了。
全部實際的工做是由任務運行器來作。命令行接口僅解析參數和將其傳遞個任務運行器。若是任務運行器沒有安裝將不會作任何事情。
命令行接口應該被安裝在全局環境,然而任務運行器在本地環境。全局命令行接口保證Grunt命令能夠在全部路徑訪問。任務運行器必須是本地的,由於不一樣的項目可能須要不一樣的Grunt版本。
安裝全局Grunt命令行接口:
npm install -g grunt-cli
切換到項目根目錄,經過npm init讓Npm幫你生成package.json文件。它會問你些問題而後根據你的回答生成合法的package.json文件。只有名字和版本是必須的;你能夠忽略其餘選項。
將Grunt.js最新版添加到本地環境,同時添加到package.json文件的開發依賴裏。
npm install grunt --save-dev
經過前面的命令建立的package.json文件應該相似相面這樣:
{ "name": "gruntdemo", "version": "0.0.0", "description": "Demo project using grunt.js.", "main": "src/gruntdemo.js", "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "repository": "", "author": "Meri", "license": "BSD", "devDependencies": { "grunt": "~0.4.1" } }
Grunt.js運行任務而且經過任務完成工做。然而,Grunt.js安裝成功後尚未任務可使用。任務必須從插件載入,而插件一般須要Npm安裝。
咱們使用五個插件:
本節將解釋如何配置這些插件。咱們從最簡單的配置開始,而後一步步解釋如何配置任務。餘下的子章節將詳細講解如何配置每一個插件。
Grunt將配置信息寫到Gruntfile.js或Gruntfile.coffee文件裏。因爲咱們建立的JavaScript項目,咱們將使用JavaScript版本。最簡單的Gruntfile.js看起來像下面這樣:
//包裝函數 有一個參數 module.exports = function(grunt) { // 默認任務。在本例子中沒有任何操做。 grunt.registerTask('default', []); };
配置信息被保存在module.exports函數內部。它包含grunt對象做爲其參數,而且經過調用該函數完成配置。
配置函數必須建立至少一個任務別名,而且配置他們。例如,上面的代碼片斷建立了一個「default」任務別名而且指定爲空的任務列表。換句話說,默認的任務別名能夠工做,但不會作任何事情。
用 grunt <taskAlias> 命令運行指定的 taskAlias任務。taskAlias的參數是可選的,若是省略,Grunt將使用「default」任務。
保存Gruntfile.js文件,在命令行運行Grunt:
grunt
你應該看到以下輸出:
Done, without errors.
若是配置任務返回錯誤或警告Grunt將發出蜂鳴聲(在命令行下輸入錯誤的聲音,譯者未發現這點)。若是你不想聽到蜂鳴聲,你可使用 -no-color 參數:
grunt -no-color
從插件添加任務是經過用步驟,對全部插件都是相同的。本節將概要講述須要的過程,實際的例子將在下面的章節講解。
首先,咱們須要將插件添加進package.json文件的開發依賴裏面,而且使用Npm進行安裝:
npm install <plugin name> --save-dev
任務配置必須被存儲在一個對象內部,有各自的任務名,而且被傳遞給 grunt.initConfig方法:
module.exports = function(grunt) { grunt.initConfig({ firstTask : { /* ... 配置第一個任務 ... */ }, secondTask : { /* ... 配置第二個任務 ... */ }, // ... 其餘任務 ... lastTask : { /* ... 最後一個任務 ... */ } }); // ... the rest ... };
全面的任務配置信息解釋看這裏Grunt.js文檔。本節僅描述最通用,簡單的例子。假設任務接受一個文件列表,並處理他們,而後生出輸出文件。
一個簡單的任務配置例子:
firstTask: { options: { someOption: value //取決於插件 }, target: { src: ['src/file1.js', 'src/file2.js'], //輸入文件 dest: 'dist/output.js' // 輸出文件 } }
例子中的任務配置有兩個屬性。一個是任務選項,名稱必須是」options「。Grunt.js不會對options的屬性執行任何操做,其行爲有插件決定。
其餘項能夠有任何名字,而且要包含任務目標。最多見的任務是操做和生成文件,因此他們的target有兩個屬性,」src「 和 」dest「。src包含輸入的文件列表,dest包含輸出的文件名字。
若是你配置多個任務,Grunt將依次執行。下面的任務將運行兩次,一次操做src及其子目錄的全部js文件,另外一次操做test及其子目錄下的全部js文件:
multipleTargetsTask: { target1: { src: ['src/**/*.js'] }, target2: { src: ['test/**/*.js']] } }
最後,將插件載入必須使用 grunt.loadNpmTasks 函數,而且註冊任務別名。
上面介紹的結構合起來以下:
module.exports = function(grunt) { grunt.initConfig({ /* ... tasks configuration ... */ }); grunt.loadNpmTasks('grunt-plugin-name'); grunt.registerTask('default', ['firstTask', 'secondTask', ...]); };
JSHint檢查JavaScript代碼中潛在的問題和錯誤。他被設計成可配置的,而且有合理的默認值。
咱們將使用 grunt-contrib-jshint 插件,grunt-contrib開頭的插件都是有Grunt官方維護的,若是你建立本身的插件千萬不要以次開頭。
打開命令行,在項目根目錄運行 npm install grunt-contrib-jshint --save-dev。將會添加插件到package.json文件的開發依賴,而且安裝到本地Npm倉庫。
grunt-contrib-jshint插件的參數和JSHint同樣。完整的參數列表能夠訪問JSHint的文檔頁面。
JSHint 的參數 「eqeqeq」 會將 == 和 != 操做符報告爲警告。默認是關閉的,由於這些操做符是合法的。但我建議你開啓它,由於嚴格相等比非嚴格相等更安全。
同時我建議你開啓trailing選項,將會對代碼中結尾部的空白元素生成警告。結尾的空白在多行字符串中會引發奇怪的問題。
每個可選項都是布爾值,設置爲true將會開啓相應檢測。下面的例子開啓了eqeqeq和trailing選項:
options: { eqeqeq: true, trailing: true }
grunt-contrib-jshint插件的任務名字是「jshint」。咱們將使用上一節中的配置選項,使它檢測位於src和test目錄下的所有JavaScript文件。
JSHint的配置信息必須寫在名爲「jshint」的屬性內部。能夠有兩個屬性,一個數參數(options)另外一個是目標(target)。
目標能夠在任何屬性內部,在這裏咱們僅使用「target」。其必須包含待驗證的JavaScript文件列表。文件列表能夠放在目標的src屬性中,可使用**和*通配符。
有兩個自定義選項,將會驗證位於src和test目錄及其子目錄下的全部js文件。
grunt.initConfig({ jshint: { options: { eqeqeq: true, trailing: true }, target: { src : ['src/**/*.js', 'test/**/*.js'] } } });
最後須要載入和註冊 grunt-contrib-jshint 任務:
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['jshint']);
目前爲止完整的 Gruntfile.js 文件以下:
module.exports = function(grunt) { grunt.initConfig({ jshint: { options: { trailing: true, eqeqeq: true }, target: { src : ['src/**/*.js', 'test/**/*.js'] } } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.registerTask('default', ['jshint']); };
js文件通常是分散的(若是你的項目不是幾十行js的話),上線前咱們必須將其打包進一個文件,並添加版本號和項目名字。在文件的開始位置應該包含庫名稱,版本,協議,構建時間和其餘一些信息。
例如,像下面這樣:
/*! gruntdemo v1.0.2 - 2013-06-04 * License: BSD */ var gruntdemo = function() { ...
咱們將使用 grunt-contrib-concat 插件完成拼接任務,並生成正確的註釋信息。
和前面同樣,將插件寫進package.json文件的開發依賴裏,而後從Npm倉庫安裝到本地。
打開命令行,運行以下命令:
npm install grunt-contrib-concat --save-dev
首先從package.json文件加載配置信息,並存儲在pkg屬性。須要使用 grunt.file.readJSON 函數:
pkg: grunt.file.readJSON('package.json'),
如今pkg的值是一個對象,包含所有package.json的信息。項目名被存儲在pkg.name屬性,版本被存儲在pkg.version。版權被存儲在pkg.license屬性等等。
Grunt提供一套模版系統,咱們可使用它構建頁頭和文件名稱。模版能夠在字符串中嵌入JavaScript表達式,經過<%= expression %> 語法。Grunt計算表達式的值並替換模版中的表達式。
例如,模版中的 <%= pkg.name %> 將被替換爲 pkg.name 的屬性值。若是屬性值是字符串,模版的行爲相似字符串拼接 ...' + pkg.name + '...
模版中能夠引用Grunt中的所有屬性。系統提供了一個很是有幫助的日期格式化函數。咱們將使用 grunt.template.today(format) 函數生成當前的時間戳。
讓咱們生成一個簡單的頁頭,包含項目名稱,版本號,版權和當前的日期。因爲咱們須要在 Uglify 任務中使用banner,因此咱們將其存儲在變量中:
var bannerContent = '/*! <%= pkg.name %> v<%= pkg.version %> - ' +
'<%= grunt.template.today("yyyy-mm-dd") %> \n' +
' * License: <%= pkg.license %> */\n';
上面的模版生成以下的頁頭:
/*! gruntdemo v0.0.1 - 2013-06-04 * License: BSD */
項目的名稱和版本部分也須要在多處使用。將項目名和版本號拼在一塊兒,存儲在一個變量中:
var name = '<%= pkg.name %>-v<%= pkg.version%>';
生成的名字以下:
gruntdemo-v0.0.1
target必須包含須要被拼接的文件列表,和合並完成後輸出文件的名字。target支持通配符和模版,因此咱們使用前一節生成的模版:
target : { // 拼接src目錄下的全部文件 src : ['src/**/*.js'], // place the result into the dist directory, // name variable contains template prepared in // previous section dest : 'distrib/' + name + '.js' }
concat插件也能夠經過banner屬性添加banner。因爲上面咱們已經將banner內容賦給bannerContent變量,因此咱們僅需引入便可:
options: {
banner: bannerContent
}
最後不要忘記從Npm加載 grunt-contrib-concat ,而且將其註冊到默認工做流:
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['jshint', 'concat']);
這一節出示包含完整contat配置的Gruntfile.js文件。
注意pkg屬性在傳遞給initConfig方法的參數中定義。咱們不能把他放在其餘地方,由於它讀取模版信息,而且僅在initConfig方法的參數和grunt對象中有訪問模版的權限。
module.exports = function(grunt) { var bannerContent = '... banner template ...'; var name = '<%= pkg.name %>-v<%= pkg.version%>'; grunt.initConfig({ // pkg is used from templates and therefore // MUST be defined inside initConfig object pkg : grunt.file.readJSON('package.json'), // concat configuration concat: { options: { banner: bannerContent }, target : { src : ['src/**/*.js'], dest : 'distrib/' + name + '.js' } }, jshint: { /* ... jshint configuration ... */ } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.registerTask('default', ['jshint', 'concat']); };
若是瀏覽器載入和解析大文件,會使頁面載入變得緩慢。可能不是全部項目都會遇到這個問題,但對於移動端的app和使用很是多大型庫的大型web應用程序而言,是必需要考慮的。
所以,咱們也將咱們庫進行壓縮。壓縮會將輸入的文件變小,經過去除空白元素,註釋,替換變量名稱等,但不會改變代碼邏輯。
壓縮功能使用 grunt-contrib-uglify 插件,其經過Grunt集成 UglifyJs。它經過uglify任務拼接和壓縮一組文件。
壓縮會使生成的文件難於閱讀和調試,因此咱們經過生成源程序映射來簡化問題。
源程序映射是壓縮文件和源文件之間的紐帶。若是瀏覽器支持,瀏覽器調試工具會顯示對人友好的源文件,而不是壓縮文件。僅有chrome和nightly版本的 firefox支持源代碼映射。你能夠在HTML5 rocks 和 Tutsplus 上獲取更多信息,我建議你看看阮一峯老師的這篇文章:http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html
將插件添加到package.json的開發依賴裏,而且安裝到本地Npm倉庫。
使用以下命令:
npm install grunt-contrib-uglify --save-dev
配置uglify任務目標的方式和concat任務相似。必需要包含待壓縮的javascript文件列表和輸出文件的名字。
支持通配符和模版,因此咱們可使用前面章節中的用到的模版:
target : { // use all files in src directory src : ['src/**/*.js'], // place the result into the dist directory, // name variable contains template prepared in // previous sub-chapter dest : 'distrib/' + name + '.min.js' }
配置banner的方式和concat同樣——經過設置「banner」屬性而且支持模版。所以,咱們能夠重複使用前面章節中準備好的 bannerContent 變量。
經過「sourceMap」屬性生成源文件映射。包含生成文件的名字。此外,必須設置「sourceMapUrl」和「sourceMapRoot」屬性。前一個包含相對於uglified文件到源文件映射文件的路徑,後一個包含是源文件映射到源文件的相對路徑。
經過bannerContent變量生成頁眉,經過name變量生成源文件映射文件的名字:
options: { banner: bannerContent, sourceMapRoot: '../', sourceMap: 'distrib/'+name+'.min.js.map', sourceMapUrl: name+'.min.js.map' }
最後一步是從Npm加載 grunt-contrib-uglify,而且添加到默認任務列表:
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['jshint', 'concat', 'uglify']);
下面是包含完整uglify配置信息的Gruntfile.js文件:
module.exports = function(grunt) { var bannerContent = '... banner template ...'; var name = '<%= pkg.name %>-v<%= pkg.version%>'; grunt.initConfig({ // pkg must be defined inside initConfig object pkg : grunt.file.readJSON('package.json'), // uglify configuration uglify: { options: { banner: bannerContent, sourceMapRoot: '../', sourceMap: 'distrib/'+name+'.min.js.map', sourceMapUrl: name+'.min.js.map' }, target : { src : ['src/**/*.js'], dest : 'distrib/' + name + '.min.js' } }, concat: { /* ... concat configuration ... */ }, jshint: { /* ... jshint configuration ... */ } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.registerTask('default', ['jshint', 'concat', 'uglify']); };
最後要發佈的庫包括兩個文件,而且都在名字中含有版本號。這會給想要自動下載每一個新版本的人形成沒必要要的困難。
若是想要查看是否發佈了新版本和新版本的名字,必須每次都要獲取和解析一個json文件。若是每次都更更名稱,則必須更新下載腳本。
所以咱們將使用 grunt-contrib-copy 插件建立無版本號的文件。
將插件添加進package.json的開發依賴,而且從Npm倉庫安裝到本地。
使用以下命令:
npm install grunt-contrib-copy --save-dev
copy配置信息包括三個目標,分別對應三個發佈文件。沒有配置選項,基本和前一個插件配置過程同樣。
僅有一點不同,就是多任務。每一個任務包含一對 src/dest,待拷貝的名字和待建立的名字。
對前面的任務配置選項稍加修改。將全部文件名字放到變量中,以即可以重複使用:
module.exports = function(grunt) { /* define filenames */ latest = '<%= pkg.name %>'; name = '<%= pkg.name %>-v<%= pkg.version%>'; devRelease = 'distrib/'+name+'.js'; minRelease = 'distrib/'+name+'.min.js'; sourceMapMin = 'distrib/source-map-'+name+'.min.js'; lDevRelease = 'distrib/'+latest+'.js'; lMinRelease = 'distrib/'+latest+'.min.js'; lSourceMapMin = 'distrib/source-map-'+latest+'.min.js'; grunt.initConfig({ copy: { development: { // copy non-minified release file src: devRelease, dest: lDevRelease }, minified: { // copy minified release file src: minRelease, dest: lMinRelease }, smMinified: { // source map of minified release file src: sourceMapMin, dest: lSourceMapMin } }, uglify: { /* ... uglify configuration ... */ }, concat: { /* ... concat configuration ... */ }, jshint: { /* ... jshint configuration ... */ } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'copy']);
最後,配置 grunt.js 運行單元測試,測試最新發布的文件。咱們將使用 grunt-contrib-qunit 插件實現目標。這個插件將在無頭的 PhantomJS 實例中運行 QUnit 單元測試。
這個解決方案不能模擬不一樣瀏覽器和查找所有 bug,但對於咱們來講已經足夠了。若是想獲得更好的配置,可使用 js-test-driver 或 其餘相似工具,然而,關於 js-test-dirver 的配置超出了本文的範圍。
Qunit 單元測試常常要運行 src 目錄裏的 JavaScript 文件,因爲測試是開發的一部分。若是你想測試剛剛發佈的拼接壓縮後的版本工做情況,須要建立一個新的 QUnit HTML 文件,並加載最後發佈的文件。
下面是一個例子是 Qunit 的入口文件:
<!DOCTYPE html> <html> <head> <meta charset="utf-8"> <title>QUnit Example</title> <link rel="stylesheet" href="../libs/qunit/qunit.css"> </head> <body> <div id="qunit"></div> <div id="qunit-fixture"></div> <script src="../libs/qunit/qunit.js"></script> <!-- Use latest versionless copy of current release --> <script src="../distrib/gruntdemo.min.js"></script> <script src="tests.js"></script> </body> </html>
將插件添加進package.json 的開發者依賴中,而且將其安裝到本地 Npm 倉庫。
使用以下命令:
npm install grunt-contrib-qunit --save-dev
配置 grunt-contrib-qunit 插件和配置前面的任務一模一樣。因爲咱們使用默認的 Qunit 配置,因此能夠省略選項屬性。不能忽略的是必須配置 target,指定所有的 Qunit HTML 文件。
接下來指定位於測試目錄下的所有 HTML 文件,及其子目錄應該運行 Qunit 測試:
grunt.initConfig({ qunit:{ target: { src: ['test/**/*.html'] } }, // ... all previous tasks ... });
下面是完整的 Gruntfile.js 配置信息:
module.exports = function(grunt) { var name, latest, bannerContent, devRelease, minRelease, sourceMap, sourceMapUrl, lDevRelease, lMinRelease, lSourceMapMin; latest = '<%= pkg.name %>'; name = '<%= pkg.name %>-v<%= pkg.version%>'; bannerContent = '/*! <%= pkg.name %> v<%= pkg.version %> - ' + '<%= grunt.template.today("yyyy-mm-dd") %> \n' + ' * License: <%= pkg.license %> */\n'; devRelease = 'distrib/'+name+'.js'; minRelease = 'distrib/'+name+'.min.js'; sourceMapMin = 'distrib/'+name+'.min.js.map'; sourceMapUrl = name+'.min.js.map'; lDevRelease = 'distrib/'+latest+'.js'; lMinRelease = 'distrib/'+latest+'.min.js'; lSourceMapMin = 'distrib/'+latest+'.min.js.map'; grunt.initConfig({ pkg: grunt.file.readJSON('package.json'), qunit:{ target: { src: ['test/**/*.html'] } }, // configure copy task copy: { development: { src: devRelease, dest: lDevRelease }, minified: { src: minRelease, dest: lMinRelease }, smMinified: { src: sourceMapMin, dest: lSourceMapMin } }, // configure uglify task uglify:{ options: { banner: bannerContent, sourceMapRoot: '../', sourceMap: sourceMapMin, sourceMappingURL: sourceMapUrl }, target: { src: ['src/**/*.js'], dest: minRelease } }, // configure concat task concat: { options: { banner: bannerContent }, target: { src: ['src/**/*.js'], dest: devRelease } }, // configure jshint task jshint: { options: { trailing: true, eqeqeq: true }, target: { src: ['src/**/*.js', 'test/**/*.js'] } } }); grunt.loadNpmTasks('grunt-contrib-jshint'); grunt.loadNpmTasks('grunt-contrib-concat'); grunt.loadNpmTasks('grunt-contrib-uglify'); grunt.loadNpmTasks('grunt-contrib-copy'); grunt.loadNpmTasks('grunt-contrib-qunit'); grunt.registerTask('default', ['jshint', 'concat', 'uglify', 'copy', 'qunit']); };
如今 Grunt.js 配置好了,而且可使用了。咱們的目標是使配置儘量簡單,使用成對的 src/dest,通配符和模版。固然,Grunt.js 也提供其餘更高級的選項。
若是可以自動下載和管理項目依賴的庫,會變得更美好。我發現兩個可行的解決方案,Bower 和 Ender。我沒有試過他們,但均可以管理前端JavaScript包和其依賴。
文章有些長,拖了好久的文章終於翻譯完成了,我最近打算寫一本關於 Grunt 指南的書籍,會詳細講解如何構建一套前端自動化工具,若是你支持個人工做,那就給我捐助吧。
原文:http://flippinawesome.org/2013/07/01/building-a-javascript-library-with-grunt-js/