Grunt 配置任務(wù)

2018-11-02 11:37 更新

配置任務(wù)

這個(gè)指南解釋了如何使用 Gruntfile 來為你的項(xiàng)目配置task。如果你還不知道 Gruntfile 是什么,請(qǐng)先閱讀 快速入門 指南并看看這個(gè) Gruntfile 實(shí)例

Grunt配置

Grunt的task配置都是在 Gruntfile 中的grunt.initConfig方法中指定的。此配置主要是以任務(wù)名稱命名的屬性,也可以包含其他任意數(shù)據(jù)。一旦這些代表任意數(shù)據(jù)的屬性與任務(wù)所需要的屬性相沖突,就將被忽略。

此外,由于這本身就是JavaScript,因此你不僅限于使用JSON;你可以在這里使用任何有效的JavaScript。必要的情況下,你甚至可以以編程的方式生成配置。

grunt.initConfig({
  concat: {
    // 這里是concat任務(wù)的配置信息。
  },
  uglify: {
    // 這里是uglify任務(wù)的配置信息
  },
  // 任意數(shù)據(jù)。
  my_property: 'whatever',
  my_src_files: ['foo/*.js', 'bar/*.js'],
});

任務(wù)配置和目標(biāo)

當(dāng)運(yùn)行一個(gè)任務(wù)時(shí),Grunt會(huì)自動(dòng)查找配置對(duì)象中的同名屬性。多任務(wù)(multi-task)可以通過任意命名的“目標(biāo)(target)”來定義多個(gè)配置。在下面的案例中,concat任務(wù)有名為foo和bar兩個(gè)目標(biāo),而uglify任務(wù)僅僅只有一個(gè)名為bar目標(biāo)。

grunt.initConfig({
  concat: {
    foo: {
      // concat task "foo" target options and files go here.
    },
    bar: {
      // concat task "bar" target options and files go here.
    },
  },
  uglify: {
    bar: {
      // uglify task "bar" target options and files go here.
    },
  },
});

同時(shí)指定任務(wù)(task)和目標(biāo)(target),例如grunt concat:foo或者grunt concat:bar,將只會(huì)處理指定目標(biāo)(target)的配置,而運(yùn)行g(shù)runt concat將遍歷所有目標(biāo)(target)并依次處理。注意,如果一個(gè)任務(wù)使用grunt.task.renameTask重命名過,Grunt將在配置對(duì)象中查找以新的任務(wù)名命名的屬性。

options屬性

在一個(gè)任務(wù)配置中,options屬性可以用來指定覆蓋內(nèi)置屬性的默認(rèn)值。此外,每一個(gè)目標(biāo)(target)中還可以擁有一個(gè)專門針對(duì)此目標(biāo)(target)的options屬性。目標(biāo)(target)級(jí)的平options將會(huì)覆蓋任務(wù)級(jí)的options。

options對(duì)象是可選的,如果不需要,可以忽略。

grunt.initConfig({
  concat: {
    options: {
      // 這里是任務(wù)級(jí)的Options,覆蓋默認(rèn)值 
    },
    foo: {
      options: {
        // "foo" target options may go here, overriding task-level options.
      },
    },
    bar: {
      // No options specified; this target will use task-level options.
    },
  },
});

文件

由于大多的任務(wù)都是執(zhí)行文件操作,Grunt有一個(gè)強(qiáng)大的抽象層用于聲明任務(wù)應(yīng)該操作哪些文件。這里有好幾種定義src-dest(源文件-目標(biāo)文件)文件映射的方式,均提供了不同程度的描述和控制操作方式。任何一種多任務(wù)(multi-task)都能理解下面的格式,所以你只需要選擇滿足你需求的格式就行。

所有的文件格式都支持src和dest屬性,此外"Compact"[簡潔]和"Files Array"[文件數(shù)組]格式還支持以下一些額外的屬性:

  • filter 它通過接受任意一個(gè)有效的fs.Stats方法名或者一個(gè)函數(shù)來匹配src文件路徑并根據(jù)匹配結(jié)果返回true或者false。
  • nonull 如果被設(shè)置為 true,未匹配的模式也將執(zhí)行。結(jié)合Grunt的--verbore標(biāo)志, 這個(gè)選項(xiàng)可以幫助用來調(diào)試文件路徑的問題。
  • dot 它允許模式模式匹配句點(diǎn)開頭的文件名,即使模式并不明確文件名開頭部分是否有句點(diǎn)。
  • matchBase如果設(shè)置這個(gè)屬性,缺少斜線的模式(意味著模式中不能使用斜線進(jìn)行文件路徑的匹配)將不會(huì)匹配包含在斜線中的文件名。 例如,a?b將匹配/xyz/123/acb但不匹配/xyz/acb/123。
  • expand 處理動(dòng)態(tài)的src-dest文件映射,更多的信息請(qǐng)查看動(dòng)態(tài)構(gòu)建文件對(duì)象。
  • 其他的屬性將作為匹配項(xiàng)傳遞給底層的庫。 請(qǐng)查看node-glob 和minimatch 文檔以獲取更多信息。

