grunt增量式任務,遇到的一些坑

恩。。今天趁着有空,把項目裏的前端相關的東西弄個自動化好了
工具grunt很少介紹了,你們都懂得。。。
安裝也很少說了,google上都有的javascript

項目須要的功能

  1. css最小化
  2. js壓縮
  3. coffee編譯

這些都是比較常見的功能了,固然css的預編譯還有less、sass,在此處的原理和coffee->js的邏輯同樣,也不贅述了css

package.json

json{
  "name": "project_name",
  "version": "0.0.1",
  "devDependencies": {
    "grunt": "~0.4.5",
    "grunt-contrib-cssmin": "~0.5.0",
    "grunt-contrib-uglify": "~0.8.0",
    "grunt-contrib-coffee": "~0.13.0",
    "grunt-contrib-copy": "~0.8.0",
    "grunt-contrib-watch": "~0.6.1",
  },
  "main": "Gruntfile.js",
  "author": "zhulegequ",
  "license": "MIT"
}

依賴的包,前面四個不解釋了,顧名思義。
grunt-contrib-copy:拷貝文件、文件數,此處是由於項目裏有一些圖片啊字體文件啊模板文件等其餘的靜態文件,這些文件和css、js放在一個文件夾裏,但css、js會隨着壓縮而移動,因此須要這個包
grunt-contrib-watch:監視文件修改,增量任務的關鍵前端

Gruntfile.coffee

grunt既支持javascript,也能支持coffeescript,爲了統一逼格,因此此處用的是coffeescript,coffeescript編譯到js,減小了不少代碼量,能夠說不再用擔憂大括號了。我也是今天才寫,仍是挺好使得。。java

文件我分爲三部分,此處的分部主要是功能的分開,但代碼不必定是分開的,注意縮進:git

第一部分:基本任務定義

coffeescriptmodule.exports = (grunt)->
#第一部分開始,這一部分是初始化配置,
  grunt.initConfig
    pkg: grunt.file.readJSON('package.json')
    cssmin: 
      comparecss: 
        files:[
                    expand:true
                    cwd:'themes/src/'#目錄下
                    src:'**/*.css'#全部css文件
                    dest: 'themes/dist/'#輸出到此目錄下
                ]
    uglify: #壓縮js
      comparejs: 
        files:[
                    expand:true
                    cwd:'themes/src/'#目錄下
                    src:'**/*.js'#全部js文件
                    dest: 'themes/dist/'#輸出到此目錄下
                ]
    copy: #移動
      main: 
        files:[
              expand:true
              cwd:'themes/src/'#目錄下
              src:['*.template']#全部模板文件
              dest: 'themes/dist/'#輸出到此目錄下
          ]
    coffee:
      compile:
        options:
          bare:true
        files:[
              expand:true
              flatten: true
              cwd:'themes/src/coffee'#目錄下
              src:'*.coffee'#全部coffee文件
              ext: '.js'
              dest: 'themes/src/js'#輸出到此目錄下
          ]
          #第一部分結束

第一部分的功能是初始化配置,在這裏基本定義了幾個任務:cssmin、uglify、copy、coffee,相關的標誌位文檔能夠查看這些包的github主頁,一個比較常見的標誌位expand,表示會遞歸的輸送,好比在src='folder/src',dest='folder/dest/'的狀況下,folder/src/a/b/c.js,會輸送到folder/dest/a/b/c.jsgithub

第二部分:監視任務定義

恩,這一部分其實算坑吧也不知道算不算,在watch的一個示例文檔中,其實也提到了基礎的用法:json

coffeescriptgrunt.initConfig({
  watch: {
#忽略一部分代碼
    src: {
      files: ['lib/*.js', 'css/**/*.scss', '!lib/dontwatch.js'],
      tasks: ['default'],
    },
  },
});

表示定義了一個src的監視任務,監視到files變量裏的文件修改時,執行default任務。
還提到了一個增量的例子:sass

coffeescriptgrunt.initConfig({
  jshint: {#定義一個jshint任務
    all: {
      src: ['lib/*.js'],
    },
  },
  watch: {#定義監視任務
    scripts: {
      files: ['lib/*.js'],
      tasks: ['jshint'],
      options: {
        spawn: false,
      },
    },
  },
});
grunt.event.on('watch', function(action, filepath,target) {#此處回調函數應當是3個參數,target是監視任務名,此處是scripts,在有多個監視任務的時候有用
  grunt.config('jshint.all.src', filepath);
});

