1. 程式人生 > 其它 >ASP.NET5之客戶端開發:Grunt和Gulp構建工具在Visual Studio 2015中的高效的應用Grunt和Gulp使用Grunt準備專案配置NPM配置Grunt整合起來監測檔案變化與V

ASP.NET5之客戶端開發:Grunt和Gulp構建工具在Visual Studio 2015中的高效的應用Grunt和Gulp使用Grunt準備專案配置NPM配置Grunt整合起來監測檔案變化與V

Grunt和Gulp是Javascript世界裡的用來做自動壓縮、Typescript編譯、程式碼質量lint工具、css前處理器的構建工具,它幫助開發者處理客戶端開發中的一些煩操重複性的工作。Grunt和Gulp都在Visual studio 2015中得到支援。ASP.NET 專案模板預設使用Gulp。

Grunt和Gulp

Grunt和Gulp有什麼區別?Gulp雖然是稍微晚一點登場的,但是它因crisp performance和優雅的語法受到歡迎。與Grunt不同,Grunt往往在硬碟上是讀寫檔案,Gulp使用流式的API去鏈式的呼叫方法,Grunt是早些出現的客戶端構建工具,Grunt預定義了大多數經常要做的壓縮和單元測試等工作。Grunt每天都有數以千計的下載和應用。

使用Grunt

這個例項使用Empty ASP.NET專案模板來展示自動化的客戶端構建工作。非空的ASP.NET專案模板預設使用Gulp。

最終示例清理目標部署目錄,合併Javascript檔案,檢查程式碼質量,壓縮Javascript檔案內容並且部署到web專案的跟目錄,我們將使用以下包:

grunt:任務執行者包; grunt-contrib-clean:一個用來移除檔案和目錄的任務 grunt-contrib-jshint:一個審查程式碼質量的任務 grunt-contrib-concat:一個連線多檔案在一個檔案中的任務 grunt-contrib-uglify:一個壓縮和縮小檔案尺寸的任務 grunt-contrib-watch:一個檢測檔案活動的任務

準備專案

首先,建立信的空的Web應用程式新增示例的Typescript檔案,Typescript檔案在Visual Studio 2015的預設設定下,會自動地編譯為Javascript中並且作為Grunt的原始檔。

  1. 在Vistual Studio 2015中,建立新的ASP.NET應用程式。
  2. 在“新ASP.NET專案”對話方塊中,選擇ASP.NET Empty模板並且單擊OK按鈕。
  3. 在解決方案管理器中,可以看到專案的目錄結構,Src資料夾包含一個空的wwwroot和dependencies節點
  1. 在專案中新增一個名為Typescript的資料夾
  2. 在新增任何檔案之前,確認Visual Studio 2015打開了“儲存時編譯”的專案(在“工具->選項->文字編輯器->Typescript=>專案”節點下)
  1. 右擊Typescript目錄,點選”新增->新專案”選擇Javascript專案命名為Tastes.ts(注意ts字尾),拷貝下列程式碼
enum Tastes { Sweet, Sour, Salty, Bitter }
  1. 在Typescript目錄中新增第二個檔案命名為Food.ts,拷貝以下程式碼
class Food {
    constructor(name: string, calories: number) {
        this._name = name;
        this._calories = calories;
    }

    private _name: string;
    get Name() {
        return this._name;
    }

    private _calories: number;
    get Calories() {
        return this._calories;
    }

    private _taste: Tastes;
    get Taste(): Tastes { return this._taste }
    set Taste(value: Tastes) {
        this._taste = value;
    }
}

配置NPM

下一步,配置npm來下來grunt和grunt-tasks

  1. 在解決方案目錄中,右擊並選擇“新增->新專案”選擇npm configuration file,保留預設的檔名,點選確定按鈕
  2. 在package.json檔案中,在devDependencies屬性下,輸入grunt,使用只能提示選擇grunt並回車,新增冒號,並使用智慧提示選擇版本號
  1. 新增我們需要的更多的依賴專案
  1. 儲存檔案

這些包將會被自動下載,你可以在node-modules目錄下看到下載的內容,前提是你打開了”顯示所有檔案“

