隨著網頁前端的技術發展,原始碼編譯、圖片最佳化、壓縮合併、內容代換、語法檢查、程式測試等等工作不斷地在我們的開發流程中出現,但是一樣一樣執行又要搭配不同的狀況來組合,實在讓人感到麻煩,幸好前端的工具也發展得很快,已經有成熟的解決方案可以來處理這些過程,Grunt就是這樣的一個方便的任務執行框架,讓你可以自動化執行這些繁瑣的開發工作。
Grunt的使用方式,看網站上的教學跟示範就很容易理解了。
這裡大略提及一些地方,首先要特別注意的是安裝,在系統上安裝的套件是grunt-cli,使用npm來安裝:
npm install -g grunt-cli |
而開發專案裡面,用npm init準備好package.json後則是安裝grunt,這才是實際負責任務執行的程式:
npm install grunt --save-dev |
如此一來,grunt跟grunt-cli分開,當使用grunt指令時,其實是呼叫系統裡的grunt-cli,它再使用專案裡安裝的grunt程式來執行Gruntfile裡的任務,達到不同的專案可以使用不同版本的grunt來執行任務的目的。
由於 Grunt 的 Plugin 實在五花八門難以盡數,在 nodeJS 的 npm 底下長成了繁盛的生態系,光是Grunt自行維護的就有二十多種,其中常用的介紹如下:
grunt-contrib-sass:把SASS編譯成CSS
當然,系統裡面要先裝好Ruby的Sass,不然就改用node版本的grunt-sass,然後Gruntfile的規則也十分簡單。
module.exports = function(grunt) { grunt.initConfig({ sass: { dist: { files: { 'style.css': 'style.scss' } } } }); grunt.loadNpmTasks('grunt-contrib-sass'); grunt.registerTask('default', ['sass']); }; |
指定要轉換的來源跟目的檔名即可。
grunt-contrib-coffee:把CoffeeScript編譯成Javascript
module.exports = function(grunt) { grunt.initConfig({ coffee: { compile: { files: { 'script.js': 'script.coffee' } } } }); grunt.loadNpmTasks('grunt-contrib-coffee'); grunt.registerTask('default', ['coffee']); }; |
除了直接列舉各個要處理的檔名外,也可以動態指定處理的套用範圍。
grunt-contrib-imagemin:減少PNG與JPG圖片大小
module.exports = function(grunt) { grunt.initConfig({ imagemin: { dist: { options: { optimizationLevel: 3 }, files: { 'texture.png': 'texture.png' } } } }); grunt.loadNpmTasks('grunt-contrib-imagemin'); grunt.registerTask('build', ['imagemin']); }; |
如果要處理 SVG 檔案的話,也有 grunt-svgmin 可以用。
grunt-contrib-cssmin:減少CSS文件大小
module.exports = function(grunt) { grunt.initConfig({ cssmin: { minify: { files: { 'style.css': 'style.css' } } } }); grunt.loadNpmTasks('grunt-contrib-cssmin'); grunt.registerTask('build', ['cssmin']); }; |
另外要壓縮Javascript的話,也有 grunt-contrib-uglify 可以使用。
grunt-contrib-connect:使用connect建立Web Server
module.exports = function(grunt) { grunt.initConfig({ connect: { server: { options: { hostname: '*' } } } }); grunt.loadNpmTasks('grunt-contrib-connect'); grunt.registerTask('default', ['connect']); }; |
預設的port是8000,hostname是localhost,改成這樣是為了讓其他機器也能連上。
grunt-contrib-watch:監控檔案在更動時執行任務,已經內建livereload支援
module.exports = function(grunt) { grunt.initConfig({ watch: { sass: { files: ['*.scss'], tasks: ['sass'], options: { livereload: true } }, livereload: { files: ['*.html'], options: { livereload: true } } } }); grunt.loadNpmTasks('grunt-contrib-watch'); grunt.registerTask('default', ['watch']); }; |
如果想要同時執行SCSS與CoffeeScript的編譯工作,還有 grunt-concurrent 可以用上。
將以上的任務通通加在一起,執行grunt會先讓connect跑起來,再watch檔案更動來livereload,打完收工再grunt build就搞定啦。
grunt.registerTask('default', ['connect', 'watch']); grunt.registerTask('build', ['imagemin', 'cssmin', 'uglify']); |
除了這些用法外,值得一提的是,可以搭配Travis CI等服務來執行grunt的測試任務,在.travis.yml裡面加上:
language: node_js node_js: - "0.10" |
然後package.json裡面加上node test的設定:
"scripts": { "test": "grunt test" }, |
很簡單地就完成了。
至於 grunt-init 這個指令就可以不必深究了,因為開發者們預計將把 Project Scaffolding 交給 Yeoman 取代,Yeoman 在初始化專案時更會內建不少常用的Grunt任務,可以省下更多功夫。
最後要說的是,其實以上介紹的用法,根據開發團隊的計畫,很可能在 Grunt 0.5 出現之後會再大改過,期待 node-task 推出的那時能再次革新整個網站開發工具鍊。
過往今昔…
- SuperTuxKart 0.7.1與台灣中文語系翻譯 - 2011
wow~
push~