簡潔格式

這種形式允許每個(gè)目標(biāo)對(duì)應(yīng)一個(gè)src-dest文件映射。通常情況下它用于只讀任務(wù),比如grunt-contrib-jshint,它就只需要一個(gè)單一的src屬性,而不需要關(guān)聯(lián)的dest選項(xiàng). 這種格式還支給每個(gè)src-dest文件映射指定額外的屬性。

grunt.initConfig({
  jshint: {
    foo: {
      src: ['src/aa.js', 'src/aaa.js']
    },
  },
  concat: {
    bar: {
      src: ['src/bb.js', 'src/bbb.js'],
      dest: 'dest/b.js',
    },
  },
});

文件對(duì)象格式

這種形式支持每個(gè)目標(biāo)對(duì)應(yīng)多個(gè)src-dest形式的文件映射,屬性名就是目標(biāo)文件,源文件就是它的值(源文件列表則使用數(shù)組格式聲明)??梢允褂眠@種方式指定數(shù)個(gè)src-dest文件映射, 但是不能夠給每個(gè)映射指定附加的屬性。

grunt.initConfig({
  concat: {
    foo: {
      files: {
        'dest/a.js': ['src/aa.js', 'src/aaa.js'],
        'dest/a1.js': ['src/aa1.js', 'src/aaa1.js'],
      },
    },
    bar: {
      files: {
        'dest/b.js': ['src/bb.js', 'src/bbb.js'],
        'dest/b1.js': ['src/bb1.js', 'src/bbb1.js'],
      },
    },
  },
});

文件數(shù)組格式

這種形式支持每個(gè)目標(biāo)對(duì)應(yīng)多個(gè)src-dest文件映射,同時(shí)也允許每個(gè)映射擁有額外屬性:

grunt.initConfig({
  concat: {
    foo: {
      files: [
        {src: ['src/aa.js', 'src/aaa.js'], dest: 'dest/a.js'},
        {src: ['src/aa1.js', 'src/aaa1.js'], dest: 'dest/a1.js'},
      ],
    },
    bar: {
      files: [
        {src: ['src/bb.js', 'src/bbb.js'], dest: 'dest/b/', nonull: true},
        {src: ['src/bb1.js', 'src/bbb1.js'], dest: 'dest/b1/', filter: 'isFile'},
      ],
    },
  },
});

較老的格式

dest-as-target文件格式在多任務(wù)和目標(biāo)出現(xiàn)之前是一個(gè)過渡形式,目標(biāo)文件路徑實(shí)際上就是目標(biāo)名稱。遺憾的是, 由于目標(biāo)名稱是文件路徑,那么運(yùn)行g(shù)runt task:target可能不合適。此外,你也不能指定一個(gè)目標(biāo)級(jí)的options或者給每個(gè)src-dest文件映射指定額外屬性。

此種格式已經(jīng)不贊成使用,請(qǐng)盡量不要使用。

grunt.initConfig({
  concat: {
    'dest/a.js': ['src/aa.js', 'src/aaa.js'],
    'dest/b.js': ['src/bb.js', 'src/bbb.js'],
  },
});

自定義過濾函數(shù)

filter屬性可以給你的目標(biāo)文件提供一個(gè)更高級(jí)的詳細(xì)幫助信息。只需要使用一個(gè)有效的fs.Stats 方法名。下面的配置僅僅清理一個(gè)與模式匹配的真實(shí)的文件:

grunt.initConfig({
  clean: {
    foo: {
      src: ['tmp/**/*'],
      filter: 'isFile',
    },
  },
});

或者創(chuàng)建你自己的filter函數(shù),根據(jù)文件是否匹配來返回true或者false。下面的例子將僅僅清理一個(gè)空目錄:

grunt.initConfig({
  clean: {
    foo: {
      src: ['tmp/**/*'],
      filter: function(filepath) {
        return (grunt.file.isDir(filepath) && require('fs').readdirSync(filepath).length === 0);
      },
    },
  },
});

通配符模式

通常分別指定所有源文件路徑是不切實(shí)際的,因此Grunt通過內(nèi)置支持node-glob 和 minimatch 庫來匹配文件名(又叫作globbing)。