如果需要的話,你要可以通過右鍵單擊dependences下的NPM,選擇Restore Packages按鈕恢復這些包

配置Grunt

Grunt使用名為gruntfile.js的檔案清單進行配置、載入和註冊任務,讓它可以手動的執行或者基數Vistual Studio的事件機制自動執行

  1. 右鍵單擊專案檔案,選擇”新增->新專案“,選擇”Grunt configuration file”選項,保留預設的檔名,並點選新增按鈕 初始的檔案包含了grunt.initConfig()方法,這個方法就是我們用來設定選項的地方
module.exports = function (grunt) {
    grunt.initConfig({
    });
};
  1. 在上文的方法中,新增clean任務,這個配置可以新增一個數組來定義要清理的目錄或者檔案
module.exports = function (grunt) {
    grunt.initConfig({
        clean: ["wwwroot/lib/*", "temp/"],
    });
};
  1. 在initConfig方法下方,我們需要呼叫grunt.loadNpmTasks方法來讓任務在Visual Studio中執行
grunt.loadNpmTasks("grunt-contrib-clean");
  1. 儲存這個檔案,檔案內容如下所示
module.exports = function (grunt) {
    grunt.initConfig({
        clean: ["wwwroot/lib/*", "temp/"],
    });
    grunt.loadNpmTasks("grunt-contrib-clean");
};
  1. 右鍵點選gruntfile.js,選擇”Task Runner Explorer”
  2. 驗證clean任務已經出現在“任務”節點下
  1. 右鍵點選clean任務,選擇Run,一個命令列窗體顯示,並執行定義的任務
  1. 在initConfig方法中,新增concat任務 Src屬性定義了要連結的檔案列表,dest屬性定義了合併完成的目標檔案,而all屬性定義了在任何構建環境下,任務都將執行
module.exports = function (grunt) {
    grunt.initConfig({
        clean: ["wwwroot/lib/*", "temp/"],
        concat: {
            all: {
                src: ['TypeScript/Tastes.js', 'TypeScript/Food.js'],
                dest: 'temp/combined.js'
            }
        },
    });
    grunt.loadNpmTasks("grunt-contrib-clean");
};
  1. 新增jihit任務 jihit程式碼質量工具將會在temp目錄下所有的js檔案中執行
jshint: {
            files: ['temp/*.js'],
            options: {
                '-W069': false,
            }
        }
  1. 新增uglify任務 src定義了混淆的原始檔列表,dest定義了目標檔案
uglify: {
        all: {
                src: ['temp/combined.js'],
                dest: 'wwwroot/lib/combined.min.js'
        }
},
  1. 最後,呼叫grunt.loadNpmTasks()讓上文定義的所有任務在Visual Studio中執行
  2. 儲存檔案,最終檔案內容如下所示
module.exports = function (grunt) {
    grunt.initConfig({
        clean: ["wwwroot/lib/*", "temp/"],
        concat: {
            all: {
                src: ['TypeScript/Tastes.js', 'TypeScript/Food.js'],
                dest: 'temp/combined.js'
            }
        },
        jshint: {
            files: ['temp/*.js'],
            options: {
                '-W069': false,
            }
        },
        uglify: {
            all: {
                src: ['temp/combined.js'],
                dest: 'wwwroot/lib/combined.min.js'
            }
        },
    });
    grunt.loadNpmTasks("grunt-contrib-clean");
    grunt.loadNpmTasks('grunt-contrib-jshint');
    grunt.loadNpmTasks('grunt-contrib-concat');
    grunt.loadNpmTasks('grunt-contrib-uglify');
};
  1. 你會發現,上文定義的任務已經都出現在了Task Runner Explorer中

依次執行這些任務,

整合起來

使用grunt.registerTask方法來註冊執行一系列指定順序的任務,比如,執行上文中任務的順序應該為clean->concat->jshint->uglify。在檔案中新增以下程式碼,並且保持方法呼叫和loadNpmTasks呼叫時同級的

grunt.registerTask("all", ['clean', 'concat', 'jshint', 'uglify']);

現在你可以在Task Runner Explorer中找到一個名為all的別名任務,執行它即可順序執行上文中的所有任務了 

監測檔案變化

