“1. 我为什么使用grunt; 2. 我为何放弃grunt转投gulp; 3. 我为何放弃gulp与grunt,转投npm scripts; 4. 我为何放弃前端” —— 司徒正美

前端(段子)界的发展突飞猛进,总感觉随时会跟不上技术潮流(其实我已经被甩开了一条街,so sad

选择在这样一个时机发布一篇 gulp 教程并不是我的初衷,第一次用 gulp 是在一年前,而这篇帖子在草稿箱里躺了一个多月,再不发出来说不定就过时了。

当我在用 gulp 时我用它做什么?

  1. 编译 sass
  2. 合并优化压缩 css
  3. 校验压缩 js
  4. 优化图片
  5. 添加文件指纹(md5)
  6. 组件化头部底部(include html)
  7. 实时自动刷新…

总之,gulp是前端开发过程中对代码进行自动化构建的利器。它不仅能对资源进行优化,而且在开发过程中能够通过配置自动完成很多重复的任务,让我们可以专注于代码,提高工作效率。

然而由于众所周知的原因,国内到 npm 服务器的连接很不稳定,如果你有V了个PN大可不必担心,也可通过设置 npm 代理服务器的方式访问:

设置与删除 npm 代理
1
2
3
4
// 设置代理
npm config set proxy="http://127.0.0.1:1080"
// 删除代理
npm config delete proxy

推荐一个简单的方案:使用淘宝 npm 镜像

“这是一个完整 npmjs.org 镜像,你可以用此代替官方版本(只读),同步频率目前为 10分钟 一次以保证尽量与官方服务同步。” —— 淘宝团队点赞

更换 npm 为淘宝源
1
2
npm config set registry="https://registry.npm.taobao.org"
npm config set disturl https://npm.taobao.org/dist

接下来开始 gulp 教程:

准备工作: 安装 node.js (推荐 TLS 版),并重启系统。

1. 全局安装 gulp

全局安装gulp
1
npm install gulp -g

2. 目录结构:

└── src/            源码目录

├── build/   .html 组件
├── sass/     .scss .sass 文件
├── css/       .css 文件
├── js/         .js 文件
└── img/     图片

└── dist/        输出目录
└── package.json
└── gulpfile.js

3. 关于 package.json

可以在项目上使用 npm init 配置,推荐直接新建并写入初始内容:

package.json
1
2
3
4
5
6
{
  "name": "gulp-build",
  "version": "1.0.0",
  "description": "Gulp.js",
  "private": true
}

对于完整的 package.json (比如别人的开源项目), 只需对整个项目执行 npm install 即可安装 package.json 文件中声明的所有插件模块。

4. 给项目目录安装 gulp

给项目目录安装gulp
1
npm install gulp --save-dev

—save-dev 这个参数会将插件信息自动更新到 package.json 里,其中的 devDependencies 属性会随插件依赖的安装卸载而改变。

PS. Windows 7及以上,按住 Shift 再右键,选择在此处打开命令窗口。免去 cd 命令定位目录的烦恼。

5. 给项目目录安装常用的插件

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 “添加到压缩文件”,勾选压缩选项里的 “压缩后删除源文件” ,确定之后即可删除。

6. API

别看我,看它:http://www.gulpjs.com.cn/docs/api/

7. 代码示例

src/build/header.html
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>
src/build/footer.html
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>
src/index.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 文件,还可以配合参数生成独立的头部。

8. 我的 gulpfile.js,配置及说明

gulpfile.js
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);
 
});

9. 使用 gulp 的方法

执行gulp任务
1
gulp taskname // 如 gulp sass,不指定 taskname 则默认执行 default 任务

赶在四年一遇的2月29号,匆忙发表。

PS. 感谢 @合金大圣 订正错误。 16.07.04

更新 Gulp 系列教程,请戳下面

