热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

gulp(http://markpop.github.io/2014/09/17/Gulp入门教程)

前言最近流行前端构建工具,苦于之前使用Grunt,代码很难阅读,现在出了Gulp,真是摆脱了痛苦。发现了一篇很好的Gulp英文教程,整理翻译给大家看看。为什么使用GulpGulp基

前言

最近流行前端构建工具,苦于之前使用Grunt,代码很难阅读,现在出了Gulp,真是摆脱了痛苦。发现了一篇很好的Gulp英文教程,整理翻译给大家看看。

为什么使用Gulp

Gulp基于Node.js的前端构建工具,通过Gulp的插件可以实现前端代码的编译(sass、less)、压缩、测试;图片的压缩;浏览器自动刷新,还有许多强大的插件可以在这里查找。比起Grunt不仅配置简单而且更容易阅读和维护,我们可以做一个对比:

Grunt:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
sass: {
dist: {
options: {
style: ‘expanded‘
},
files: {
‘dist/assets/css/main.css‘: ‘src/styles/main.scss‘,
}
}
},
autoprefixer: {
dist: {
options: {
browsers: [
‘last 2 version‘, ‘safari 5‘, ‘ie 8‘, ‘ie 9‘, ‘opera 12.1‘, ‘ios 6‘, ‘android 4‘
]
},
src: ‘dist/assets/css/main.css‘,
dest: ‘dist/assets/css/main.css‘
}
},
grunt.registerTask(‘styles‘, [‘sass‘, ‘autoprefixer‘]);

在Grunt里面,每个插件使用的方式相对独立,正如上面的代码通过sass插件将main.sass文件编译成main.css文件,接着autoprefixer插件再对编译好的main.css文件进行修改,最后覆盖main.css。那么覆盖文件就是多余的了,有没办法做到sass和autoprefixer一并处理完再生成main.css?我们来看看Gulp是如何做到的:

Gulp:

1
2
3
4
5
6
gulp.task(‘sass‘, function() {
return gulp.src(‘src/styles/main.scss‘)
.pipe(sass({ style: ‘compressed‘ }))
.pipe(autoprefixer(‘last 2 version‘, ‘safari 5‘, ‘ie 8‘, ‘ie 9‘, ‘opera 12.1‘, ‘ios 6‘, ‘android 4‘))
.pipe(gulp.dest(‘dist/assets/css‘))
});

使用Gulp我们只需要放一个路径,通过管道方式使用插件,最后生成文件,是不是有种jQuery的感觉。这种方式不仅提高效率而且一眼就看清了输入文件和输出文件,再也不用看gruntfile看得眼花缭乱了。

再打个比喻,Grunt的插件就像独立的工厂,这个工厂生成出来的产品打包封装好后再送到另一个工厂去加工,使用了Gulp后实现了工厂的合并,所有东西都在一个工厂里完成了。现在是否对Gulp感兴趣了,那就开始使用Gulp吧!

安装

首先我们要全局安装一遍:

1
$ npm install gulp -g

接着我们要进去到项目的根目录再安装一遍(确保你根目录存在package.json文件):

1
$ npm install gulp --save-dev

—save-dev这个属性会将条目保存到你package.json的devDependencies里面

安装Gulp插件

我们将要使用Gulp插件来完成我们以下任务:

  • sass的编译(gulp-ruby-sass)
  • 自动添加css前缀(gulp-autoprefixer)
  • 压缩css(gulp-minify-css)
  • js代码校验(gulp-jshint)
  • 合并js文件(gulp-concat)
  • 压缩js代码(gulp-uglify)
  • 压缩图片(gulp-imagemin)
  • 自动刷新页面(gulp-livereload)
  • 图片缓存,只有图片替换了才压缩(gulp-cache)
  • 更改提醒(gulp-notify)
  • 清除文件(del)

安装这些插件需要运行如下命令:

1
$ npm install gulp-ruby-sass gulp-autoprefixer gulp-minify-css gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-livereload gulp-cache del --save-dev

上面是一些常用的插件,如果想要找更多的插件点击这里

加载插件

接着我们要创建一个gulpfile.js在根目录下,然后在里面加载插件:

1
2
3
4
5
6
7
8
9
10
11
12
13
var gulp = require(‘gulp‘),
sass = require(‘gulp-ruby-sass‘),
autoprefixer = require(‘gulp-autoprefixer‘),
minifycss = require(‘gulp-minify-css‘),
jshint = require(‘gulp-jshint‘),
uglify = require(‘gulp-uglify‘),
imagemin = require(‘gulp-imagemin‘),
rename = require(‘gulp-rename‘),
cOncat= require(‘gulp-concat‘),
notify = require(‘gulp-notify‘),
cache = require(‘gulp-cache‘),
livereload = require(‘gulp-livereload‘),
del = require(‘del‘);

Gulp的插件和Grunt有些许不一样,Grunt插件是为了更好的完成一项任务。就像Grunt的imagemin插件就利用了缓存来避免重复压缩,而Gulp要利用gulp-cache来完成,当然啦,不仅限定于缓存图片。

建立任务

编译sass、自动添加css前缀和压缩

首先我们编译sass,添加前缀,保存到我们指定的目录下面,还没结束,我们还要压缩,给文件添加.min后缀再输出压缩文件到指定目录,最后提醒任务完成了:

1
2
3
4
5
6
7
8
9
10
gulp.task(‘styles‘, function() {
return gulp.src(‘src/styles/main.scss‘)
.pipe(sass({ style: ‘expanded‘ }))
.pipe(autoprefixer(‘last 2 version‘, ‘safari 5‘, ‘ie 8‘, ‘ie 9‘, ‘opera 12.1‘, ‘ios 6‘, ‘android 4‘))
.pipe(gulp.dest(‘dist/assets/css‘))
.pipe(rename({suffix: ‘.min‘}))
.pipe(minifycss())
.pipe(gulp.dest(‘dist/assets/css‘))
.pipe(notify({ message: ‘Styles task complete‘ }));
});

让我解释一下:

1
gulp.task(‘styles‘, function () {...});

gulp.task这个API用来创建任务,在命令行下可以输入$ gulp styles来执行上面的任务。

1
return gulp.src(‘src/styles/main.scss‘)

gulp.src这个API设置需要处理的文件的路径,可以是多个文件以数组的形式[main.scss, vender.scss],也可以是正则表达式/**/*.scss

1
.pipe(sass({ style: ‘expanded‘ }))

我们使用.pipe()这个API将需要处理的文件导向sass插件,那些插件的用法可以在github上找到,为了方便大家查找我已经在上面列出来了。

1
.pipe(gulp.dest(‘dist/assets/css‘));

gulp.dest()API设置生成文件的路径,一个任务可以有多个生成路径,一个可以输出未压缩的版本,另一个可以输出压缩后的版本。

为了更好的了解Gulp API,强烈建议看一下Gulp API文档,其实Gulp API就这么几个,没什么好可怕的。

js代码校验、合并和压缩

希望大家已经知道如何去创建一个任务了,接下来我们完成scripts的校验、合并和压缩的任务吧:

1
2
3
4
5
6
7
8
9
10
11
gulp.task(‘scripts‘, function() {
return gulp.src(‘src/scripts/**/*.js‘)
.pipe(jshint(‘.jshintrc‘))
.pipe(jshint.reporter(‘default‘))
.pipe(concat(‘main.js‘))
.pipe(gulp.dest(‘dist/assets/js‘))
.pipe(rename({suffix: ‘.min‘}))
.pipe(uglify())
.pipe(gulp.dest(‘dist/assets/js‘))
.pipe(notify({ message: ‘Scripts task complete‘ }));
});

需要提醒的是我们要设置JSHint的reporter方式,上面使用的是default默认的,了解更多点击这里。

压缩图片

1
2
3
4
5
6
gulp.task(‘images‘, function() {
return gulp.src(‘src/images/**/*‘)
.pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true }))
.pipe(gulp.dest(‘dist/assets/img‘))
.pipe(notify({ message: ‘Images task complete‘ }));
});

