● Grunt
( http://gruntjs.com/ )
名稱來自於 grunt
work (單調的工作),它的功能是使用設定來執行常做的動作,例如最小化
JavaScript
和 CSS
檔等。
● Grunt
在 0.3
版時提供常用的功能,設定檔使用
grunt.js。到
0.4
版時做了些調整,使用外掛的架構,設定檔為
Gruntfile.js。
● 本講義以 Windows
7 為作業系統為例,各軟體的安裝皆在
Windows
7 底下安裝,請注意使用的軟體版本,例如
NodeJS
有 32-bit
和 64-bit
之分。
◎ Windows
Command Prompt 使用 PowerShell
◎ 範例專案
shinder_maze.zip
和 shinder_circle_menu.zip (** blog 不提供專案包 zip 檔 )
● Web
server,使用 Python3
內建的簡易 web
server ( 非必要 )
安裝 Python
3 ( https://www.python.org/downloads/
)
在 Command
prompt,到專案目錄使用下式啟動
server
>
python -m http.server [埠號]
使用「Ctrl
+ C」停止 server
● 在安裝 Grunt
之前需先安裝 Git
和 NodeJS
◎ 1.
NodeJS ( http://nodejs.org/ )
– 直接從官網按「
INSTALL
」,下載 msi
檔並安裝。
◎ 2.
Git
– 安裝 Git
for Windows ( http://git-scm.com/download/win
)
– 安裝過程中請勾選「Run
Git from the Windows Command Prompt」
● 安裝 grunt-cli
>
npm install -g grunt-cli
● 安裝 Grunt
起始功能(非必要)
>
npm install -g grunt-init
◎ 安裝 Grunt
起始功能的樣版 (
grunt-init-XXX templates )
官方維護的 templates
( http://gruntjs.com/project-scaffolding#installing-templates )
以安裝 gruntplugin
template 為例:
>
git clone git://github.com/gruntjs/grunt-init-gruntplugin.git
C:\Users\shinder\.grunt-init\gruntplugin
或
>
git clone git://github.com/gruntjs/grunt-init-gruntplugin.git
$env:home\.grunt-init\gruntplugin
● 建立新目錄成為專案目錄,手動的話自行建立
package.json
和 Gruntfile.js
◎ 使用 Grunt
起始功能 (
在專案目錄 )
>
grunt-init gruntplugin
● 在專案目錄安裝
Grunt
外掛 (
產生 package.json
和 Gruntfile.js
之後 )
◎ 下式命令列將會安裝
package.json
裡所設定的外掛
>
npm install
● 手動安裝 Grunt
外掛
>
npm install grunt --save-dev
>
npm install grunt-contrib-clean --save-dev
>
npm install grunt-contrib-jshint --save-dev
>
npm install grunt-contrib-concat --save-dev
>
npm install grunt-contrib-watch --save-dev
>
npm install grunt-contrib-uglify --save-dev
>
npm install grunt-contrib-cssmin --save-dev
>
npm install grunt-contrib-htmlmin --save-dev
>
npm install grunt-contrib-connect --save-dev
>
npm install grunt-usemin --save-dev
● Gruntfile.js
的架構
◎ 1.
The "wrapper" function
◎ 2.
Project and task configuration
◎ 3.
Loading Grunt plugins and tasks
◎ 4.
Custom tasks
module.exports = function (grunt) {
grunt.initConfig({
cssmin: {
combine: {
files: {
'dist/css/style.css': ['src/css/normalize.css','src/css/main.css']
}
}
},
uglify: {
jssrcTask: {
files: {
'dist/js/main.min.js': 'src/js/*.js'
}
}
}
});
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.registerTask('default', ['cssmin', 'uglify']);
};
● 外掛原則上可以分成兩類:開發過程的工具、發佈的工具
◎ 發佈的工具,以下將介紹:
grunt-contrib-concat
grunt-contrib-uglify
grunt-contrib-cssmin
grunt-contrib-copy
grunt-usemin
◎ 開發過程的工具,以下將介紹:
grunt-contrib-jshint
grunt-contrib-connect
grunt-contrib-watch
● grunt-contrib-concat
用法範例:
concat: {
jslibTask: {
src: ['src/assets/lib/*.js'],
dest: 'dist/assets/lib/lib.js'
}
}
concat: {
basic_and_extras: {
files: {
'dist/basic.js': ['src/main.js'],
'dist/with_extras.js': ['src/main.js', 'src/extras.js']
}
}
}
● grunt-contrib-uglify
用法範例:
uglify: {
jssrcTask: {
files: {
'dist/assets/js/main.min.js': 'src/assets/js/*.js',
'dest/output.min.js': ['src/input1.js', 'src/input2.js']
}
}
}
uglify: {
options: {
mangle: {
except: ['jQuery', 'Backbone']
}
},
my_target: {
files: {
'dest/output.min.js': ['src/input.js']
}
}
}
● grunt-contrib-cssmin
用法範例:
cssmin: {
combine: {
files: {
'dist/css/style.css': ['src/css/normalize.css','src/css/main.css']
}
}
}
cssmin: {
add_banner: {
options: {
banner: '/* My minified css file */'
},
files: {
'path/to/output.css': ['path/to/**/*.css']
}
}
}
● grunt-contrib-copy
用法範例:
copy: {
task0: {
files: [{
src: 'src/shadow_maze.htm',
dest: 'dist/shadow_maze.htm'
}]
}
}
copy: {
main: {
expand: true,
cwd: 'src/', // 相對於 cwd 目錄, current working directory
src: '**',
dest: 'dest/',
flatten: true,
filter: 'isFile'
}
}
● grunt-usemin
用法範例:
◎ 1.
修改 HTML
檔
<!doctype html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta id="viewport" name="viewport" content="">
<meta name="author" content="Shinder Lin">
<title>Shinder studio : Shadow Maze</title>
<!-- build:css assets/css/style.css -->
<link rel="stylesheet" type="text/css" href="assets/css/normalize.css" />
<link rel="stylesheet" type="text/css" href="assets/css/main.css" />
<!-- endbuild -->
</head>
<body>
<div id="wrapper">
<div id="container"></div>
</div>
<!-- build:js assets/lib/lib.js -->
<script type="text/javascript" src="assets/lib/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="assets/lib/detectmobilebrowser.js"></script>
<script type="text/javascript" src="assets/lib/kinetic-v4.7.4.min.js"></script>
<script type="text/javascript" src="assets/lib/qrcode.min.js"></script>
<!-- endbuild -->
<!-- build:js assets/js/main.min.js -->
<script type="text/javascript" src="assets/js/shinder.classes.js"></script>
<script type="text/javascript" src="assets/js/shinder.main.js"></script>
<!-- endbuild -->
</body>
</html>
<html lang="zh">
<head>
<meta charset="UTF-8">
<meta id="viewport" name="viewport" content="">
<meta name="author" content="Shinder Lin">
<title>Shinder studio : Shadow Maze</title>
<!-- build:css assets/css/style.css -->
<link rel="stylesheet" type="text/css" href="assets/css/normalize.css" />
<link rel="stylesheet" type="text/css" href="assets/css/main.css" />
<!-- endbuild -->
</head>
<body>
<div id="wrapper">
<div id="container"></div>
</div>
<!-- build:js assets/lib/lib.js -->
<script type="text/javascript" src="assets/lib/jquery-1.10.2.min.js"></script>
<script type="text/javascript" src="assets/lib/detectmobilebrowser.js"></script>
<script type="text/javascript" src="assets/lib/kinetic-v4.7.4.min.js"></script>
<script type="text/javascript" src="assets/lib/qrcode.min.js"></script>
<!-- endbuild -->
<!-- build:js assets/js/main.min.js -->
<script type="text/javascript" src="assets/js/shinder.classes.js"></script>
<script type="text/javascript" src="assets/js/shinder.main.js"></script>
<!-- endbuild -->
</body>
</html>
◎ 2. Gruntfile.js 檔
module.exports = function (grunt) {
grunt.initConfig({
copy: {
task0: {
files: [
{ src: 'src/shadow_maze.htm',
dest: 'dist/shadow_maze.htm'}
]
}
},
useminPrepare: {
html: 'src/shadow_maze.htm',
options: {
dest: 'dist'
}
},
usemin: {
html: 'dist/shadow_maze.htm'
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-usemin');
grunt.registerTask('default', [
'copy',
'useminPrepare',
'usemin'
]);
};
◎ 3. pre-run 測試
◎ 4.
複製圖片目錄,並將
useminPrepare
所需的工作加入。
module.exports = function (grunt) {
grunt.initConfig({
copy: {
task0: {
files: [
{ src: 'src/shadow_maze.htm',
dest: 'dist/shadow_maze.htm'},
{ expand: true,
cwd: 'src/',
src: ['assets/images/**'],
dest: 'dist'}
]
}
},
useminPrepare: {
html: 'src/shadow_maze.htm',
options: {
dest: 'dist'
}
},
usemin: {
html: 'dist/shadow_maze.htm'
}
});
grunt.loadNpmTasks('grunt-contrib-copy');
grunt.loadNpmTasks('grunt-usemin');
grunt.loadNpmTasks('grunt-contrib-concat');
grunt.loadNpmTasks('grunt-contrib-uglify');
grunt.loadNpmTasks('grunt-contrib-cssmin');
grunt.registerTask('default', [
'copy',
'useminPrepare',
'concat',
'uglify',
'cssmin',
'usemin'
]);
};
● ●
jshint: {
options: {
curly: true, // if, for 單一 statement 也要有大括號包裹
eqeqeq: true, // 使用 === 和 !==
immed: true, // 暱名函式即時呼叫檢查, 需 ( ) 包裹
latedef: true, // 變數在宣告之前不能使用
newcap: true, // 建構函式的第一個字母需大寫
noarg: true, // 禁用 arguments.caller 和 arguments.callee
sub: true, // 允許使用 obj['name'] 中括號表示法 (不顯示警示)
undef: true, // 禁用未宣告的變數
unused: true, // 提示沒有使用的變數
boss: true, // 條件式可以使用設定 =
eqnull: true, // 允許使用 ==null
browser: true // 在瀏覽器底下使用 (可以使用瀏覽器裡的預設物件)
},
jsTest: {
src: ['src/assets/js/*.js']
}
}
● grunt-contrib-connect
用法範例:
connect: {
server: {
options: {
port: 9001,
base: 'src',
keepalive: true
}
}
}
◎ 使用「Ctrl
+ C」停止 server
◎ 使用多個伺服器時,應使用多個
command
prompt 視窗執行。
connect: {
site1: {
options: {
port: 9002,
base: 'src',
keepalive: true
}
},
site2: {
options: {
port: 9003,
base: 'dist',
keepalive: true
}
}
}
● grunt-contrib-watch
用法範例:
watch: {
scripts: {
files: ['src/assets/js/*.js'],
tasks: ['jshint']
}
}
watch: {
gruntfile: {
files: 'Gruntfile.js',
tasks: ['jshint:gruntfile'],
},
src: {
files: ['lib/*.js', 'css/**/*.scss', '!lib/dontwatch.js'],
tasks: ['default'],
},
test: {
files: '<%= jshint.test.src %>',
tasks: ['jshint:test', 'qunit'],
},
}
◎ 使用
grunt-contrib-watch
的 LiveReload
watch: {
options: {
livereload: true
},
scripts: {
files: ['src/js/main.js', 'src/css/style.css'],
tasks: ['jshint']
}
}
◎ 在 HTML
檔掛 livereload.js
<script src="http://localhost:35729/livereload.js"></script>
◎ 也可以使用瀏覽器的外掛,但使用
livereload.js
比較不會發生連接出狀況。
沒有留言:
張貼留言