前端构建工具gulp入门学习

前端构建工具gulp的使用介绍及技巧

gulp是一个自动化工具,前端开发者可以使用它来处理常见任务:

搭建web服务器

文件保存时自动重载浏览器

使用预处理器如Sass/LESS

优化资源,比如压缩CSS/JavaScript,压缩图片

当然gulp能做的远不止这些;如果你够疯狂,甚至可以使用它搭建一个静态页面生成器;Gulp真的足够强大,但你必须学会驾驭它;这是这篇文章的主要目的就是帮助你了解Gulp的基础用法

在我们深入了解之前,先来说说为什么是Gulp

为什么是gulp

gulp是一个前端构建工具,与gruntjs相比,gulpjs无需写一大堆繁杂的配置参数,API也很简单,而且gulpjs使用的是nodejs中stream来读取和操作数据,其速度更快

gulp的安装

gulp需要在node环境下安装

安装Node

首先,最基本也最重要的是,我们需要搭建node环境,然后点击大大的绿色的install按钮,下载完成后直接运行程序,就一切准备就绪。npm会随着安装包一起安装,稍后会用到它;具体可以参考linux子系统ubuntu中node和git和gulp的安装配置windows下node和git和gulp的配置总结

node安装后我们来执行几个简单的命令

node -v //如果正确安装的话可以看到所安装的Node的版本号
npm -v //得到npm的版本号

如果这两行命令没有得到返回,可能node就没有安装正确,尝试重启下命令行工具,如果还不行的话,只能回到第一步进行重装

安装gulp

确保你已经正确安装了nodejs环境后以全局方式安装gulp:

npm install -g gulp //npm install是指定从Node Package Manager安装的命令;-g 表示全局安装,这样你在电脑上任何位置都能用gulp命令

定位到项目

安装过全局gulp后,我们只需要两个命令就能定位到文件目录并看看目录里都有些什么文件

cd //定位到目录
ls/dir //列出文件列表
cls //清空命令提示符窗口内容

建议多敲敲这两个命令,了解文件系统并知道文件都在哪里;成功进入项目目录后,我们开始安装本地gulp

安装gulp

首先,我们在项目目录下执行npm init命令:

$ npm init