監視任務仍是同樣的,spawn標誌位的做用挺魔怔的。。默認是true,你們能夠試一試效果,這個標誌位特別重要!特別重要!特別重要!千萬別漏了,漏了就是起的全量更新做用了。less

此處起到監視增量做用的,就是註冊的這個事件回調
實際上這句等同於grunt.config.set('jshint.all.src', filepath),我都要哭了。。函數

因此下面是個人監視任務定義

coffeescript#第二部分開始
    watch:
      coffeescript:
        files:['themes/src/coffee/*.coffee']
        tasks:'coffee'
        # options: #這個很關鍵
        #   spawn: false
      jsuglify:
        files:['themes/src/**/*.js']
        tasks:'uglify'
        options: 
          spawn: false
      cssminify:
        files:['themes/src/**/*.css']
        tasks:'cssmin'
        options: 
          spawn: false
  #這段的縮進和grunt.initConfig平級
  grunt.loadNpmTasks('grunt-contrib-cssmin')
  grunt.loadNpmTasks('grunt-contrib-uglify')
  grunt.loadNpmTasks('grunt-contrib-coffee')
  grunt.loadNpmTasks('grunt-contrib-watch')

注意到我這裏的coffeescript的spawn被我註釋掉了,這裏坑了我一小下,這樣意味着coffeescript的更新,是全量更新,一個文件修改了,所有文件都會從新編譯一次,爲啥這樣作呢,由於有coffeescript->javascript->javascript.min這個過程,若是此處spawn置爲false,那麼後邊那半段就沒了。。。技術所限,只能走這樣的流水線,若是大家知道coffeescript->javascript.min的過程,請務必告訴我。。

第三部分:同步刪除

做用:刪除js源文件的時候,把生成的js.min刪掉,css同理

coffeescriptdeleteDist=(srcfilepath,distpath,sourcepath)->
    distfile = distpath+srcfilepath.substring(sourcepath.length)
    if grunt.file.exists(distfile)
      grunt.file.delete(distfile)
  grunt.event.on 'watch', (action, filepath,target) ->
    console.log action, filepath,target
    if target=="jsuglify"
      if action == "deleted" or action=="renamed"
        deleteDist(filepath,'themes/dist/','themes/src/')
        if action=="deleted"
          return
      grunt.config 'uglify.comparejs.files',
        [
          expand:true
          cwd:'themes/src/'#目錄下
          src:filepath.substring(11)#去掉 themes/src/ 這11個字符
          dest: 'themes/dist/'#輸出到此目錄下
        ]
      console.log 'uglify detach',filepath,action
      return
    else if target=="coffeescript"
      grunt.config "coffee.compile.files",#覆蓋配置,只對修改文件進行編譯
      [
            expand:true
            flatten: true
            cwd:'themes/src/coffee'#目錄下
            src:filepath.substring(18)#
            ext: '.js'
            dest: 'themes/src/js'#輸出到此目錄下
        ]
      console.log 'coffeescript detach',filepath,action
      return
    else if target=="cssminify"
      if action == "deleted" or action=="renamed"
        deleteDist(filepath,'themes/dist/','themes/src/')
        if action=="deleted"
          return
      console.log 'cssminify detach',filepath,action
      grunt.config.set "cssmin.comparecss.files",#覆蓋配置,只對修改文件進行編譯
      [
        expand:true
        cwd:'themes/src/'#目錄下
        src:filepath.substring(11)#全部css文件
        dest: 'themes/dist/'#輸出到此目錄下
      ]
      return
  grunt.registerTask 'default', ['watch']
  return

這個第二部分講過了,大體原理就是檢測到修改的時候,把任務的配置改爲被修改的文件的路徑,而後結束,grunt在以後會事件冒泡,執行任務,你們看代碼領悟就好了哈哈,
刪除檢測就是檢測文件名,沒用sync庫,當進行重命名的時候,實際上會發生兩次事件,一次deleted舊文件,一次renamed新文件,因此重命名的時候,須要刪掉舊文件編譯的結果、冒泡上去,繼續生產新文件。而刪除的時候就直接刪掉舊文件編譯的結果就行
比較醜陋的是src:filepath.substring(18)這樣的句子,由於filepath的參數是全路徑,包含cwd,因此要去掉和cwd變量等長+一個'/'的長度。。。恩deleteDist這個函數也沒用正則,=w=就醬。。。

其餘的坑

就是注意coffee的函數調用,函數+空格+以逗號分隔的參數們,逗號沒了意味着函數參數結束,因此console.log "hi","123"console.log "hi" "123"顯然不等同,空格換成回車也相似

相關文章
相關標籤/搜索