在不久前我曾寫了一篇 應用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.json 和 Gruntfile.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 插件,其具體配置可以點此查看,本文就不贅述了。
共勉~
文章列表