前端构建工具Gulp.js 你知多少..(webpack/gulp/grunt)

@TOC

写在前面

前几天在更新webpack知识的时候,想起来三年前用过的前端构建工具gulp/grunt,遂写个笔记总结一下,出来混总是要还的,忘得七七八八了...

阅读本文章之前,相信你已经对前端构建工具(webpack、gulp、grunt)有一定的认知和了解了,那么他们之间究竟有什么区别呢?

什么是gulp?

gulp文档上面有这么一句话\color{blue} {用自动化构建工具增强你的工作流程!} ,也就是说 gulp是一个自动化构建工具;
gulp的一些功能如下(包括但不限于):

自动化构建工具gulp

gulp或grunt和webpack的区别

其实Webpack和另外两个并没有太多的可比性

  • Gulp/Grunt是一种能够优化前端的开发流程的工具,而WebPack是一种模块化的解决方案,不过Webpack的优点使得Webpack在很多场景下可以替代Gulp/Grunt类的工具。

  • Grunt和Gulp的工作方式是:在一个配置文件中,指明对某些文件进行类似编译,组合,压缩等任务的具体步骤,工具之后可以自动替你完成这些任务。


    Grunt和Gulp的工作流程
  • Webpack的工作方式是:把你的项目当做一个整体,通过一个给定的主文件(如:index.js),Webpack将从这个文件开始找到你的项目的所有依赖文件,使用loaders处理它们,最后打包为一个(或多个)浏览器可识别的JavaScript文件。

    Webpack的工作方式

    上述内容转自@zhangwang的入门Webpack,看这篇就够了

gulp起步

傻瓜式起步照搬官网文档
1.安装

// 全局安装
$ npm install -g gulp
或者
$ npm install --global gulp

// 作为项目的开发依赖(devDependencies)安装:
$ npm install --save-dev gulp

2.在项目根目录下创建一个名为 gulpfile.js 的文件:

var gulp = require('gulp');

gulp.task('default', function() {
  // 将你的默认的任务代码放在这
});

3.运行 gulp:

$ gulp

默认的名为 default 的任务(task)将会被运行,在这里,这个任务并未做任何事情。
具体详情可以查看gulpjs.com文档

项目搭建

新建一个项目gulp-test
环境:

$ node -v // v9.1.0
$ npm -v // 6.5.0

1.新建文件以下文件如下

gulp-test/
          css/
               index.scss
           js/
               helloworld.js
           index.html
           gulpfile.js

其中 gulpfile.js 是我们gulp的配置文件,启动gulp默认会找个这个文件并执行;
2.接下来安装依赖

$ npm init

一直按回车Enter初始化package.json文件(小技巧: npm iniy -y 可以免去繁琐的enter步骤)
此时我们的目录结构是这样了

gulp-test/
          css/
               index.scss
           js/
               helloworld.js
           index.html
           gulpfile.js
           package.json

安装依赖

npm i --save-dev gulp        // gulp自动化构建工具
npm i --save-dev gulp-uglify //js压缩
npm i --save-dev gulp-concat //文件合并
npm i --save-dev gulp-jshint //js语法检测
npm i --save-dev gulp-rename //文件重命名
npm i --save-dev gulp-sass //sass编译工具
npm i --save-dev gulp-minify-css //css压缩
npm i --save-dev del       //文件删除
// 以下三选一
npm i --save-dev gulp-connect       // 自动刷新页面
npm i --save-dev  browser-sync       // 自动刷新页面
npm i --save-dev gulp-livereload       // 自动刷新页面

这里页面实时刷新只讲这个gulp-connect ,其他详情可以参照Browsersync和文章gulp-livereload

安装完依赖后配置gulpfile.js如下:

// 定义依赖项和插件
const gulp=require('gulp');
const  uglify=require('gulp-uglify'); //js压缩
const  concat=require('gulp-concat'); //文件合并
const jshint = require('gulp-jshint'); //js语法检测
const rename = require('gulp-rename'); // 重命名
const sass = require('gulp-sass'); // 编译scss
const  minifycss = require('gulp-minify-css'); // 压缩css
// const livereload = require('gulp-livereload'); // 自动刷新页面
const  del = require('del'); //文件删除
const connect = require('gulp-connect'); // 自动刷新页面