Watch任務可以監視檔案和目錄的變化,並且在監測到變化後觸發一系列任務,在initConfig方法中新增以下的程式碼來監視Typescript目錄下的所有js檔案的變化,並執行’all“任務

watch: {
            files: ["TypeScript/*.js"],
            tasks: ["all"]
        }

新增一個loadNpmTask方法呼叫讓任務顯示在Task Runner Explorer中

grunt.loadNpmTasks('grunt-contrib-watch');

執行Watch任務,命令列窗體將處在等待狀態,此時它監視著檔案的變化,開啟一個Typescript檔案,新增任何內容,你就會發現它已經在工作了

與Visual Studio事件一起協作

你除了可以手動執行這些任務之外,你還可以把這些任務和Visual Studio事件繫結,當Visual Studio觸發既定的事件後,自動執行定義的任務 在Task Runner Explorer中,右鍵點選watch任務,選擇“Bindings->Project Open”,此時,當你開啟專案的時候,watch任務將自動執行並且觀測檔案變化並執行上文中定義的一系列任務

使用Gulp

除了一些著名的不同以外,Gulp的配置檔案和grunt的非常相似,下文中的例子對比grunt的示例但是使用gulp包和約定。

NPM 包的不同

與grunt一樣,gulp定義也在ackage.json檔案的devDependencies屬性中,內容如下文所示,你也可以通過只能提示來更新到最近的版本號。

{
  "version": "1.0.0",
  "name": "GruntFromEmptyWebApp",
  "private": true,
  "devDependencies": {
    "gulp": "3.8.11",
    "gulp-clean": "0.3.1",
    "gulp-jshint": "1.11.0",
    "gulp-concat": "2.5.2",
    "gulp-uglify":"1.2.0",
    "gulp-rename": "1.2.2",
    "gulp-watch": "4.2.4"
  }
}

Gulpfile和Gruntfile示例的不同

取代gruntfile.js,新增一個命名為gulpfile.js的檔案,在這個檔案中,使用node.js的方法require()為下文中的幾個變數賦值

var gulp = require('gulp');
var clean = require('gulp-clean');
var concat = require('gulp-concat');
var jshint = require('gulp-jshint');
var uglify = require('gulp-uglify');
var rename = require('gulp-rename');
var watch = require('gulp-watch');

在賦值語句下方,呼叫gulp的task方法,第一個引數是任務的名字的字串表示方式,第二個引數是一個回撥方法

gulp.task('default', function () {
    // place code for your default task here
});

此時在Task Runner Explorer中已經存在一個命名為default的任務,雖然它是空的

在task方法的回撥函式內部,使用方才定義的gulp執行我們需要的工作,首先定義一個clean任務

gulp.src('wwwroot/lib/*').pipe(clean());

Gulp流

gulp是一個包含src、pipe和dest方法的流式物件

  • src()方法用來定義流從哪裡來
  • pipe()方法定義怎麼重寫流
  • dest()方法定義流的輸出

程式碼通常的模式如下文所示

gulp.src()
        .pipe()
        .pipe()
        .pipe(dest());

src方法拿到初始的原始流檔案,在一系列的pipe呼叫後執行對流的操作,最後通過dest()方法輸出最終的結果,這種方式的優勢是隻有一個輸入和一個輸出,讓任務執行的更快。

整合

下文是我們組織的一系列任務,將它定義為ALL,執行的任務和上文中grunt的例子是完全一樣的

gulp.task("all", function () {
    gulp.src('wwwroot/lib/*').pipe(clean());
    gulp.src(['TypeScript/Tastes.js', 'TypeScript/Food.js'])
           .pipe(concat("combined.js"))
           .pipe(jshint())
           .pipe(uglify())
           .pipe(rename({
               extname: '.min.js'
           }))
           .pipe(gulp.dest('wwwroot/lib'))
});

watch任務也和grunt的示例非常相似

gulp.task("watch", function () {
    gulp.watch("TypeScript/*.js", ['all']);
});

使用同樣的方式,在Task Runner Explorer中繫結Visual Studio事件,就可以讓watch任務在專案開啟時自動執行了。

乙烷

原文連結:http://docs.asp.net/en/latest/client-side/grunt-gulp.html