Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
Physical Address
304 North Cardinal St.
Dorchester Center, MA 02124
這次公司的網站更新,同時又接觸了新技能:Grunt。
以前在執行靜態檔案最佳化,都是透過快取外掛 W3 Total Cache 協助執行,但是有時最小化之後會出錯 (可能在最小化 JavaScript 時,變數或函式互相干擾),因此想要自己可以控制最小化的任務。這次執行最小化後,將原本的 CSS 檔案縮小了 33% (70 kb → 47kb),JavaScript 檔案也都縮小了 30-50%。
如同官方網站的次標題:the JavaScript Task Runner,Grunt 是一款奠基於 Node.js 之上的任務管理套件。在使用 Grunt 前,需要先能夠從 NPM 中安裝套件。關於 NPM 的使用方法,可以參考這篇文章,這裡就不再贅述。
內容目錄
在開始使用 Grunt 以前,需要先透過 NPM 安裝 Grunt。打開終端機/命令提示字元,並輸入 NPM 的安裝指令,在全域安裝 Grunt CLI。
npm install -g grunt-cli
接著在你的專案資料夾中,編輯你的 package.json 檔案,加入以下相依套件:
{ "name": "my-project-name", "version": "0.1.0", "devDependencies": { "grunt": "~0.4.5", "grunt-contrib-jshint": "~0.10.0", "grunt-contrib-nodeunit": "~0.4.1", "grunt-contrib-uglify": "~0.5.0" } }
執行 npm install
指令,將相依套件安裝至專案資料夾中。
module.exports = function(grunt) { // Project configuration. grunt.initConfig( { pkg: grunt.file.readJSON( 'package.json' ), } ); };
grunt.file.readJSON('package.json')
這項指令是用以讀取 package.json 中的套件中繼資料。
接著加入任務名稱,並載入任務套件。以這次的範例為例,我想要最小化我的靜態話資源 (CSS 與 JavaScript 檔案),因此我使用了 terser、autoprefixer、sass 與 cssmin。
module.exports = function ( grunt ) { // Project configuration. grunt.initConfig( { pkg: grunt.file.readJSON( 'package.json' ), } ); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks( 'grunt-terser' ); grunt.loadNpmTasks( 'grunt-autoprefixer' ); grunt.loadNpmTasks( 'grunt-contrib-sass' ); grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); };
同時記得在終端機/命令提示字元中執行 NPM 指令,安裝上述套件。
npm install --save-dev grunt-terser grunt-autoprefixer grunt-contrib-sass grunt-contrib-cssmin
Terser 是一款最小化 JavaScript 檔案的套件,在 Gruntfile.js 中加入選項與組態:
module.exports = function ( grunt ) { // Project configuration. grunt.initConfig( { pkg: grunt.file.readJSON( 'package.json' ), terser: { options: { mangle: { toplevel: true, }, }, build: { files: [ { expand: true, src: [ 'js/*.js', '!js/*.min.js' ], ext: '.min.js', }, ], }, }, } ); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks( 'grunt-terser' ); grunt.loadNpmTasks( 'grunt-autoprefixer' ); grunt.loadNpmTasks( 'grunt-contrib-sass' ); grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); // Default task(s). grunt.registerTask( 'default', [ 'terser', 'sass', 'autoprefixer', 'cssmin', ] ); };
mangle
是用來將 JavaScript 中的變數與屬性改以單個字母表現,例如 let findMyCookie
會被壓縮為 let f
。這種作法可以有效的減少 JavaScript 的檔案大小。
toplevel
則是讓 mangle
的適用範圍只及於最上層的變數與函式名稱。
build
中則是指定要適用的檔案範圍,expand: true
會去自動偵測路徑,js/*.js
代表要包含 js 這個資料夾中的所有副檔名為 js 的檔案,而 !js/*.min.js
代表不要再去壓縮是壓縮檔的檔案,例如已經壓縮過的第三方套件。ext
是檔案匯出後使用的副檔名。
接著加入其他任務的組態:
module.exports = function ( grunt ) { // Project configuration. grunt.initConfig( { pkg: grunt.file.readJSON( 'package.json' ), terser: { options: { mangle: { toplevel: true, }, }, build: { files: [ { expand: true, src: [ 'js/*.js', '!js/*.min.js' ], ext: '.min.js', }, ], }, }, sass: { dist: { files: { 'style.css': 'sass/style.scss', }, }, }, autoprefixer: { your_target: { files: [ { expand: true, src: [ 'style.css', 'assets/css/*.css', '!**/*.min.css', '!assets/css/*.min.css', ], ext: '.min.css', }, ], }, }, cssmin: { targets: { files: [ { expand: true, src: [ 'style.css', 'assets/css/*.css', '!**/*.min.css', '!assets/css/*.min.css', ], ext: '.min.css', }, ], }, }, } ); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks( 'grunt-terser' ); grunt.loadNpmTasks( 'grunt-autoprefixer' ); grunt.loadNpmTasks( 'grunt-contrib-sass' ); grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); };
最後再利用 grunt.registerTask();
安排任務順序:
module.exports = function ( grunt ) { // Project configuration. grunt.initConfig( { pkg: grunt.file.readJSON( 'package.json' ), terser: { options: { mangle: { toplevel: true, }, }, build: { files: [ { expand: true, src: [ 'js/*.js', '!js/*.min.js' ], ext: '.min.js', }, ], }, }, sass: { dist: { files: { 'style.css': 'sass/style.scss', }, }, }, autoprefixer: { options: {}, your_target: { files: [ { expand: true, src: [ 'style.css', 'assets/css/*.css', '!**/*.min.css', '!assets/css/*.min.css', ], ext: '.min.css', }, ], }, }, cssmin: { options: {}, targets: { files: [ { expand: true, src: [ 'style.css', 'assets/css/*.css', '!**/*.min.css', '!assets/css/*.min.css', ], ext: '.min.css', }, ], }, }, } ); // Load the plugin that provides the "uglify" task. grunt.loadNpmTasks( 'grunt-terser' ); grunt.loadNpmTasks( 'grunt-autoprefixer' ); grunt.loadNpmTasks( 'grunt-contrib-sass' ); grunt.loadNpmTasks( 'grunt-contrib-cssmin' ); // Default task(s). grunt.registerTask( 'default', [ 'terser', 'sass', 'autoprefixer', 'cssmin', ] ); };
最後,只要在終端機/命令提示字元中,執行 grunt
指令,接下來就會由 Grunt 執行剩下的任務工序。
Grunt 在 Developer Roadmap 中並沒有被提到,但其中有提到類似概念的 Gulp。
透過 Grunt 的方法,可以將本來最小化 JavaScript 與 CSS 的工作變得更輕鬆。但是如果要真的將整個流程更有組織、更全面,看樣子還是需要多點一些 Webpack 的技能。