gulp.task('server', function() {
  connect.server({
    port: 8080, //指定端口号,在浏览器中输入localhost:8080就可以直接访问生成的html页面
    root: './', //指定html文件起始的根目录
    livereload: true //启动实时刷新功能(配合上边的connect.reload()方法同步使用)
  });
});

// 定义名为 "my-task" 的任务压缩js
gulp.task('my-task-js', function(){
  gulp.src('./js/*.js')
    .pipe(jshint())
    .pipe(uglify())
    .pipe(concat('all.js'))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('./dist/js'))
    .pipe(connect.reload())
});


// 定义名为 "my-task-css" 的任务编译scss压缩css
gulp.task('my-task-css', function() {
  gulp.src('./css/*.scss')
    .pipe(sass().on('error', sass.logError))
    .pipe(concat('all.css'))
    .pipe(rename({suffix: '.min'}))
    .pipe(minifycss())
    .pipe(connect.reload())
    .pipe(gulp.dest('./dist/css'))

});

gulp.task('html', function(){
  gulp.src('*.html')
    .pipe(gulp.dest('dist/html'))
    .pipe(connect.reload())
})
//执行压缩前,先删除以前压缩的文件
gulp.task('clean', function() {
  return del(['./dist/css/all.css', './dist/css/all.min.css', './dist/all.js','./dist/all.min.js', './dist/html'])
});
// 定义默认任务

gulp.task('default',['clean'],function() {
  gulp.start('my-task-js', 'my-task-css', 'watch', 'server' );
});
// 任务监听
gulp.task('watch', function() {
  // Watch.js files
  gulp.watch('./js/*.js', ['my-task-js']);
  // Watch .scss files
  gulp.watch('./css/*.scss', ['my-task-css']);
  // Watch .html files
  gulp.watch('./*.html', ['html']);
  // Watch any files in dist/, reload on change
  // gulp.watch(['dist/!**']).on('change', livereload.changed);
});

大概讲解一下gulpfile.js:

// ...
// 定义名为 "my-task" 的任务压缩js
gulp.task('my-task-js', function(){
  gulp.src('./js/*.js')
    .pipe(jshint()) //js检测
    .pipe(uglify()) //js压缩
    .pipe(concat('all.js')) //合并为all.js
    .pipe(rename({suffix: '.min'})) // 重命名为all.mim.js
    .pipe(gulp.dest('./dist/js')) //输出到/dist/js目录
    .pipe(connect.reload()) // 更新页面
});
// ...

gulp.task是gulp的api 定义一个使用 Orchestrator 实现的任务(task)
如上我们定义了my-task-jsmy-task-csshtmlcleandefaultwatchserver等任务,其中:


my-task-js 是将 符合所提供的匹配模式的js 进行检测(gulp-jshint)、压缩(gulp-uglify)、合并(gulp-concat)、重命名(gulp-rename)、输出(gulp.dest)到/dist/js目录下;


my-task-css 是将 符合所提供的匹配模式的sass进行编译(gulp-sass)、压缩(gulp-uglify)、合并(gulp-concat)、重命名(gulp-rename)、输出(gulp.dest)到/dist/css目录下;


html 是将 符合所提供的匹配模式的html进行监听,如果有变化则connect.reload()


clean 是如果任务重新启动时 删除旧文件;


default gulp默认启动的任务


watch gulp的api 监视文件,并且可以在文件发生改动时候做一些事情。它总会返回一个 EventEmitter 来发射(emit) change 事件。


server 依赖gulp-connect启动一个服务器

gulp.task('server', function() {
  connect.server({
    port: 8080, //指定端口号,在浏览器中输入localhost:8080就可以直接访问生成的html页面
    root: './', //指定html文件起始的根目录
    livereload: true //启动实时刷新功能(配合上边的connect.reload()方法同步使用)
  });
});

配置完gulpfile.js之后,我们给js和css及html加点东西:

首先js/helloworld.js

// helloworld.js
console.log('hello world')

css/index.scss