然這并不是一個(gè)綜合的匹配模式方面的教程,你只需要知道如何在文件路徑匹配過程中使用它們即可:

  • * 匹配任意數(shù)量的字符,但不匹配 /
  • ? 匹配單個(gè)字符,但不匹配 /
  • ** 匹配任意數(shù)量的字符,包括 /,只要它是路徑中唯一的一部分
  • {} 允許使用一個(gè)逗號(hào)分割的“或”表達(dá)式列表
  • ! 在模式的開頭用于排除一個(gè)匹配模式所匹配的任何文件

每個(gè)人都需要知道的是:foo/*.js將匹配位于foo/目錄下的所有的.js結(jié)尾的文件;而foo/**/*js將匹配foo/目錄以及其子目錄中所有以.js結(jié)尾的文件。

此外, 為了簡化原本復(fù)雜的通配符模式,Grunt允許指定一個(gè)數(shù)組形式的文件路徑或者一個(gè)通配符模式。所有模式按順序處理,模式處理的過程中,帶有!前綴的模式所匹配的文件將不包含在結(jié)果集中。 而且其結(jié)果集中的每一項(xiàng)也是唯一的。

例如:

// 指定單個(gè)文件:
{src: 'foo/this.js', dest: ...}
// 指定一個(gè)文件數(shù)組:
{src: ['foo/this.js', 'foo/that.js', 'foo/the-other.js'], dest: ...}
// 使用一個(gè)匹配模式:
{src: 'foo/th*.js', dest: ...}

// 一個(gè)獨(dú)立的node-glob模式:
{src: 'foo/{a,b}*.js', dest: ...}
// 也可以這樣編寫:
{src: ['foo/a*.js', 'foo/b*.js'], dest: ...}

// foo目錄中所有的.js文件,按字母順序排序:
{src: ['foo/*.js'], dest: ...}
// 首先是bar.js,接著是剩下的.js文件,并按字母順序排序:
{src: ['foo/bar.js', 'foo/*.js'], dest: ...}

// 除bar.js之外的所有的.js文件,按字母順序排序:
{src: ['foo/*.js', '!foo/bar.js'], dest: ...}
// 按字母順序排序的所有.js文件,但是bar.js在最后。
{src: ['foo/*.js', '!foo/bar.js', 'foo/bar.js'], dest: ...}

// 模板也可以用于文件路徑或者匹配模式中:
{src: ['src/<%= basename %>.js'], dest: 'build/<%= basename %>.min.js'}
// 它們也可以引用在配置中定義的其他文件列表:
{src: ['foo/*.js', '<%= jshint.all.src %>'], dest: ...}

更多關(guān)于通配符模式的語法,請(qǐng)查看node-glob 和 minimatch 的文檔。

動(dòng)態(tài)構(gòu)建文件對(duì)象

當(dāng)你希望處理大量的單個(gè)文件時(shí),這里有一些附加的屬性可以用來動(dòng)態(tài)的構(gòu)建一個(gè)文件列表。這些屬性都可以用于Compact和Files Array文件映射格式。

expand 設(shè)置為true用于啟用下面的選項(xiàng):

  • cwd 所有src指定的匹配都將相對(duì)于此處指定的路徑(但不包括此路徑) 。
  • src 相對(duì)于cwd路徑的匹配模式。
  • dest 目標(biāo)文件路徑前綴。
  • ext 對(duì)于生成的dest路徑中所有實(shí)際存在文件,均使用這個(gè)屬性值替換擴(kuò)展名。
  • extDot 用于指定標(biāo)記擴(kuò)展名的英文點(diǎn)號(hào)的所在位置??梢再x值 'first' (擴(kuò)展名從文件名中的第一個(gè)英文點(diǎn)號(hào)開始) 或 'last' (擴(kuò)展名從最后一個(gè)英文點(diǎn)號(hào)開始),默認(rèn)值為 'first' [添加于 0.4.3 版本]
  • flatten 從生成的dest路徑中移除所有的路徑部分。
  • rename 對(duì)每個(gè)匹配的src文件調(diào)用這個(gè)函數(shù)(在重命名后綴和移除路徑之后)。dest和匹配的src路徑將被作為參數(shù)傳入,此函數(shù)應(yīng)該返回一個(gè)新的dest值。 如果相同的dest返回不止一次,那么,每個(gè)返回此值的src來源都將被添加到一個(gè)數(shù)組中作為源列表。

