“1. 我为何使用grunt; 2. 我为什么放弃grunt转投gulp; 3. 我为什么放弃gulp与grunt,转投npm scripts; 4. 我为什么放弃前端” —— 司徒正美javascript
前端(段子)界的发展日新月异,总感受随时会跟不上技术潮流(其实我已经被甩开了一条街,so sadcss
选择在这样一个时机发布一篇 gulp 教程并非个人初衷,第一次用 gulp 是在一年前,而这篇帖子在草稿箱里躺了一个多月,再不发出来讲不定就过期了。html
当我在用 gulp 时我用它作什么?前端
总之,gulp是前端开发过程当中对代码进行自动化构建的利器。它不只能对资源进行优化,并且在开发过程当中可以经过配置自动完成不少重复的任务,让咱们能够专一于代码,提升工做效率。java
然而因为众所周知的缘由,国内到 npm 服务器的链接很不稳定,若是你有V了个PN大可没必要担忧,也可经过设置 npm 代理服务器的方式访问:node
1
2
3
4
|
推荐一个简单的方案:使用淘宝 npm 镜像 jquery
“这是一个完整 npmjs.org 镜像,你能够用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽可能与官方服务同步。” —— 淘宝团队点赞npm
1
2
|
npm config set registry="https://registry.npm.taobao.org"
npm config set disturl https://npm.taobao.org/dist
|
准备工做: 安装 node.js (推荐 TLS 版),并重启系统。json
1
|
npm install gulp -g
|
└── src/ 源码目录gulp
├── build/ .html 组件
├── sass/ .scss .sass 文件
├── css/ .css 文件
├── js/ .js 文件
└── img/ 图片
└── dist/ 输出目录
└── package.json
└── gulpfile.js
能够在项目上使用 npm init 配置,推荐直接新建并写入初始内容:
1
2
3
4
5
6
|
{
"name"
:
"gulp-build"
,
"version"
:
"1.0.0"
,
"description"
:
"Gulp.js"
,
"private"
:
true
}
|
对于完整的 package.json (好比别人的开源项目), 只需对整个项目执行 npm install 便可安装 package.json 文件中声明的全部插件模块。
1
|
npm install gulp --save-dev
|
—save-dev 这个参数会将插件信息自动更新到 package.json 里,其中的 devDependencies 属性会随插件依赖的安装卸载而改变。
PS. Windows 7及以上,按住 Shift 再右键,选择在此处打开命令窗口。免去 cd 命令定位目录的烦恼。
PS.可与上一步同时进行
1
|
npm install gulp del gulp-cached gulp-uglify gulp-rename gulp-concat gulp-notify gulp-filter gulp-jshint gulp-ruby-sass gulp-rev-append gulp-cssnano gulp-replace gulp-imagemin browser-sync gulp-font-spider gulp-file-include gulp-autoprefixer --save-dev
|
插件将在配置文件里介绍,更多用法请参见相应的 GitHub 主页,或者直接戳这里: https://www.npmjs.com/package/
以上两个安装操做将会在项目目录下生成 node_modules 文件夹,相应的插件都在这里。
Windows 用户请注意,此文件夹可能 没法删除 没法复制 没法移动,会出现诸如“包含名称过长且没法放入回收站”,“源文件名长度大于文件系统支持的长度。请尝试将其移动到具备较短路径名称的位置” 等等问题。使用一个简单的方式便可删除,使用 WinRAR “添加到压缩文件”,勾选压缩选项里的 “压缩后删除源文件” ,肯定以后便可删除。
别看我,看它:http://www.gulpjs.com.cn/docs/api/
1
2
3
4
5
6
7
8
9
10
|
<!
DOCTYPE
html>
<
html
>
<
head
>
<
meta
charset
=
"utf-8"
/>
<
title
>嘿嘿嘿</
title
>
<
link
href
=
"css/m.base.css?rev=@@hash"
rel
=
"stylesheet"
type
=
"text/css"
/>
<
link
href
=
"css/jquery.fullPage.css?rev=@@hash"
rel
=
"stylesheet"
type
=
"text/css"
/>
<
link
href
=
"css/mobile.css?rev=@@hash"
rel
=
"stylesheet"
type
=
"text/css"
/>
</
head
>
<
body
>
|
1
2
3
4
5
|
<!-- common js -->
<
script
type
=
"text/javascript"
src
=
"js/jquery-2.1.4.min.js"
></
script
>
<
script
type
=
"text/javascript"
src
=
"js/main.js?rev=@@hash"
></
script
>
</
body
>
</
html
>
|
1
2
3
4
5
|
@@include('build/header.html')
<
div
class
=
"wrap"
>内容</
div
>
@@include('build/footer.html')
|
代码中, ?rev=@@hash 是 gulp-rev-append 插件的指纹标识
@@include(‘build/header.html’) 能够插入 html 文件,还能够配合参数生成独立的头部。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
|
/*!
* gulp
* $ npm install gulp gulp-ruby-sass gulp-cached gulp-uglify gulp-rename gulp-concat gulp-notify gulp-filter gulp-jshint gulp-rev-append gulp-cssnano gulp-imagemin browser-sync gulp-file-include gulp-autoprefixer del --save-dev
*/
// Load plugins
var
gulp = require(
'gulp'
),
// 必须先引入gulp插件
del = require(
'del'
),
// 文件删除
sass = require(
'gulp-ruby-sass'
),
// sass 编译
cached = require(
'gulp-cached'
),
// 缓存当前任务中的文件,只让已修改的文件经过管道
uglify = require(
'gulp-uglify'
),
// js 压缩
rename = require(
'gulp-rename'
),
// 重命名
concat = require(
'gulp-concat'
),
// 合并文件
notify = require(
'gulp-notify'
),
// 至关于 console.log()
filter = require(
'gulp-filter'
),
// 过滤筛选指定文件
jshint = require(
'gulp-jshint'
),
// js 语法校验
rev = require(
'gulp-rev-append'
),
// 插入文件指纹(MD5)
cssnano = require(
'gulp-cssnano'
),
// CSS 压缩
imagemin = require(
'gulp-imagemin'
),
// 图片优化
browserSync = require(
'browser-sync'
),
// 保存自动刷新
fileinclude = require(
'gulp-file-include'
),
// 能够 include html 文件
autoprefixer = require(
'gulp-autoprefixer'
);
// 添加 CSS 浏览器前缀
// sass
gulp.task(
'sass'
,
function
() {
return
sass(
'src/sass/**/*.scss'
, {style:
'expanded'
})
// 传入 sass 目录及子目录下的全部 .scss 文件生成文件流经过管道并设置输出格式
.pipe(cached(
'sass'
))
// 缓存传入文件,只让已修改的文件经过管道(第一次执行是所有经过,由于尚未记录缓存)
.pipe(autoprefixer(
'last 6 version'
))
// 添加 CSS 浏览器前缀,兼容最新的5个版本
.pipe(gulp.dest(
'dist/css'
))
// 输出到 dist/css 目录下(不影响此时管道里的文件流)
.pipe(rename({suffix:
'.min'
}))
// 对管道里的文件流添加 .min 的重命名
.pipe(cssnano())
// 压缩 CSS
.pipe(gulp.dest(
'dist/css'
))
// 输出到 dist/css 目录下,此时每一个文件都有压缩(*.min.css)和未压缩(*.css)两个版本
});
// css (拷贝 *.min.css,常规 CSS 则输出压缩与未压缩两个版本)
gulp.task(
'css'
,
function
() {
return
gulp.src(
'src/css/**/*.css'
)
.pipe(cached(
'css'
))
.pipe(gulp.dest(
'dist/css'
))
// 把管道里的全部文件输出到 dist/css 目录
.pipe(filter([
'**/*'
,
'!**/*.min.css'
]))
// 筛选出管道中的非 *.min.css 文件
.pipe(autoprefixer(
'last 6 version'
))
.pipe(gulp.dest(
'dist/css'
))
// 把处理过的 css 输出到 dist/css 目录
.pipe(rename({suffix:
'.min'
}))
.pipe(cssnano())
.pipe(gulp.dest(
'dist/css'
))
});
// styleReload (结合 watch 任务,无刷新CSS注入)
gulp.task(
'styleReload'
, [
'sass'
,
'css'
],
function
() {
return
gulp.src([
'dist/css/**/*.css'
])
.pipe(cached(
'style'
))
.pipe(browserSync.reload({stream:
true
}));
// 使用无刷新 browserSync 注入 CSS
});
// script (拷贝 *.min.js,常规 js 则输出压缩与未压缩两个版本)
gulp.task(
'script'
,
function
() {
return
gulp.src([
'src/js/**/*.js'
])
.pipe(cached(
'script'
))
.pipe(gulp.dest(
'dist/js'
))
.pipe(filter([
'**/*'
,
'!**/*.min.js'
]))
// 筛选出管道中的非 *.min.js 文件
// .pipe(jshint('.jshintrc')) // js的校验与合并,根据须要开启
// .pipe(jshint.reporter('default'))
// .pipe(concat('main.js'))
// .pipe(gulp.dest('dist/js'))
.pipe(rename({suffix:
'.min'
}))
.pipe(uglify())
.pipe(gulp.dest(
'dist/js'
))
});
// image
gulp.task(
'image'
,
function
() {
return
gulp.src(
'src/img/**/*.{jpg,jpeg,png,gif}'
)
.pipe(cached(
'image'
))
.pipe(imagemin({optimizationLevel: 3, progressive:
true
, interlaced:
true
, multipass:
true
}))
// 取值范围:0-7(优化等级),是否无损压缩jpg图片,是否隔行扫描gif进行渲染,是否屡次优化svg直到彻底优化
.pipe(gulp.dest(
'dist/img'
))
});
// html 编译 html 文件并复制字体
gulp.task(
'html'
,
function
() {
return
gulp.src(
'src/*.html'
)
.pipe(fileinclude())
// include html
.pipe(rev())
// 生成并插入 MD5
.pipe(gulp.dest(
'dist/'
))
});
// clean 清空 dist 目录
gulp.task(
'clean'
,
function
() {
return
del(
'dist/**/*'
);
});
// build,关连执行所有编译任务
gulp.task(
'build'
, [
'sass'
,
'css'
,
'script'
,
'image'
],
function
() {
gulp.start(
'html'
);
});
// default 默认任务,依赖清空任务
gulp.task(
'default'
, [
'clean'
],
function
() {
gulp.start(
'build'
);
});
// watch 开启本地服务器并监听
gulp.task(
'watch'
,
function
() {
browserSync.init({
server: {
baseDir:
'dist'
// 在 dist 目录下启动本地服务器环境,自动启动默认浏览器
}
});
// 监控 SASS 文件,有变更则执行CSS注入
gulp.watch(
'src/sass/**/*.scss'
, [
'styleReload'
]);
// 监控 CSS 文件,有变更则执行CSS注入
gulp.watch(
'src/css/**/*.css'
, [
'styleReload'
]);
// 监控 js 文件,有变更则执行 script 任务
gulp.watch(
'src/js/**/*.js'
, [
'script'
]);
// 监控图片文件,有变更则执行 image 任务
gulp.watch(
'src/img/**/*'
, [
'image'
]);
// 监控 html 文件,有变更则执行 html 任务
gulp.watch(
'src/**/*.html'
, [
'html'
]);
// 监控 dist 目录下除 css 目录之外的变更(如js,图片等),则自动刷新页面
gulp.watch([
'dist/**/*'
,
'!dist/css/**/*'
]).on(
'change'
, browserSync.reload);
});
|
1
|
gulp taskname // 如 gulp sass,不指定 taskname 则默认执行 default 任务
|
赶在四年一遇的2月29号,匆忙发表。
PS. 感谢 @合金大圣 订正错误。 16.07.04
更新 Gulp 系列教程,请戳下面