npm init命令会为你创建一个package.json文件,这个文件保存着这个项目相关信息,比如你用到的各种依赖(这里主要是插件

创建完之后,我们执行下面的命令:

$ npm install gulp --save-dev //我们局部安装Gulp,使用—save-dev在安装的时候把gulp写进项目package.json文件的依赖中

执行完之后,gulp将创建node_modules文件夹,里面有个gulp文件夹

在正式开始之前,我们再来明确下项目的目录结构
1

package.json是基于nodejs项目必不可少的配置文件,它是存放在项目根目录的普通json文件;执行命令提示符npm init进行手动安装,安装完成后会在当前文件夹下看到package.json文件

这样就完成了gulp的安装;在全局安装gulp后还需要在项目中本地安装一次,主要是为了版本的灵活性

开始使用gulp

建立gulpfile.js文件

就像gruntjs需要一个Gruntfile.js文件一样,gulp也需要一个文件作为它的主文件,在gulp中这个文件叫做gulpfile.js;在根目录下新建一个文件名为gulpfile.js的文件,然后放到你的项目目录中,之后要做的事情就是在gulpfile.js文件中定义我们的任务

第一个gulp任务

//引入gulp:这行命令告知Node去node_modules中查找gulp包,先局部查找,找不到就去全局环境中查找,找到之后就会赋值给gulp变量,然后我们就可以使用它了

var gulp = require('gulp'); 

//简单的任务如下所示:

gulp.task('task-name', function() {
  // Stuff here
});

task-name是给你的任务起的名字,稍后在命令行中执行gulp task-name,将运行该任务

例如:写个HelloWorld,是这样的:

gulp.task('hello', function() {
  console.log('Hello World!');
});

在命令行中执行:

$ gulp hello

将会输出Hello World!, 够简单吧!

Gulp任务通常都会比这难一丁点,通常会包含两个特定的Gulp方法和一些列Gulp插件

大概这样:

gulp.task('task-name', function () {
  return gulp.src('source-files') // Get source files with gulp.src
    .pipe(aGulpPlugin()) // Sends it through a gulp plugin
    .pipe(gulp.dest('destination')) // Outputs the file in the destination folder
})

正如你所见,两个Gulp方法:src,dest,一进一出;下面用编译Sass来举栗子

gulp执行预处理

我们使用gulp-sass插件来编译Sass,安装插件的步骤是这样的:

使用npm install 命令安装

$ npm install gulp-sass --save-dev

在gulpfile中引入插件,用变量保存

var gulp = require('gulp');
var sass = require('gulp-sass');// Requires the gulp-sass plugin

在任务中使用

gulp.task('sass', function(){
  return gulp.src('source-files')
    .pipe(sass()) // Using gulp-sass
    .pipe(gulp.dest('destination'))
});

我们需要给sass任务提供源文件和输出位置。所以我们先在项目中创建app/scss文件夹,里面有个styles.scss文件。这个文件将在gulp.src中用到。

sass处理后,我们希望它生成css文件并产出到app/css目录下,可以这样写:

gulp.task('sass', function(){
  return gulp.src('app/scss/styles.scss')
    .pipe(sass()) // Converts Sass to CSS with gulp-sass
    .pipe(gulp.dest('app/css'))
});

测试下:

// styles.scss
.testing {
  width: percentage(5/7);
}

使用Terminal执行gulp sass,将看到app/css/styles.css文件下会有下面的代码:

/* styles.css */
.testing {
  width: 71.42857%;
}

styles.css是gulp自动为我们生成的,percentage是Sass的方法

但是通常我们不止有一个scss文件,这时候可以使用Node通配符

Node中的通配符

通配符是一种匹配模式,允许你匹配到多个文件;不止是Node,很多平台都有,有点像正则表达式;使用通配符,计算机检查文件名和路径进行匹配;大部分时候,我们只需要用到下面4种匹配模式:

.scss:号匹配当前目录任意文件,所以这里*.scss匹配当前目录下所有scss文件

*/.scss:匹配当前目录及其子目录下的所有scss文件

!not-me.scss:!号移除匹配的文件,这里将移除not-me.scss

*.+(scss|sass):+号后面会跟着圆括号,里面的元素用|分割,匹配多个选项,这里将匹配scss和sass文件

那么还是上面的栗子,改造一下:

gulp.task('sass', function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss and children dirs
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
})

任何app下的scss文件,在执行命令之后将生成对应的css文件存放到相应路径

现在我们能处理多个文件了,但是不想每次都要执行命令,怎么办?Gulp就是为懒人而生的,我们可以使用watch命令自动检测并执行

监听Sass文件

Gulp提供watch方法给我们,语法如下:

// Gulp watch syntax
gulp.watch('files-to-watch', ['tasks', 'to', 'run']);

将上面的栗子再改下:

// Gulp watch syntax
gulp.watch('app/scss/**/*.scss', ['sass']); //通常我们监听的还不只是一个文件,把它变成一个任务:
gulp.task('watch', function(){
  gulp.watch('app/scss/**/*.scss', ['sass']); //执行gulp watch命令
  // Other watchers
})

有了监听,每次修改文件,Gulp都将自动为我们执行任务;还不够,修改完直接帮我刷新浏览器行吗,我不想每次都要手动按Command + R;

使用Browser Sync自动刷新

Browser Sync帮助我们搭建简单的本地服务器并能实时刷新浏览器,它还能同时刷新多个设备

新插件?记住!安装,引入,使用

$ npm install browser-sync --save-dev //这里没有gulp-前缀,因为browser-sync支持Gulp,所以没有人专门去搞一个给Gulp用
var browserSync = require('browser-sync');//我们创建一个broswerSync任务,我们需要告知它,根目录在哪里
gulp.task('browserSync', function() {
  browserSync({
    server: {
      baseDir: 'app'
    },
  })
})