// index.scss

// 变量测试
$fontColor:  #red;
$backColor: aqua;
// 嵌套类测试
div {
  p {
    font-weight: bold;
    font-size: 20px;
    color: $fontColor;
  }
}

div{
  background: $backColor;
}

index.html

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>gulp-study</title>
    <link href=/dist/css/all.min.css rel=stylesheet>
</head>
<body>
    <div id="firstDiv">
        <p>我是gulp</p>
        <p>hello world</p>
    </div>
<p>我是p标签</p>
<p>我是p标签</p>
</body>
<script src="/dist/js/all.min.js"></script>
</html>

运行gulp

$ gulp 
运行输出

浏览器效果:


效果

接下来我们修改helloworld.js来看看是否能实时刷新
修改如下:

// helloworld.js
console.log('hello world');

let firstDiv =  document.getElementById('firstDiv')

console.log(firstDiv)

按保存之后,终端给我们报了一个错:


Unhandled 'error' event

查看js发现我们用了es6语法的声明语句\color{red}{let} 但当前gulp无法处理es6语法,有问题解决问题,es6=>es5

解决方案:
安装gulp-babel babel-core babel-preset-es2015

npm i  --save-dev  gulp-babel babel-core babel-preset-es2015

gulpfile.js修改如下:

// ...
const babel = require('gulp-babel');
// ...
// 定义名为 "my-task" 的任务压缩js
gulp.task('my-task-js', function(){
  gulp.src('./js/*.js')
    .pipe(babel())
    .pipe(jshint())
    .pipe(uglify())
    .pipe(concat('all.js'))
    .pipe(rename({suffix: '.min'}))
    .pipe(gulp.dest('./dist/js'))
    .pipe(connect.reload())
});
// ...

运行

$ gulp

依然报上面的错;找了一些原因发现,虽然安装了相关依赖,却没有配置.babelrc文件,即babel还没转化es6

根目录添加.babelrc文件

{
    "presets": ["es2015"]
}

重新运行:

$ gulp
结果如下

查看dist下的js文件


let已经转化成var

改变helloworld.js检查页面是否刷新

// helloworld.js
console.log('hello world');

let firstDiv =  document.getElementById('firstDiv')

console.log(firstDiv)
firstDiv.style.backgroundColor = 'yellow';

保存,页面的天空蓝换成你们喜欢的yellow颜色


页面的天空蓝换成你们喜欢的yellow颜色

修改index.scss 查看是否会刷新页面

// index.scss

// 变量测试
$fontColor:  #red;
$backColor: aqua;
// 嵌套类测试
div {
  p {
    font-weight: bold;
    font-size: 20px;
    color: $fontColor;
  }
}

div{
  background: $backColor;
  width: 400px;
  height: 400px;
  margin: 0 auto;
}


页面更新正常

最后修改index.html 查看是否会刷新页面

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>gulp-study</title>
    <link href=/dist/css/all.min.css rel=stylesheet>
</head>
<body>
    <div id="firstDiv">
        <p>我是gulp</p>
        <p>hello world</p>
    </div>
<div>
    <p>我是真的皮</p>
</div>
</body>
<script src="/dist/js/all.min.js"></script>
</html>

输出完美

此次项目源码请转@王一诺gulp-study

文章最后

今天主要学习了gulp的简单项目搭建及实时更新配置;其实gulp类似于grunt的弱化版,但更简单好用,只是插件会少一些,目前主流的项目搭建工具主要是webpack,但依然有不少项目还用着gulp或者grunt

扩展:

webpack中文网
gulpjs中文网
gruntjs中文网

下面还有一些楼主的学习笔记:

@webpack4+加vue2+从零开始搭设vue项目
@nginx部署/代理/跨域

有兴趣的可以多多交流@楼主博客

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 217,826评论 6 506
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 92,968评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 164,234评论 0 354
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,562评论 1 293
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,611评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,482评论 1 302
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,271评论 3 418
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,166评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,608评论 1 314
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,814评论 3 336
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,926评论 1 348
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,644评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,249评论 3 329
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,866评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,991评论 1 269
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,063评论 3 370
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,871评论 2 354