基於Grunt構建一個JavaScript庫
現在公認的JavaScript典型專案需要執行單元測試,合併壓縮。有些還會使用程式碼生成器,程式碼樣式檢查或其他構建工具。
Grunt.js是一個開源工具,可以幫助你完成上面的所有步驟。它非常容易擴充套件,並使用JavaScript書寫,所以任何為JavaScript庫或專案工作的人都可以按自己的需要擴充套件它。
本文解釋如何使用Grunt.js構建JavaScript庫。Grunt.js依賴Node.js和npm,所以第一節解釋其是什麼,如何安裝和使用。如果你對npm有了解,那你可以跳過這一節。第四和第五節講述如何配置Grunt和一系列典型Grunt任務。
本文討論的程式碼例子可以在GitHub上訪問。
工具概述(Tool Chain Overview)
開始之前,我們需要三個工具:
Node.js是一個流行的伺服器端JavaScript環境。它被用來編寫和執行JavaScript服務和JavaScript命令列工具。如果你想進一步連結Node.js,你可以檢視Stack Overflow上相關的資料。
Npm是Node.js的包管理工具。它能從中心倉庫下載依賴,解決大部分依賴衝突問題。Npm倉庫僅僅儲存Node.js伺服器段和命令列專案。它不包含用於web和移動app相關的庫。我們用它來下載Grunt.js。
Grunt.js是一個任務執行工具,我們用起構建我們的專案。它在Node.js之上執行並且通過Npm安裝。
安裝Node.js和Npm(Node.js and Npm Installation)
你可以直接從下載頁面或用其它包管理工具安裝node.js。安裝成功後在命令列輸入 node -v Node.js將輸出它的版本號。
大部分安裝器和包管理工具將同時安裝Npm。在命令列輸入 npm -v 測試是否安裝成功。如果成功將輸出它的版本號。不同的系統可能安裝方式略有不同。
Linux
下載和使用安裝指令碼。
Windows
windows安裝器包含npm並會新增path變數。僅在你下載Node.exe或從原始碼編譯Node是才需要獨立安裝Npm。從這裡下載Npm的最新版zip壓縮包。解壓後賦值到Node.exe的安裝目錄。如果你願意,你也可以放到任何位置,將其加入path變數即可。
OSX
安裝包中內建Npm。
Npm基礎(Npm Basics)
瞭解Npm基礎操作對於使用和安裝Grunt.js都有幫助。這節僅包含接觸知識。更多細節可以檢視npm文件。
本節將解釋下面的東西:
- 什麼是npm;
- npm外掛本地安裝和全域性安裝的區別;
- package.json檔案和其規範;
- npm安裝命令。
概要(Overview)
Npm是一個包管理工具,可以從中心倉庫下載和安裝JavaScript依賴。安裝包能被用在Node.js專案或命令列工具。
專案通常在package.json檔案內部列出其依賴和安裝外掛。此外npm庫也可以從命令列安裝。
全域性安裝vs本地安裝(Global vs Local Installation)
每個包可以安裝在全域性或本地環境。實際的區別是儲存位置和訪問方式。
全域性安裝包被直接儲存在Node.js安裝路徑。他們之所以被稱為全域性,是因為他們可以在任何地方直接訪問。
本地安裝將下載包安裝在當前工作路徑。本地安裝包只能從其所在目錄訪問。
本地安裝包被儲存進node_mudules子目錄。無論你使用什麼版本控制系統,你可以將其新增僅.ignorefile 檔案。
Package.json
package.json檔案包含npm專案描述。它總是位於專案的根目錄,並且包含專案名稱,版本,協議和其他類似後設資料。最重要的是,它包含兩個專案依賴列表。
第一個列表包含執行所需要的依賴。任何希望使用此專案的人必須安裝它們。第二個列表包含開發時需要依賴項。包括測試工具,構建工具和程式碼樣式檢測工具。
建立package.json最簡單的方法是通過 npm install 命令。這條命令會以互動式提問一系列問題,並根據回答在當前工作目錄生成基本的package.json檔案。只有名字(name)和版本(version)屬性是必須的。如果你不打算將你的庫釋出到Npm,你能忽略其餘的部分。
下面的連結包含對package.json的詳細描述:
安裝命令(The Install Command)
Npm寶可以通過npm install 命令安裝。預設安裝到本地。全域性安裝需要指定 -g開關。
不帶引數的 npm install 將在當前目錄或上層目錄查詢 package.json 檔案。如果發現,將會在當前目錄安裝所有列出的依賴項。
可以通過 npm install <pkg_name@version> 命令安裝具體的npm包。這條命令將從中心倉庫找到指定版本的包,並將其安裝到當前目錄。
版本號是可選的。如果省略將下載最新穩定版。
最後,通過 --sace-dev開關不僅可以安裝包,還會將其新增到 package.json 的開發依賴中。
為專案新增Grunt.js(Adding Grunt.js to the Project)
我們將首先將Grunt.js新增進我們的JavaScript專案。為此我們需要安裝兩個Grunt.js模組:
- grunt-cli - 命令列介面 (CLI);
- grunt - 任務執行器.
提醒:最新的Grunt.js(4.0)不再相容以前的版本。一些老的教程和文件不再適合新版Grunt.js了。
概論(Overview)
所有實際的工作是由任務執行器來做。命令列介面僅解析引數和將其傳遞個任務執行器。如果任務執行器沒有安裝將不會做任何事情。
命令列介面應該被安裝在全域性環境,然而任務執行器在本地環境。全域性命令列介面保證Grunt命令可以在所有路徑訪問。任務執行器必須是本地的,因為不同的專案可能需要不同的Grunt版本。
安裝(Installation)
安裝全域性Grunt命令列介面:
npm install -g grunt-cli
切換到專案根目錄,通過npm init讓Npm幫你生成package.json檔案。它會問你些問題然後根據你的回答生成合法的package.json檔案。只有名字和版本是必須的;你可以忽略其他選項。
將Grunt.js最新版新增到本地環境,同時新增到package.json檔案的開發依賴裡。
npm install grunt --save-dev
Package.json
通過前面的命令建立的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(Configure Grunt.js)
Grunt.js執行任務並且通過任務完成工作。然而,Grunt.js安裝成功後還沒有任務可以使用。任務必須從外掛載入,而外掛通常需要Npm安裝。
我們使用五個外掛:
- grunt-contrib-concat - 拼接檔案,
- grunt-contrib-uglify - 拼接並壓縮檔案(js),
- grunt-contrib-copy - 複製檔案,
- grunt-contrib-qunit - 執行單元測試,
- grunt-contrib-jshint - 檢查bug和JavaScript程式碼風格.
本節將解釋如何配置這些外掛。我們從最簡單的配置開始,然後一步步解釋如何配置任務。餘下的子章節將詳細講解如何配置每個外掛。
基礎-不做任何配置(Basic Do Nothing Configuration)
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
Grunt Npm 任務(Grunt Npm Tasks)
從外掛新增任務是通過用步驟,對所有外掛都是相同的。本節將概要講述需要的過程,實際的例子將在下面的章節講解。
安裝外掛(Install the Plugin)
首先,我們需要將外掛新增進package.json檔案的開發依賴裡面,並且使用Npm進行安裝:
npm install <plugin name> --save-dev
配置任務(Configure Tasks)
任務配置必須被儲存在一個物件內部,有各自的任務名,並且被傳遞給 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']] }
}
載入和註冊任務(Load and Register Tasks)
最後,將外掛載入必須使用 grunt.loadNpmTasks 函式,並且註冊任務別名。
上面介紹的結構合起來如下:
module.exports = function(grunt) {
grunt.initConfig({ /* ... tasks configuration ... */ });
grunt.loadNpmTasks('grunt-plugin-name');
grunt.registerTask('default', ['firstTask', 'secondTask', ...]);
};
配置JSHint(Configure JSHint)
JSHint檢查JavaScript程式碼中潛在的問題和錯誤。他被設計成可配置的,並且有合理的預設值。
我們將使用 grunt-contrib-jshint 外掛,grunt-contrib開頭的外掛都是有Grunt官方維護的,如果你建立自己的外掛千萬不要以次開頭。
安裝外掛(Install the Plugin)
開啟命令列,在專案根目錄執行 npm install grunt-contrib-jshint --save-dev。將會新增外掛到package.json檔案的開發依賴,並且安裝到本地Npm倉庫。
JSHint引數(JSHint Options)
grunt-contrib-jshint外掛的引數和JSHint一樣。完整的引數列表可以訪問JSHint的文件頁面。
JSHint 的引數 “eqeqeq” 會將 == 和 != 操作符報告為警告。預設是關閉的,因為這些操作符是合法的。但我建議你開啟它,因為嚴格相等比非嚴格相等更安全。
同時我建議你開啟trailing選項,將會對程式碼中結尾部的空白元素生成警告。結尾的空白在多行字串中會引起奇怪的問題。
每一個可選項都是布林值,設定為true將會開啟相應檢測。下面的例子開啟了eqeqeq和trailing選項:
options: {
eqeqeq: true,
trailing: true
}
配置JSHint任務(Configure the JSHint Task)
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']
}
}
});
載入和註冊(Load and Register)
最後需要載入和註冊 grunt-contrib-jshint 任務:
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.registerTask('default', ['jshint']);
全部JSHint配置選項(Full JSHint Configuration)
目前為止完整的 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']);
};
拼接檔案(Concatenate Files)
js檔案一般是分散的(如果你的專案不是幾十行js的話),上線前我們必須將其打包進一個檔案,並新增版本號和專案名字。在檔案的開始位置應該包含庫名稱,版本,協議,構建時間和其他一些資訊。
例如,像下面這樣:
/*! gruntdemo v1.0.2 - 2013-06-04
* License: BSD */
var gruntdemo = function() {
...
我們將使用 grunt-contrib-concat 外掛完成拼接任務,並生成正確的註釋資訊。
安裝外掛(Install the Plugin)
和前面一樣,將外掛寫進package.json檔案的開發依賴裡,然後從Npm倉庫安裝到本地。
開啟命令列,執行如下命令:
npm install grunt-contrib-concat --save-dev
載入Package.json(Load Package.json)
首先從package.json檔案載入配置資訊,並儲存在pkg屬性。需要使用 grunt.file.readJSON 函式:
pkg: grunt.file.readJSON('package.json'),
現在pkg的值是一個物件,包含全部package.json的資訊。專案名被儲存在pkg.name屬性,版本被儲存在pkg.version。版權被儲存在pkg.license屬性等等。
生成頁頭資訊和 檔名(Compose Banner and File Name)
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
配置目標和選項(Configure Target and Options)
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
}
載入和註冊(Load and Register)
最後不要忘記從Npm載入 grunt-contrib-concat ,並且將其註冊到預設工作流:
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.registerTask('default', ['jshint', 'concat']);
完整的拼接配置(Full Concat Configuration)
這一節出示包含完整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']);
};
壓縮(Minify)
如果瀏覽器載入和解析大檔案,會使頁面載入變得緩慢。可能不是所有專案都會遇到這個問題,但對於移動端的app和使用非常多大型庫的大型web應用程式而言,是必須要考慮的。
因此,我們也將我們庫進行壓縮。壓縮會將輸入的檔案變小,通過去除空白元素,註釋,替換變數名稱等,但不會改變程式碼邏輯。
壓縮功能使用 grunt-contrib-uglify 外掛,其通過Grunt整合 UglifyJs。它通過uglify任務拼接和壓縮一組檔案。
源程式對映(Source Maps)
壓縮會使生成的檔案難於閱讀和除錯,所以我們通過生成源程式對映來簡化問題。
源程式對映是壓縮檔案和原始檔之間的紐帶。如果瀏覽器支援,瀏覽器除錯工具會顯示對人友好的原始檔,而不是壓縮檔案。僅有chrome和nightly版本的 firefox支援原始碼對映。你可以在HTML5 rocks 和 Tutsplus 上獲取更多資訊,我建議你看看阮一峰老師的這篇文章:http://www.ruanyifeng.com/blog/2013/01/javascript_source_map.html
安裝外掛(Install the Plugin)
將外掛新增到package.json的開發依賴裡,並且安裝到本地Npm倉庫。
使用如下命令:
npm install grunt-contrib-uglify --save-dev
配置目標(Configure Target)
配置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'
}
配置選項(Configure Options)
配置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'
}
載入和註冊(Load and Register)
最後一步是從Npm載入 grunt-contrib-uglify,並且新增到預設任務列表:
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.registerTask('default', ['jshint', 'concat', 'uglify']);
全部 Uglify 配置資訊(Full Uglify Configuration)
下面是包含完整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']);
};
最後的釋出檔案(Latest Release File)
最後要釋出的庫包括兩個檔案,並且都在名字中含有版本號。這會給想要自動下載每個新版本的人造成不必要的困難。
如果想要檢視是否釋出了新版本和新版本的名字,必須每次都要獲取和解析一個json檔案。如果每次都更改名稱,則必須更新下載指令碼。
因此我們將使用 grunt-contrib-copy 外掛建立無版本號的檔案。
安裝外掛(Install the Plugin)
將外掛新增進package.json的開發依賴,並且從Npm倉庫安裝到本地。
使用如下命令:
npm install grunt-contrib-copy --save-dev
配置外掛(Configure the Plugin)
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']);
單元測試(Unit Tests)
最後,配置 grunt.js 執行單元測試,測試最新發布的檔案。我們將使用 grunt-contrib-qunit 外掛實現目標。這個外掛將在無頭的 PhantomJS 例項中執行 QUnit 單元測試。
這個解決方案不能模擬不同瀏覽器和查詢全部 bug,但對於我們來說已經足夠了。如果想得到更好的配置,可以使用 js-test-driver 或 其他類似工具,然而,關於 js-test-dirver 的配置超出了本文的範圍。
準備測試用例(Prepare Tests)
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>
安裝外掛(Install the Plugin)
將外掛新增進package.json 的開發者依賴中,並且將其安裝到本地 Npm 倉庫。
使用如下命令:
npm install grunt-contrib-qunit --save-dev
配置外掛(Configure Plugin)
配置 grunt-contrib-qunit 外掛和配置前面的任務如出一轍。由於我們使用預設的 Qunit 配置,所以可以省略選項屬性。不能忽略的是必須配置 target,指定全部的 Qunit HTML 檔案。
接下來指定位於測試目錄下的全部 HTML 檔案,及其子目錄應該執行 Qunit 測試:
grunt.initConfig({
qunit:{
target: {
src: ['test/**/*.html']
}
},
// ... all previous tasks ...
});
完整的 Grunt.js 檔案(Final Grunt.js File)
下面是完整的 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']);
};
結論(Conclusion)
現在 Grunt.js 配置好了,並且可以使用了。我們的目標是使配置儘可能簡單,使用成對的 src/dest,萬用字元和模版。當然,Grunt.js 也提供其他更高階的選項。
如果能夠自動下載和管理專案依賴的庫,會變得更美好。我發現兩個可行的解決方案,Bower 和 Ender。我沒有試過他們,但都可以管理前端JavaScript包和其依賴。
注
文章有些長,拖了很久的文章終於翻譯完成了,我最近打算寫一本關於 Grunt 指南的書籍,會詳細講解如何構建一套前端自動化工具,如果你支援我的工作,那就給我捐助吧。
- 原文:http://yanhaijing.com/grunt/2014/07/14/building-a-javascript-library-with-grunt-js
- 英文:http://flippinawesome.org/2013/07/01/building-a-javascript-library-with-grunt-js/
相關文章
- 基於 Spring Boot 2.0 構建一個 RESTful WebServiceSpring BootRESTWeb
- 基於 Stencil 構建 Web Components 元件庫Web元件
- 淺談自動化構建之grunt
- 構建一個基於容器的開發環境開發環境
- 從零構建一個基於Docker的Laravel應用DockerLaravel
- 構建第一個基於 Gradle 的 Spring Boot 專案GradleSpring Boot
- Kunbernetes-基於Nexus構建私有映象倉庫
- 基於 AnythingLLM 及 Ollama 構建本地知識庫
- 基於 EventBridge 構建資料庫應用整合資料庫
- 基於 MUI 構建一個具有 90 +頁面的APP應用UIAPP
- urlcat:JavaScript的URL構建器庫JavaScript
- websocketd | 基於 docker 構建WebDocker
- 使用flex佈局構建一個iphone容器---基於react,styled-componentsFlexiPhoneReact
- 實戰Parcel構建一個基於Vue.js的相簿應用Vue.js
- 基於 Apache ShardingSphere 構建高可用分散式資料庫Apache分散式資料庫
- 動手學Avalonia:基於矽基流動構建一個文生圖應用(一)
- 基於 ubuntu base 構建 rootfsUbuntu
- 基於xcrun的工程構建
- GearCase UI – 自己構建一套基於 Vue 的簡易開源元件庫UIVue元件
- 使⽤用Requests庫構建⼀一個HTTP請求HTTP
- 構建一個基於事件分發驅動的EventLoop執行緒模型事件OOP執行緒模型
- 構建工具:grunt、Glup、webpackWeb
- 基於 Docker 構建統一的開發環境Docker開發環境
- 構建一個 @synchronizedsynchronized
- 基於vuecli3構建一個快速開發h5 APP的模板VueH5APP
- 基於ubuntu映象構建redis映象UbuntuRedis
- 基於VMWare構建私有云2019
- 從0到1構建基於自身業務的前端工具庫前端
- 自動化構建工具 Grunt
- 基於url-to-pdf-api構建docker映象,製作一個網頁另存服務APIDocker網頁
- 基於Amazon ECS Fargate構建Apache SupersetApache
- 基於kubernetes構建混合雲的利弊
- 如何開發一個基於 Vue 的 ui 元件庫(一)VueUI元件
- Topshelf一個用於使用.NET構建Windows服務框架Windows框架
- 基於webpack構建的angular 1.x 工程(一)webpack篇WebAngular
- 基於Java語言構建區塊鏈(一)—— 基本原型Java區塊鏈原型
- 微軟正在構建一個基於 Chromium 的瀏覽器並計劃取代 Microsoft Edge微軟瀏覽器ROS
- JavaScript 建構函式JavaScript函式
- 輕鬆構建基於 Serverless 架構的小程式Server架構