文章出處

在不久前我曾寫了一篇 應用r.js來優化你的前端 的文章,為大家介紹了r.js這個實用工具,它可以很好地壓縮、合并前端文件并打包整個項目。但是如果將r.js放到項目中,我們不得不顧及到一個問題——項目每維護一次,就需要維護的人員輸入一次rjs運行口令重新打包項目,自然是非常繁瑣的事情。另外如果我們的項目用sass來寫樣式,可能還得外開一個koala。如果我們能讓項目自己處理自己的所有事宜,那一切就美好多了。

針對上述問題,今天我們就利用更為大眾的工具——Grunt,來自動化地處理前端事務(其實rjs也是使用了Grunt的concat和uglify等插件)。

我們依舊使用一個非常簡單的、名為before的項目(你可以在我的Github下載這個案例)來作為示例,它是一個很純凈的項目,還沒有使用任何前端工具對其進行操作:

你可以試著運行根目錄下的index.html文件,它會顯示一張幻燈片。

接下來我們將在before項目上使用Grunt自動化前端事務。

操作需求

由于Grunt是運行與node上的,故要求你的電腦安裝了nodeJS(點我下載);

由于我們這邊使用了sass來寫樣式,故要求你的電腦安裝了Ruby(注意Mac是默認安裝有Ruby的,如果是Windows或其它系統請點此下載安裝)。

安裝時建議把三個可以勾選的選項都勾上(特別要勾選上第二個,這樣才會添加環境變量),安裝后點擊 “所有程序” -  “Ruby.13...” -  “start command prompt with Ruby”,打開Ruby命令行界面并輸入指令:

gem install sass

注意該指令必須要在FQ的情況下才執行,不然可能會導致無法安裝sass的錯誤:

不過有時候系統可能會提示這個錯誤信息:

SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed (https://bb-m.rubygems.org/gems/multi_json-1.3.2.gem)

解決方法是在這里下載證書(http://curl.haxx.se/ca/cacert.pem),比如下載到 D:/ruby/cacert.pem, 然后再環境變量里新建一個SSL_CERT_FILE這個環境變量,并把變量值設為這個文件路徑即可:

 

另外,我們后續編譯sass的時候,若.scss文件中存在中文注釋,Ruby可能會因為識別不了中文編碼而導致出錯。不過解決方法很簡單,點擊此處查看

安裝GRUNT CLI

我們打開 Node.js command prompt 進入node命令行界面:

在命令行界面輸入以下代碼并回車運行,此舉是安裝Grunt全局命令行,從而我們可以在電腦任何位置調用grunt命令語句:

npm install -g grunt-cli

Grunt配置

Grunt的入門其實可以參考官方入門,雖然這篇官方指引寫的很爛,卻也告訴我們,Grunt配置離不開兩個文件—— package.jsonGruntfile.js ,我們一般都把它們放置在項目根目錄上 。

其中 package.json 作用是記錄項目的名稱(隨便起個名字就行)、版本號(隨便起個數字串就行)和插件依賴,創建package.json完全不用手動,我們只需要把node命令行定位到項目下(假設我們把上述的before項目放在E盤),然后輸入以下指令并回車執行,便會在項目根目錄自動創建一個初始化的 package.json 文件:

npm init

回車后node會問你若干個問題,包括項目名啊版本號啊什么有的沒的,你有心情可以寫一寫,沒心情就一路按回車下來即可:

這時你會發現根目錄下就這樣多了個叫package.json的文件:

里面有node幫我們預先定義好的json代碼。不過我各人并不喜歡使用 npm init 這種婆媽的形式來自動生成package.json,還不如自己手動創建一個package.json,并輸入簡潔的代碼:

{
  "name": "before",
  "version": "1.0.0"
}

是的,初始化咱只要就這么倆行即可,其實我甚至希望能簡短到只有 {  } 即可。可惜 name 和 version 對于 package.json 來說是非常重要的倆個屬性,缺一不可(可以查看這里了解更多package.json屬性的作用)

安裝插件

Grunt只是一個載體,實際要用起來得使用各種五花八門的grunt插件(有點類似在Sublime上我們可以安裝并使用各種sb插件)。

而我們的before項目需要運用到下面幾個插件:

grunt —— 這個不用說了,就是Grunt它自己本身;

grunt-contrib-uglify —— 作用是壓縮項目js文件;

grunt-contrib-sass —— 作用是編譯項目中的sass為(壓縮版的)css文件;

grunt-contrib-watch —— 作用是實現我們一開始需求的“自動化”!是最重要的一個插件之一!它會監聽需要處理的文件的變動,一旦有變動就會自動執行相應處理。但是它有一個問題,就是每當監聽到一處變動時,就會大費周章地把所有被監聽的文件都處理一遍;

grunt-newer —— 作用是處理上方watch的毛病,讓watch在監聽到某個文件變動時,僅僅對變動的文件進行事務處理。

然而在node中,安裝grunt插件的命令為:

npm install <插件名> --save-dev

其中后面的 “--save-dev” 表示保存為依賴,即在安裝好插件后,會將此插件依賴寫入package.json文件中(記得我們前面說到package.json的作用之一是記錄項目的插件依賴么)。

于是我們在項目的根目錄下分別運行下述命令安裝插件:

npm install grunt --save-dev

npm install grunt-contrib-uglify --save-dev

npm install grunt-contrib-sass --save-dev

npm install grunt-contrib-watch --save-dev

運行時可能會提示如下的警告:

這是因為咱在package.json里沒有寫一些description等婆媽的東西,故這里的WARN不痛不癢直接無視它即可。

插件安裝好后會發現項目根目錄上多了個叫“node_modules”的文件夾,是用來存放我們安裝好的插件的。另外我們打開package.json,會發現它已經自動加入了插件依賴信息:

配置Gruntfile.js文件

開始我們就提到grunt有2個不可缺少的文件 —— package.json 和 Gruntfile.js 文件,package.json咱已輕松搞定,下面新建一個Gruntfile.js 文件并輸入以下代碼:

module.exports = function(grunt) {
  grunt.initConfig({ 
    pkg: grunt.file.readJSON('package.json'),
    //上面是固定好的,不用管它,照搬即可。
    //下面是各插件事務的配置,順序不分先后
    sass: { // grunt-contrib-sass的事務定義
      tocss: {
        options: {       
          style: 'compressed', //以壓縮模式編譯css,這樣咱們也沒必要使用grunt-contrib-cssmin插件了
          sourcemap:'none'  //設置不要配套輸出map文件
        },
        files: [{
            expand:true,
            cwd:'css',//css目錄下
            src:'**/*.scss',//所有css文件
            dest: 'css',//輸出到此目錄下
            ext: '.css'
        }]
      }
    },
    uglify: {  // grunt-contrib-uglify的事務定義
      compressjs: {
        files: [{
            expand:true,
            cwd:'js',//js目錄下
            src:'**/*.js',//所有js文件
            dest: 'output/js'//輸出到此目錄下
        }]
      }
    },
    watch: {  // grunt-contrib-watch的事務定義
      all: {
        files: ['css/**/*.scss','js/**/*.js'],
        tasks: ['newer:sass','newer:uglify']
      }
    }
  });
  //grunt.loadNpmTasks() 是告訴Grunt,咱們要使用哪些插件,順序不分先后
  grunt.loadNpmTasks('grunt-contrib-watch');
  grunt.loadNpmTasks('grunt-contrib-uglify');
  grunt.loadNpmTasks('grunt-contrib-sass');
  grunt.loadNpmTasks('grunt-newer');
  //grunt.registerTask('default', [])是告訴Grunt,我們在node命令行輸入grunt指令后要執行哪些事務
  grunt.registerTask('default', ['newer:sass','newer:uglify','watch']);  //注意 "newer:XXX"是插件grunt-newer的事件定義,表示對冒號后面的事務生效
};

Gruntfile.js的配置或許算是配置Grunt的一個難點吧,它的作用是告訴Grunt要使用哪些插件(安裝了不代表一定要用對吧,當然要用的話一定得安裝)、每個插件又要進行怎樣的事務操作。

其實Gruntfile.js最最簡單的初始化框架是這樣的:

module.exports = function(grunt) {
  grunt.initConfig({ 
    pkg: grunt.file.readJSON('package.json'),

    插件事務名稱: { 
      ........//事務定義
    }
  });
  //grunt.loadNpmTasks() 是告訴Grunt,咱們要使用哪些插件,順序不分先后
  grunt.loadNpmTasks('插件名');

  //grunt.registerTask('default', [])是告訴Grunt,我們在node命令行輸入grunt指令后要執行哪些事務
  grunt.registerTask('default', ['插件事務名稱']);  
};

稍微推敲下,很容易理解代碼的含義。如若了解更靈活、復雜的Gruntfile.js配置,可以點此查看指引

一切都搗鼓好后,我們可以直接在node命令行(依舊定位在根目錄下哦,其實可以不用再嘮嗑了)輸入

grunt

回車執行后便進入自動化執行狀態,只要有js或者scss文件變動,變動的文件就會重新被壓縮或編譯:

像本章的例子是使用了sass來寫樣式,如果你只寫原生的css,又希望能壓縮樣式文件,那么可以使用 grunt-contrib-cssmin 插件,其具體配置可以點此查看,本文就不贅述了。

共勉~

donate


文章列表




Avast logo

Avast 防毒軟體已檢查此封電子郵件的病毒。
www.avast.com


arrow
arrow
    全站熱搜
    創作者介紹
    創作者 大師兄 的頭像
    大師兄

    IT工程師數位筆記本

    大師兄 發表在 痞客邦 留言(0) 人氣()