我们稍微修改一下之前的代码,让每次css文件更改都刷新一下浏览器:

gulp.task('sass', function() {
  return gulp.src('app/scss/**/*.scss') // Gets all files ending with .scss in app/scss
    .pipe(sass())
    .pipe(gulp.dest('app/css'))
    .pipe(browserSync.reload({
      stream: true
    }))
});

现在我们配置好Broswer Sync了,我们需要运行这两个命令;我们可以在watch任务之前告知Gulp,先把browserSync和Sass任务执行了再说;语法如下:

gulp.task('watch', ['array', 'of', 'tasks', 'to', 'complete','before', 'watch'], function (){
 //...
})

应用下来是这样:

gulp.task('watch', ['browserSync', 'sass'], function (){
  gulp.watch('app/scss/**/*.scss', ['sass']);
  // Other watchers
})

现在你执行gulp watch命令,在执行完browserSync和Sass,才会开始监听;并且现在浏览器的显示的页面为app/index.html,你修改了styles.scss之后,浏览器将自动属性页面;不止是scss修改的时候需要刷新浏览器吧,再改改:

gulp.task('watch', ['browserSync', 'sass'], function (){
  gulp.watch('app/scss/**/*.scss', ['sass']);
  // Reloads the browser whenever HTML or JS files change
  gulp.watch('app/*.html', browserSync.reload);
  gulp.watch('app/js/**/*.js', browserSync.reload);
});

到目前为止,我们做了下面三件事:

可运转的web开发服务

使用Sass预处理器

自动刷新浏览器

接下来说说优化方面的技巧

优化CSS和JavaScript文件

说到优化的时候,我们需要想到:压缩/拼接,也就是减少体积和HTTP次数;开发者面临的主要问题是很难按照正确的顺序合并文件

<body>
  <!-- other stuff -->
  <script src="js/lib/a-library.js"></script>
  <script src="js/lib/another-library.js"></script>
  <script src="js/main.js"></script>
</body>

由于文件路径的的不同,使用https://www.npmjs.com/package/gulp-concat等插件非常困难;庆幸的是,gulp-useref解决了这个问题

gulp-useref会将多个文件拼接成单一文件,并输出到相应目录

<!-- build:<type> <path> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->

可以是js,css,或者remove;如果你设为remove,Gulp将不会生成文件

我们想最终产出main.min.js,可以这样写:

<!--build:js js/main.min.js -->
<script src="js/lib/a-library.js"></script>
<script src="js/lib/another-library.js"></script>
<script src="js/main.js"></script>
<!-- endbuild -->

我们来安装gulp-useref。

$ npm install gulp-useref --save-dev

引用

var useref = require('gulp-useref'); 

使用起来非常简单:

gulp.task('useref', function(){
  return gulp.src('app/*.html')
        .pipe(useref())
        .pipe(gulp.dest('dist'));
});

执行useref命令,Gulp将合并三个script标签成一个文件,并保存到dist/js/main.min.js

合并完之后,我们再来压缩,使用gulp-uglify插件

安装

$ npm install gulp-uglify --save-dev

使用

// Other requires...
var uglify = require('gulp-uglify');
gulp.task('useref', function(){
  return gulp.src('app/*.html')
    .pipe(uglify()) // Uglifies Javascript files
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

注意:执行完useref后,html中的script路径将只剩下main.min.js

gulp-useref同样可以用在css上;除了压缩,需要区分其它内容同js一样.所以我们使用gulp-if来做不同处理

使用gulp-minify-css压缩css

$ npm install gulp-if gulp-minify-css --save-dev

应用

var gulpIf = require('gulp-if');
var minifyCSS = require('gulp-minify-css');
gulp.task('useref', function(){
  return gulp.src('app/*.html')
    // Minifies only if it's a CSS file
    .pipe(gulpIf('*.css', minifyCSS()))
    // Uglifies only if it's a Javascript file
    .pipe(gulpIf('*.js', uglify()))
    .pipe(useref())
    .pipe(gulp.dest('dist'))
});

再说说如何压缩图片

优化图片

使用gulp-imagemin插件

$ npm install gulp-imagemin --save-dev

引入,使用:

var imagemin = require('gulp-imagemin');
gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|gif|svg)')
  .pipe(imagemin())
  .pipe(gulp.dest('dist/images'))
});