这个任务使用imagemin插件把所有在src/images/目录以及其子目录下的所有图片(文件)进行压缩,我们可以进一步优化,利用缓存保存已经压缩过的图片,使用之前装过的gulp-cache插件,不过要修改一下上面的代码:

将这行代码:

1
.pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true }))

修改成:

1
.pipe(cache(imagemin({ optimizationLevel: 5, progressive: true, interlaced: true })))

现在,只有新建或者修改过的图片才会被压缩了。

清除文件

在任务执行前,最好先清除之前生成的文件:

1
2
3
gulp.task(‘clean‘, function(cb) {
del([‘dist/assets/css‘, ‘dist/assets/js‘, ‘dist/assets/img‘], cb)
});

在这里没有必要使用Gulp插件了,可以使用NPM提供的插件。我们用一个回调函数(cb)确保在退出前完成任务。

设置默认任务(default)

我们在命令行下输入$ gulp执行的就是默认任务,现在我们为默认任务指定执行上面写好的三个任务:

1
2
3
gulp.task(‘default‘, [‘clean‘], function() {
gulp.start(‘styles‘, ‘scripts‘, ‘images‘);
});

在这个例子里面,clean任务执行完成了才会去运行其他的任务,在gulp.start()里的任务执行的顺序是不确定的,所以将要在它们之前执行的任务写在数组里面。