gulp (转)的更多相关文章

  1. 构建一个基本的前端自动化开发环境 —— 基于 Gulp 的前端集成解决方案(四)

    通过前面几节的准备工作,对于 npm / node / gulp 应该已经有了基本的认识,本节主要介绍如何构建一个基本的前端自动化开发环境. 下面将逐步构建一个可以自动编译 sass 文件.压缩 ja ...

  2. 常用 Gulp 插件汇总 —— 基于 Gulp 的前端集成解决方案(三)

    前两篇文章讨论了 Gulp 的安装部署及基本概念,借助于 Gulp 强大的 插件生态 可以完成很多常见的和不常见的任务.本文主要汇总常用的 Gulp 插件及其基本使用,需要读者对 Gulp 有一个基本 ...

  3. 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一)

    相关连接导航 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一) 执行 $Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二) 常用 Gulp 插件汇总 ...

  4. 执行 $Gulp 时发生了什么 —— 基于 Gulp 的前端集成解决方案(二)

    前言 文章 在windows下安装gulp —— 基于 Gulp 的前端集成解决方案(一) 中,已经完成对 gulp 的安装,由于是window环境,文中特意提到了可以通过安装 gitbash 来代替 ...

  5. gulp详细入门教程

    本文链接:http://www.ydcss.com/archives/18 gulp详细入门教程 简介: gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器:她不仅能对网站资源进行优 ...

  6. 做一个gulp+webpack+vue的单页应用开发架子

    1.目标 最近项目上的事情不多,根据我自己的开发习惯,决定开发一些简单的开发架子,方便以后事情多的时候直接套用.本文讲的一个gulp+webpack+vue的单页应用架子,想要达到的目的: 可以通过命 ...

  7. 前端自动化构建工具gulp记录

    一.安装 1)安装nodejs 通过nodejs的npm安装gulp,插件也可以通过npm安装.windows系统是个.msi工具,只要一直下一步即可,软件会自动在写入环境变量中,这样就能在cmd命令 ...

  8. gulp初学

    原文地址:gulp初学 至于gulp与grunt的区别,用过的人都略知一二,总的来说就是2点: 1.gulp的gulpfile.js  配置简单而且更容易阅读和维护.之所以如此,是因为它们的工作方式不 ...

  9. gulp批量打包文件并提取公共文件

    gulp是前端开发过程中对代码进行构建的工具,是自动化项目的构建利器. browseriyf是模块化打包工具. 一般情况下,Browserify 会把所有的模块打包成单个文件.单个文件在大多数情况下是 ...

  10. 使用gulp解决RequireJS项目前端缓存问题(二)

    1.前言 这一节,我们主要解决在上一节<使用gulp解决RequireJSs项目前端缓存问题(一)>末尾提到的几个问题: 对通过require-config.js引入的js文件修改后,没有 ...

随机推荐

  1. 前端JavaScript之DOM使用案例

    1.弹出框点击关闭 (这个例子关键自己创建标签以及属性,不是太好想啊,而且作用相对来数也不是太大) <!DOCTYPE html> <html> <head> &l ...

  2. C#如何表格型数据导出到Excel?

    代码如下: int intDataCount = myData.Tables[0].Rows.Count; Microsoft.Office.Interop.Excel.Application app ...

  3. java 集合 HashSet 实现随机双色球 HashSet addAll() 实现去重后合并 HashSet对象去重 复写 HashCode()方法和equals方法 ArrayList去重

    package com.swift.lianxi; import java.util.HashSet; import java.util.Random; /*训练知识点:HashSet 训练描述 双色 ...

  4. 太阳地球月亮运行动画(使用@keyframes)

    闲来无事的demo <!DOCTYPE html> <html> <head> <meta charset="utf-8"> < ...

  5. lvs+ipvsadm负载均衡

    使用LVS实现负载均衡原理及安装配置详解 负载均衡集群是 load balance 集群的简写,翻译成中文就是负载均衡集群.常用的负载均衡开源软件有nginx.lvs.haproxy,商业的硬件负载均 ...

  6. 【Effective C++读书笔记】序

    C++ 是一个难学易用的语言! [C++为什么难学?] C++的难学,不仅在其广博的语法,以及语法背后的语义,以及语义背后的深层思维,以及深层思维背后的对象模型: C++的难学还在于它提供了四种不同而 ...

  7. Mysql:case when then end 的用法

    0.创建一张数据表 表名为 test_when_case CREATE TABLE `test_when_case` ( `id` int(11) unsigned NOT NULL AUTO_INC ...

  8. 数据分析处理库Pandas——显示设置

    获取最多打印行数 显示内容超出部分打印成省略号. 设置最多打印行数 获取最多打印列数 显示内容超出部分打印成省略号. 设置最多打印列数 获取打印字符串的最大长度 显示内容超出部分打印成省略号. 设置打 ...

  9. C++基础 namespace register bool

    1. namespace (1)命令空间 C中的命名空间 在C中只有一个全局作用域 C语言中所有全局标识符共享同一个作用域 标识符之间可能发生冲突 C++中提出了命名空间的概念 命令空间将全局作用域分 ...

  10. C语言进阶——关于07中指针的补充

    首先我们应该了解指针可以分为: 野指针: 野指针不是NULL指针,是未初始化或未清零的指针,他指向的内存地址不是程序员想要的.人们一般不会错用NULL指针,因为用if语句很容易判断.但是“野指针”是很 ...