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 的技能。