监听文件

为了监听文件的是否修改以便执行相应的任务,我们需要创建一个新的任务,然后利用gulp.watchAPI实现:

1
2
3
4
5
6
7
8
gulp.task(‘watch‘, function() {
// Watch .scss files
gulp.watch(‘src/styles/**/*.scss‘, [‘styles‘]);
// Watch .js files
gulp.watch(‘src/scripts/**/*.js‘, [‘scripts‘]);
// Watch image files
gulp.watch(‘src/images/**/*‘, [‘images‘]);
});

我们将不同类型的文件分开处理,执行对应的数组里的任务。现在我们可以在命令行输入$ gulp watch执行监听任务,当.sass.js和图片修改时将执行对应的任务。

自动刷新页面

Gulp也可以实现当文件修改时自动刷新页面,我们要修改watch任务,配置LiveReload:

1
2
3
4
5
6
gulp.task(‘watch‘, function() {
// Create LiveReload server
livereload.listen();
// Watch any files in dist/, reload on change
gulp.watch([‘dist/**‘]).on(‘change‘, livereload.changed);
});

要使这个能够工作,还需要在浏览器上安装LiveReload插件,除此之外还能这样做

所有任务放一起

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
/*!
* gulp
* $ npm install gulp-ruby-sass gulp-autoprefixer gulp-minify-css gulp-jshint gulp-concat gulp-uglify gulp-imagemin gulp-notify gulp-rename gulp-livereload gulp-cache del --save-dev
*/
// Load plugins
var gulp = require(‘gulp‘),
sass = require(‘gulp-ruby-sass‘),
autoprefixer = require(‘gulp-autoprefixer‘),
minifycss = require(‘gulp-minify-css‘),
jshint = require(‘gulp-jshint‘),
uglify = require(‘gulp-uglify‘),
imagemin = require(‘gulp-imagemin‘),
rename = require(‘gulp-rename‘),
cOncat= require(‘gulp-concat‘),
notify = require(‘gulp-notify‘),
cache = require(‘gulp-cache‘),
livereload = require(‘gulp-livereload‘),
del = require(‘del‘);
// Styles
gulp.task(‘styles‘, function() {
return gulp.src(‘src/styles/main.scss‘)
.pipe(sass({ style: ‘expanded‘, }))
.pipe(autoprefixer(‘last 2 version‘, ‘safari 5‘, ‘ie 8‘, ‘ie 9‘, ‘opera 12.1‘, ‘ios 6‘, ‘android 4‘))
.pipe(gulp.dest(‘dist/styles‘))
.pipe(rename({ suffix: ‘.min‘ }))
.pipe(minifycss())
.pipe(gulp.dest(‘dist/styles‘))
.pipe(notify({ message: ‘Styles task complete‘ }));
});
// Scripts
gulp.task(‘scripts‘, function() {
return gulp.src(‘src/scripts/**/*.js‘)
.pipe(jshint(‘.jshintrc‘))
.pipe(jshint.reporter(‘default‘))
.pipe(concat(‘main.js‘))
.pipe(gulp.dest(‘dist/scripts‘))
.pipe(rename({ suffix: ‘.min‘ }))
.pipe(uglify())
.pipe(gulp.dest(‘dist/scripts‘))
.pipe(notify({ message: ‘Scripts task complete‘ }));
});
// Images
gulp.task(‘images‘, function() {
return gulp.src(‘src/images/**/*‘)
.pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
.pipe(gulp.dest(‘dist/images‘))
.pipe(notify({ message: ‘Images task complete‘ }));
});
// Clean
gulp.task(‘clean‘, function(cb) {
del([‘dist/assets/css‘, ‘dist/assets/js‘, ‘dist/assets/img‘], cb)
});
// Default task
gulp.task(‘default‘, [‘clean‘], function() {
gulp.start(‘styles‘, ‘scripts‘, ‘images‘);
});
// Watch
gulp.task(‘watch‘, function() {
// Watch .scss files
gulp.watch(‘src/styles/**/*.scss‘, [‘styles‘]);
// Watch .js files
gulp.watch(‘src/scripts/**/*.js‘, [‘scripts‘]);
// Watch image files
gulp.watch(‘src/images/**/*‘, [‘images‘]);
// Create LiveReload server
livereload.listen();
// Watch any files in dist/, reload on change
gulp.watch([‘dist/**‘]).on(‘change‘, livereload.changed);
});

在gist上有源码,并且附上Grunt的实现作为对比。

gulp ( http://markpop.github.io/2014/09/17/Gulp入门教程 )


推荐阅读
  • 在 Axublog 1.1.0 版本的 `c_login.php` 文件中发现了一个严重的 SQL 注入漏洞。该漏洞允许攻击者通过操纵登录请求中的参数,注入恶意 SQL 代码,从而可能获取敏感信息或对数据库进行未授权操作。建议用户尽快更新到最新版本并采取相应的安全措施以防止潜在的风险。 ... [详细]
  • 二分查找算法详解与应用分析:本文深入探讨了二分查找算法的实现细节及其在实际问题中的应用。通过定义 `binary_search` 函数,详细介绍了算法的逻辑流程,包括初始化上下界、循环条件以及中间值的计算方法。此外,还讨论了该算法的时间复杂度和空间复杂度,并提供了多个应用场景示例,帮助读者更好地理解和掌握这一高效查找技术。 ... [详细]
  • 在Eclipse中提升开发效率,推荐使用Google V8插件以增强Node.js的调试体验。安装方法有两种:一是通过Eclipse Marketplace搜索并安装;二是通过“Help”菜单中的“Install New Software”,在名称栏输入“googleV8”。此插件能够显著改善调试过程中的性能和响应速度,提高开发者的生产力。 ... [详细]
  • Nginx 反向代理配置与应用指南
    本文详细介绍了 Nginx 反向代理的配置与应用方法。首先,用户可以从官方下载页面(http://nginx.org/en/download.html)获取最新稳定版 Nginx,推荐使用 1.14.2 版本。下载并解压后,通过双击 `nginx.exe` 文件启动 Nginx 服务。文章进一步探讨了反向代理的基本原理及其在实际应用场景中的配置技巧,包括负载均衡、缓存管理和安全设置等,为用户提供了一套全面的实践指南。 ... [详细]
  • 本指南详细介绍了如何在CentOS 6.6 64位系统上以root用户身份部署Tomcat 8服务器。系统环境为CentOS 6.6 64位,采用源码安装方式。所需软件为apache-tomcat-8.0.23.tar.gz,建议将软件下载至/root/opt目录。具体下载地址请参见官方资源。本指南涵盖了从环境准备到服务启动的完整步骤,适用于需要在该系统环境下搭建高性能Web应用服务器的技术人员。 ... [详细]
  • 该问题可能由守护进程配置不当引起,例如未识别的JVM选项或内存分配不足。建议检查并调整JVM参数,确保为对象堆预留足够的内存空间(至少1572864KB)。此外,还可以优化应用程序的内存使用,减少不必要的内存消耗。 ... [详细]
  • 在 Mac 上查看隐藏文件和文件夹的详细指南。通过终端命令,您可以轻松地显示或隐藏这些文件。具体步骤如下:输入 `defaults write com.apple.finder AppleShowAllFiles -bool true` 以显示所有隐藏文件,或使用 `defaults write com.apple.finder AppleShowAllFiles -bool false` 以重新隐藏它们。此方法适用于各种版本的 macOS,帮助用户更好地管理和访问系统文件。 ... [详细]
  • 近日,我在处理一个复杂的前端问题时遇到了极大困扰。具体来说,我之前开发了一个功能丰富的纯jQuery代码的前端GridView控件,实现了多种功能和视觉效果,并在多个项目中表现良好。然而,最近在尝试应用 `border-box` 布局模式时,却遇到了意想不到的兼容性和性能问题。这提醒我们在条件尚未完全成熟的情况下,应谨慎使用 `border-box` 布局模式,以免引入不必要的复杂性和潜在的bug。 ... [详细]
  • 深入解析Java虚拟机的内存分区与管理机制
    Java虚拟机的内存分区与管理机制复杂且精细。其中,某些内存区域在虚拟机启动时即创建并持续存在,而另一些则随用户线程的生命周期动态创建和销毁。例如,每个线程都拥有一个独立的程序计数器,确保线程切换后能够准确恢复到之前的执行位置。这种设计不仅提高了多线程环境下的执行效率,还增强了系统的稳定性和可靠性。 ... [详细]
  • Python 伦理黑客技术:深入探讨后门攻击(第三部分)
    在《Python 伦理黑客技术:深入探讨后门攻击(第三部分)》中,作者详细分析了后门攻击中的Socket问题。由于TCP协议基于流,难以确定消息批次的结束点,这给后门攻击的实现带来了挑战。为了解决这一问题,文章提出了一系列有效的技术方案,包括使用特定的分隔符和长度前缀,以确保数据包的准确传输和解析。这些方法不仅提高了攻击的隐蔽性和可靠性,还为安全研究人员提供了宝贵的参考。 ... [详细]
  • 题目 E. DeadLee:思维导图与拓扑结构的深度解析问题描述:给定 n 种食物,每种食物的数量由 wi 表示。同时,有 m 位朋友,每位朋友喜欢两种特定的食物 x 和 y。目标是通过合理分配食物,使尽可能多的朋友感到满意。本文将通过思维导图和拓扑排序的方法,对这一问题进行深入分析和求解。 ... [详细]
  • 深入解析Linux内核中的进程上下文切换机制
    在现代操作系统中,进程作为核心概念之一,负责管理和分配系统资源,如CPU和内存。深入了解Linux内核中的进程上下文切换机制,需要首先明确进程与程序的区别。进程是一个动态的执行流,而程序则是静态的数据和指令集合。进程上下文切换涉及保存当前进程的状态信息,并加载下一个进程的状态,以实现多任务处理。这一过程不仅影响系统的性能,还关系到资源的有效利用。通过分析Linux内核中的具体实现,可以更好地理解其背后的原理和技术细节。 ... [详细]
  • 如何在PDF文档中添加新的文本内容?
    在处理PDF文件时,有时需要向其中添加新的文本内容。这是否可以直接实现呢?有哪些简便且免费的方法可供选择?使用极速PDF阅读器打开文档后,可以通过点击左上角的“注释”按钮切换到注释模式,并选择相应的工具进行编辑。此外,还可以利用其他功能丰富的PDF编辑软件,如Adobe Acrobat DC或Foxit PhantomPDF,它们提供了更多高级的编辑选项,能够满足更复杂的需求。 ... [详细]
  • 题目要求解决一个有趣的编程挑战,即计算由四个自然数 \( p, q, r, s \) 组成的分数序列的和。具体来说,需要编写一个 C# 程序来处理这些自然数,并通过特定的数学运算得出最终结果。该任务不仅考验编程技能,还涉及对数学公式的理解和应用。 ... [详细]
  • POJ 2482 星空中的星星:利用线段树与扫描线算法解决
    在《POJ 2482 星空中的星星》问题中,通过运用线段树和扫描线算法,可以高效地解决星星在窗口内的计数问题。该方法不仅能够快速处理大规模数据,还能确保时间复杂度的最优性,适用于各种复杂的星空模拟场景。 ... [详细]
author-avatar
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有