所有的gulp插件都是有相关参数可以配置,如果需要可自行查看

压缩图片可能会占用较长时间,使用gulp-cache插件可以减少重复压缩

$ npm install gulp-cache --save-dev

引入,使用

var cache = require('gulp-cache');
gulp.task('images', function(){
  return gulp.src('app/images/**/*.+(png|jpg|jpeg|gif|svg)')
  // Caching images that ran through imagemin
  .pipe(cache(imagemin({
      interlaced: true
    })))
  .pipe(gulp.dest('dist/images'))
});

接下来我们说说发布流程

清理生成文件

由于是自动生成文件,我们不想旧文件掺杂进来

使用del

npm install del --save-dev

引入,使用

var del = require('del');
gulp.task('clean', function() {
  del('dist');
});

但是我们又不想图片被删除(图片改动的几率不大),启用新的任务

gulp.task('clean:dist', function(callback){
  del(['dist/**/*', '!dist/images', '!dist/images/**/*'], callback)
});

这个任务会删除dist下除了images/文件夹的任意文件,为了知道clean:dist任务什么时候完成,我们需要提供callback参数

在某些时候我们还是需要清除图片,所以clean任务我们还需要保留

gulp.task('clean', function(callback) {
  del('dist');
  return cache.clearAll(callback);
})

把我们学到的组合到一块吧

组合Gulp任务

废话了这么多,我们主要有两条线路

第一条是开发过程,我们以Sass监听文件刷新浏览器

第二条是优化,我们优化CSS,JavaScript,压缩图片,并把资源从app移动到dist

开发任务我们上面的watch已经组装好了

gulp.task('watch', ['browserSync', 'sass'], function (){
  // ... watchers
})

我们也做一个来执行第二条线路

gulp.task('build', [`clean`, `sass`, `useref`, `images`, `fonts`], function (){
  console.log('Building files');
})

但是这样Gulp会同时触发[]的事件,我们要让clean在其他任务之前完成

这里要用到RunSequence

$ npm install run-sequence --save-dev

用法如下:

var runSequence = require('run-sequence');
gulp.task('task-name', function(callback) {
  runSequence('task-one', 'task-two', 'task-three', callback);
});

执行task-name时,Gulp会按照顺序执行task-one,task-two,task-thre

RunSequence也允许你同时执行多个任务。

gulp.task('task-name', function(callback) {
  runSequence('task-one', ['tasks','two','run','in','parallel'], 'task-three', callback);
});

改造我们的代码:

gulp.task('build', function (callback) {
  runSequence('clean:dist',
    ['sass', 'useref', 'images', 'fonts'],
    callback
  )
})

开发任务我们也用runSequence:

gulp.task('default', function (callback) {
  runSequence(['sass','browserSync', 'watch'],
    callback
  )
})

default? 如果你的任务名字叫做default,那么只需要输入gulp命令即可执行。

这里是我们最终的 代码仓库 。

开发过程:

使用Autoprefixer,不再需要写CSS浏览器内核前缀

增加Sourcemaps,更方便的调试Sass,coffeescript

使用sprity创建精灵图

gulp-changed只允许通过修改的文件

Babel或Traceur写ES6

Browserify,webpack,jspm 模块化JavaScript

Handlebars,Swing模块化Html

require-dir分割gulpfile成多个文件

gulp-moderinizr自动生成Modernizr脚本

优化:

unCSS移除多余的CSS

CSSO更深入地优化CSS

Critical生成行内CSS

除了开发和优化过程,可以使用gulp-jasmine写JavaScript单元测试,甚至使用gulp-rync直接部署dist文件到生产环境

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值