閱讀552 返回首頁    go 阿裏雲 go 技術社區[雲棲]


《JavaScript開發框架權威指南》——2.5 操作文件係統

本節書摘來自異步社區《JavaScript開發框架權威指南》一書中的第2章,第2.5節,作者:【美】Tim Ambler , Nicholas Cloud著,更多章節內容可以訪問雲棲社區“異步社區”公眾號查看

2.5 操作文件係統

可想而知,作為構建工具,大部分Grunt插件都要以某種方式和文件係統交互。鑒於操作文件的重要性,Grunt提供了有益的抽象允許開發者與文件係統交互,並且僅僅使用很少數量的樣板代碼。

當然,我們不會把所有方法都列舉在此,表顯示了Grunt文件操作API中一些使用頻率最高的方法。
screenshot
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

  上一篇:go  阿裏雲生態日沙龍申請及落地規則
  下一篇:go  在 Docker 中運行 MySQL:多主機網絡下 Docker Swarm 模式的容器管理