在下面的例子中,uglify 任務(wù)中的static_mappings和dynamic_mappings兩個(gè)目標(biāo)具有相同的src-dest文件映射列表, 這是因?yàn)槿蝿?wù)運(yùn)行時(shí)Grunt會(huì)自動(dòng)展開dynamic_mappings文件對(duì)象為4個(gè)單獨(dú)的靜態(tài)src-dest文件映射--假設(shè)這4個(gè)文件能夠找到。

可以指定任意靜態(tài)src-dest和動(dòng)態(tài)的src-dest文件映射相互結(jié)合。

grunt.initConfig({
  uglify: {
    static_mappings: {
      // Because these src-dest file mappings are manually specified, every
      // time a new file is added or removed, the Gruntfile has to be updated.
      files: [
        {src: 'lib/a.js', dest: 'build/a.min.js'},
        {src: 'lib/b.js', dest: 'build/b.min.js'},
        {src: 'lib/subdir/c.js', dest: 'build/subdir/c.min.js'},
        {src: 'lib/subdir/d.js', dest: 'build/subdir/d.min.js'},
      ],
    },
    dynamic_mappings: {
      // Grunt will search for "**/*.js" under "lib/" when the "uglify" task
      // runs and build the appropriate src-dest file mappings then, so you
      // don't need to update the Gruntfile when files are added or removed.
      files: [
        {
          expand: true,     // Enable dynamic expansion.
          cwd: 'lib/',      // Src matches are relative to this path.
          src: ['**/*.js'], // Actual pattern(s) to match.
          dest: 'build/',   // Destination path prefix.
          ext: '.min.js',   // Dest filepaths will have this extension.
          extDot: 'first'   // Extensions in filenames begin after the first dot
        },
      ],
    },
  },
});

模板

使用<% %>分隔符指定的模板會(huì)在任務(wù)從它們的配置中讀取相應(yīng)的數(shù)據(jù)時(shí)將自動(dòng)擴(kuò)展掃描。模板會(huì)被遞歸的展開,直到配置中不再存在遺留的模板相關(guān)的信息(與模板匹配的)。

整個(gè)配置對(duì)象決定了屬性上下文(模板中的屬性)。此外,在模板中使用grunt以及它的方法都是有效的,例如: <%= grunt.template.today('yyyy-mm-dd') %>。

  • <%= prop.subprop %> 將會(huì)自動(dòng)展開配置信息中的prop.subprop的值,不管是什么類型。像這樣的模板不僅可以用來引用字符串值,還可以引用數(shù)組或者其他對(duì)象類型的值。
  • <% %> 執(zhí)行任意內(nèi)聯(lián)的JavaScript代碼。對(duì)于控制流或者循環(huán)來說是非常有用的。

下面以concat任務(wù)配置為例,運(yùn)行g(shù)runt concat:sample時(shí)將通過banner中的/* abcde */連同foo/*.js+bar/*.js+bar/*.js匹配的所有文件來生成一個(gè)名為build/abcde.js的文件。

grunt.initConfig({
  concat: {
    sample: {
      options: {
        banner: '/* <%= baz %> */\n',   // '/* abcde */\n'
      },
      src: ['<%= qux %>', 'baz/*.js'],  // [['foo/*.js', 'bar/*.js'], 'baz/*.js']
      dest: 'build/<%= baz %>.js',      // 'build/abcde.js'
    },
  },
  //用于任務(wù)配置模板的任意屬性
  foo: 'c',
  bar: 'b<%= foo %>d', // 'bcd'
  baz: 'a<%= bar %>e', // 'abcde'
  qux: ['foo/*.js', 'bar/*.js'],
});

導(dǎo)入外部數(shù)據(jù)

在下面的Gruntfile中,項(xiàng)目的元數(shù)據(jù)是從package.json文件中導(dǎo)入到Grunt配置中的,并且grunt-contrib-uglify 插件中的 uglify 任務(wù)被配置用于壓縮一個(gè)源文件以及使用該元數(shù)據(jù)動(dòng)態(tài)的生成一個(gè)banner注釋。

Grunt有g(shù)runt.file.readJSON和grunt.file.readYAML兩個(gè)方法分別用于引入JSON和YAML數(shù)據(jù)。

grunt.initConfig({
  pkg: grunt.file.readJSON('package.json'),
  uglify: {
    options: {
      banner: '/*! <%= pkg.name %> <%= grunt.template.today("yyyy-mm-dd") %> */\n'
    },
    dist: {
      src: 'src/<%= pkg.name %>.js',
      dest: 'dist/<%= pkg.name %>.min.js'
    }
  }
});
以上內(nèi)容是否對(duì)您有幫助:
在線筆記
App下載
App下載

掃描二維碼

下載編程獅App

公眾號(hào)
微信公眾號(hào)

編程獅公眾號(hào)