《JavaScript開發框架權威指南》——2.5 操作文件係統
本節書摘來自異步社區《JavaScript開發框架權威指南》一書中的第2章,第2.5節,作者:【美】Tim Ambler , Nicholas Cloud著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看
2.5 操作文件係統
可想而知,作為構建工具,大部分Grunt插件都要以某種方式和文件係統交互。鑒於操作文件的重要性,Grunt提供了有益的抽象允許開發者與文件係統交互,並且僅僅使用很少數量的樣板代碼。
當然,我們不會把所有方法都列舉在此,表顯示了Grunt文件操作API中一些使用頻率最高的方法。
2.5.1 源-目標映射
許多Grunt任務與文件係統交互是依賴於源-目標映射的,該映射描述了要被處理的文件及各文件對應的目標。構建這樣的映射會很冗長乏味,感謝Grunt為我們提供了解決此問題的有益捷徑。
假設你正在開發一個項目,該項目根目錄有一個公共文件夾。一旦工程部署後,這個文件夾中的文件要通過網絡提供服務(見清單)。
清單2-23 虛構項目的公共文件夾內容
// example-iterate1
.
└── public
└── images
├── cat1.jpg
├── cat2.jpg
└── cat3.png
如你所見,項目包含一個圖片文件夾,其中有三個文件。了解這些內容之後,讓我們看看Grunt能通過哪些方式來幫我們迭代這些文件。
如清單所示,Grunt的多任務配置和剛才介紹的很相似。關鍵不同之處在於任務配置中的src屬性。在我們的任務中,Grunt提供了一個this.files屬性,該屬性提供了一個包含著匹配到每個文件路徑的數組,這些文件通過node-glob模塊取得匹配到的文件路徑數組。任務輸出的結果可以在清單中看到。
清單2-24 Grunt多任務配置對象,包含一個src鍵
// example-iterate1/tasks/list-files.js
module.exports = function(grunt) {
grunt.config('list-files', {
'images': {
'src': ['public/**/*.jpg', 'public/* * /* .png']
}
});
grunt.registerMultiTask('list-files', function() {
this.files.forEach(function(files) {
grunt.log.writeln('Source:', files.src);
});
});
};
清單2-25 清單中Grunt任務輸出的結果
$ grunt list-files
Running "list-files:images" (#list-files) task
Source: [ 'public/images/cat1.jpg',
'public/images/cat2.jpg',
'public/images/cat3.png' ]
Done, without errors.
配置屬性src和多任務屬性this.files的結合使用,在迭代多文件時給開發者提供了精確的語法。以上的例子明顯設計得非常簡單,不過Grunt也同樣為更複雜的場景提供額外選項。下麵讓我們來看一下。
與清單中所示的鍵src的用法相反,清單的例子展示了文件數組的使用——盡管這種方法有點冗長,但它為選擇文件提供了更強大的數據格式。該格式接受額外的選項,從而讓我們能夠更好地調整我們的選擇。特別重要的是它的expand選項,如清單所示。請仔細關注,由於使用了expand選項,該示例與清單的輸出有所不同。
清單2-26 使用“文件數組”格式迭代文件
// example-iterate2/tasks/list-files.js
module.exports = function(grunt) {
grunt.config('list-files', {
'images': {
'files': [
{
'cwd': 'public',
'src': ['**/*.jpg', '* */*.png'],
'dest': 'tmp',
'expand': true
}
]
}
});
grunt.registerMultiTask('list-files', function() {
this.files.forEach(function(files) {
grunt.log.writeln('Source:', files.src);
grunt.log.writeln('Destination:', files.dest);
});
});
};
清單2-27 清單中Grunt任務的輸出
$ grunt list-files
Running "list-files:images" (#list-files) task
Source: [ 'public/images/cat1.jpg' ]
Destination: tmp/images/cat1.jpg
Source: [ 'public/images/cat2.jpg' ]
Destination: tmp/images/cat2.jpg
Done, without errors.
當該expand選項與dest選項成對出現的時候,表示明Grunt會迭代訪問任務中的this.files.forEach循環所找到的每個入口文件。在每個文件內,我們可以找到對應的dest屬性。使用這種方法,我們就能很容易地創建源-目的地映射,可以用於把文件從一個位置複製(或移動)到另一個位置。
2.5.2 監視文件變化
當特定模式下匹配到的文件被創建、修改、刪除時,Grunt最為流行的插件之一grunt-contrib-watch使Grunt有能力運行預定義的任務。當和其他任務結合在一起時,grunt-contrib-watch讓開發者能創建強大的工作流,用於自動執行如下工作:
檢查JavaScript代碼中的錯誤(如靜態語法分析“linting”);
編譯Sass/L樣式表;
運行單元測試
下麵讓我們看幾個實踐中運用上述工作流的例子。
1.JavaScript 自動化靜態檢查
清單顯示了一個基本的Grunt設置,和本章已經展示的示例相似。監視任務以默認任務作為別名注冊在Grunt中,這樣我們就能簡單地在命令行中運行$ grunt來監視項目中的變化。本例中,Grunt會監視src文件夾下的變化。一旦變化發生,jshint任務就會觸發。
清單2-28 發生變化時自動檢查JavaScript錯誤
// example-watch-hint/Gruntfile.js
module.exports = function(grunt) {
grunt.loadTasks('tasks');
grunt.registerTask('default', ['watch']);
};
// example-watch-hint/tasks/jshint.js
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-jshint');
grunt.config('jshint', {
'options': {
'globalstrict': true,
'node': true,
'scripturl': true,
'browser': true,
'jquery': true
},
'all': [
'src/**/*.js'
]
});
};
// example-watch-hint/tasks/watch.js
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.config('watch', {
'js': {
'files': [
'src/**/*'
],
'tasks': ['jshint'],
'options': {
'spawn': true
}
}
});
};
2.自動編譯Sass樣式表
清單展示了這樣一個示例,它引導Grunt來監視項目變化。然而這次不同於監視JavaScript文件,Grunt監視的是項目的Sass樣式表。當變化發生的時候,插件grunt-contrib-compass被調用,把樣式表編譯為最終形態。
清單2-29 變化發生時自動編譯Sass樣式表
// example-watch-sass/Gruntfile.js
module.exports = function(grunt) {
grunt.loadTasks('tasks');
grunt.registerTask('default', ['watch']);
};
// example-watch-sass/tasks/compass.js
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-compass');
grunt.config('compass', {
'all': {
'options': {
'httpPath': '/',
'cssDir': 'public/css',
'sassDir': 'scss',
'imagesDir': 'public/images',
'relativeAssets': true,
'outputStyle': 'compressed'
}
}
});
};
// example-watch-compass/tasks/watch.js
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.config('watch', {
'scss': {
'files': [
'scss/**/*'
],
'tasks': ['compass'],
'options': {
'spawn': true
}
}
});
};
注意:
若想讓本例生效,前提是需要安裝Compass。它是一個開源CSS編輯框架。
3.自動化單元測試
最後一個例子是使用grunt-contrib-watch插件來完成單元測試。清單展示了用於監視JavaScript變化的Gruntfile。變化發生時會立即觸發項目的單元測試,單元測試由grunt-mocha-test插件完成。
清單2-30 當變化發生時自動運行單元測試
// example-watch-test/Gruntfile.js
module.exports = function(grunt) {
grunt.loadTasks('tasks');
grunt.registerTask('default', ['watch']);
};
// example-watch-test/tasks/mochaTest.js
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-mocha-test');
grunt.config('mochaTest', {
'test': {
'options': {
'reporter': 'spec'
},
'src': ['test/**/*.js']
}
});
};
// example-watch-test/tasks/watch.js
module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-contrib-watch');
grunt.config('watch', {
'scss': {
'files': [
'src/**/*.js'
],
'tasks': ['mochaTest'],
'options': {
'spawn': true
}
}
});
};
最後更新:2017-06-06 07:32:56