gulp简介
gulp,是基于nodejs的前端自动化构建工具,用于压缩项目文件,合并文件,部署等,简言之,就是解放生产力,提高开发效率。
现如今的前端全正处于飞速发展期,各种号称解放生产力的工具,框架喷涌而出,导致技术栈却是处于不稳定的状态,虽然技术层出不穷,但还是不要盲目的去推崇,还是结合项目本身找到合适的技术栈比较好。
现在大多数项目的技术栈中使用到的前端构建打包工具都是webpack或者webpack+gulp结合使用,本系列将讲解下gulp的使用。
使用前准备
nodejs安装
说明: gulp是基于nodejs运行的前端自动化构建工具,所以必须要先安装nodejs,可前往nodejs官网下载nodejs包安装。使用命令行
说明:window系统下可通过window + r 输入cmd回车启动命令行界面,或者安装git客户端。
简单介绍下几个常用的命令
1.node -v:查看安装的nodejs版本,出现版本号,说明刚刚已正确安装nodejs
2.npm -v:查看npm的版本号
3.cd:定位到目录,用法:cd + 路径
4.dir:列出文件列表
5.cls:清空命令提示符窗口内容npm介绍
说明:npm是nodejs的包管理器,用于node插件管理(包括安装、卸载、管理依赖等)
1.安装插件:通过命令行 npm install <name> [g] [--save-dev] 安装
注: <name>,插件名称,如:npm install gulp -g --save-dev。
[g],全局安装插件,可以通过命令行在任何地方调用它,PS: 本地安装将安装在定位目录的node_modules文件夹下,通过require()调用。
--save,将保存配置信息至package.json。
-dev,保存至package.json的devDependencies节点,不指定-dev将保存至dependencies节点。
2.卸载插件:通过命令行 npm uninstall <name> [-g] [--save-dev] 卸载
3.更新插件:通过命令行 npm update <name> [-g] [--save-dev] 更新cnpm的安装
由于npm是从国外服务器下载插件,可能网络方面会比较的慢,影响下载,因此我们需要通过代理的方式来解决这个问题。cnmp是一个淘宝代理镜像,能够代替npm下载需要的插件。
说明: 通过命令行 npm install cnpm -g --registry=https://registry.npm.taobao.org 安装cnpm镜像代理,安装好后可通过命令行 cnpm -v查看是否安装成功。
注: cnpm跟npm用法完全一致,只是在执行命令时将npm改为cnpm(以下操作将以cnpm代替npm)。
gulp API
先来了解下gulp常用的一些API。
1. gulp.src()
需要处理的源文件路径,参数可以是字符串,也可以是字符串数组,参数可以是通配符类型。比如,需要将项目下js文件夹下所有js文件做处理,就可以这样写:gulp.src("js/.js")*
2. gulp.dest()
指定处理完后文件的输出路径,参数类型为String or Function。
比如将项目下js文件夹下所有js文件处理完后,保存到同级的dist文件夹中,就可以这样写:gulp.dest("dist")
3. gulp.pipe()
该API可以链式调用,在输出和输入之间,可以用pipe指定任意的插件去处理你的文件。
4. gulp.task()
定制gulp任务,参数类型可以是字符串也可以是数组,比如定义第一个gulp执行任务,就可以这样写:gulp.task("firstGulp",function(){})
5. gulp.watch()
用于监听文件变化,任务gulp执行
具体的API参数详解,请参考这两篇关于gulp API的文章
http://www.gulpjs.com.cn/docs/api/
http://www.ydcss.com/archives/424
使用gulp压缩打包js文件
-
安装gulp
首先需要在全局下安装gulp,通过命令行 cnpm install gulp -g全局安装gulp。
新建一个gulp文件夹,目录结构如下,
---gulp源文件夹
---script文件夹
---a.js
---package.json文件
---gulpfile.js文件
在gulp文件夹根目录下,通过命令行 cnpm install gulp --save-dev,把gulp插件安装到本地项目的根目录中,至于为什么已经在全局安装了gulp还要在本地项目目录再安装gulp,这是为了防止版本冲突。
在a.js中写入一段代码,这是需要压缩的js文件
function gulpHello(){
alert("this is gulp firstDemo: hello world!");
}
接着,在项目的根目录下创建一个名为gulpfile.js的文件,这个文件名是gulp固定的,不能修改的。在gulpfile.js中,写入如下代码:
//引入gulp插件
var gulp = require("gulp");
//引入gulp-uglify模块,用于压缩js
var uglify = require("gulp-uglify");
//自定义任务,firstGulp为自定义任务名
gulp.task("firstGulp",function(){
gulp.src("./script/a.js")
.pipe(uglify())
.pipe(gulp.dest("./dest"))
})
之后再通过命令行执行该任务,输入gulp firstGulp命令行,敲击回车,执行结果如下图
出现了报错情况,原因是因为上面引入了压缩js的gulp-uglify模块没有下载到本地,所以我们在引入模块之前,得在本地安装我们需要引入的模块,且引入的模块名与需要安装的模块名是一致的。
比如安装gulp-uglify模块,通过命令行 cnpm install gulp-uglify --save-dev 安装即可。
再来执行gulp下任务,会发现,gulp文件夹中多了一个dist文件夹,里面的a.js文件就是我们压缩过的js文件。
虽然这样可以达到压缩文件的效果了,但是有一点不足的地方就是每次文件修改后都要通过命令行来执行任务,这样就并没有体现出gulp的自动化这样强大的功能。所以得完善gulpfile.js的代码,使其自动化,一旦文件有所改动,就自动执行gulp任务。
这里就可以使用gulp.watch()的API了,来监听文件的改动,从而执行相应的任务。
gulpfile.js文件代码修改如下:
//引入gulp插件
var gulp = require("gulp");
//引入gulp-uglify模块,用于压缩js
var uglify = require("gulp-uglify");
//自定义任务,firstGulp为自定义任务名
gulp.task("firstGulp",function(){
gulp.src("./script/a.js")
.pipe(uglify())
.pipe(gulp.dest("./dest"))
})
//新增一个auto的任务
gulp.task("auto",function(){
//watch()监听a.js文件的变动,如果变动,就执行firstGulp任务
//如果监听script下所有文件,只需把第一个参数改成script/*.js
gulp.watch("./script/a.js",["firstGulp"]);
})
然后只需要执行命令行 gulp auto 就可以实行自动化压缩文件了,但是这样还是有点不完善,就是gulp.watch方法监听到script文件夹中的某个js代码发生改变时,gulp会将script下所有的js都压缩一遍,极大地影响性能。
为了完善这一点,我们需要引入gulp-watch-path模块,就可以达到修改了哪个文件就压缩哪个文件的目的,而不是盲目压缩。在script文件夹下新增b.js和c.js两个js文件,随便放入一些代码,监听script文件夹下所有文件,那么如何使用gulp-watch-path模块,代码如下:
//引入gulp插件
var gulp = require("gulp");
//引入gulp-uglify模块,用于压缩js
var uglify = require("gulp-uglify");
//引入gulp-watch-path模块
var watchPath = require("gulp-watch-path");
//自定义任务,firstGulp为自定义任务名
gulp.task("firstGulp",function(){
gulp.src("./script/a.js")
.pipe(uglify())
.pipe(gulp.dest("./dest"))
})
//新增一个auto的任务
gulp.task("auto",function(){
//watch()监听a.js文件的变动,如果变动,就执行firstGulp任务
//如果监听script下所有文件,只需把第一个参数改成script/*.js
//gulp.watch("./script/a.js",["firstGulp"]);
gulp.watch("./script/*.js", function(event){
var paths = watchPath(event,"script","dist");
gulp.src(paths.srcPath)
.pipe(uglify())
//paths.distDir为目录文件
.pipe(gulp.dest(paths.distDir));
})
})
然后再在项目中安装gulp-watch-path模块,执行命令行 gulp auto,再修改a.js
function gulpHello(){
alert("this is gulp firstDemo: hello world!");
alert("do something...");
}
然后在dist文件夹下,可以看到压缩后的a.js了,这样就实现了自动化压缩且不盲目压缩的效果了。
但是每次执行任务都需要输入gulp+任务名才行,为了更加的简洁完善,只需要输入gulp敲击回车就可以执行任务,那么完善gulpfile.js就这样实现:
//引入gulp插件
var gulp = require("gulp");
//引入gulp-uglify模块,用于压缩js
var uglify = require("gulp-uglify");
//引入gulp-watch-path模块
var watchPath = require("gulp-watch-path");
//自定义任务,firstGulp为自定义任务名
gulp.task("firstGulp",function(){
gulp.src("./script/a.js")
.pipe(uglify())
.pipe(gulp.dest("./dest"))
})
//新增一个auto的任务
gulp.task("auto",function(){
//watch()监听a.js文件的变动,如果变动,就执行firstGulp任务
//如果监听script下所有文件,只需把第一个参数改成script/*.js
//gulp.watch("./script/a.js",["firstGulp"]);
gulp.watch("./script/*.js", function(event){
var paths = watchPath(event,"script","dist");
gulp.src(paths.srcPath)
.pipe(uglify())
//paths.distDir为目录文件
.pipe(gulp.dest(paths.distDir));
})
})
//default为gulp默认任务
gulp.task("default",["auto"])
这样就只需要输入gulp敲击回车就可以执行任务了,这样就更加完善了一步。
但是我们发现,压缩后的文件与源文件的文件名是一样的,我们压缩的源文件名为a.js,在dist文件夹下压缩过后的文件名也是a.js。通常我们见到的被压缩过的文件都是会带有.min的后缀,为了完善这一效果,需要引入gulp-rename模块,用于重命名压缩后的文件。
gulpfile.js修改如下:
//引入gulp插件
var gulp = require("gulp");
//引入gulp-uglify模块,用于压缩js
var uglify = require("gulp-uglify");
//引入gulp-watch-path模块
var watchPath = require("gulp-watch-path");
//引入gulp-rename模块,用于重命名压缩后的文件
var rename = require("gulp-rename");
//自定义任务,firstGulp为自定义任务名
gulp.task("firstGulp",function(){
gulp.src("./script/a.js")
.pipe(uglify())
.pipe(gulp.dest("./dest"))
})
//新增一个auto的任务
gulp.task("auto",function(){
//watch()监听a.js文件的变动,如果变动,就执行firstGulp任务
//如果监听script下所有文件,只需把第一个参数改成script/*.js
//gulp.watch("./script/a.js",["firstGulp"]);
gulp.watch("./script/*.js", function(event){
var paths = watchPath(event,"script","dist");
gulp.src(paths.srcPath)
.pipe(uglify())
//给压缩后的文件添加.min后缀
.pipe(rename({suffix: ".min"}))
//paths.distDir为目录文件
.pipe(gulp.dest(paths.distDir));
})
})
//default为gulp默认任务
gulp.task("default",["auto"])
再来执行下gulp,会发现压缩后的文件名改变了
合并压缩js文件
如果是在实际项目当中,js文件的个数肯定是很多的,就算我们压缩小了所以文件的体积,把100kb大小的文件压缩成了3kb大小,但在页面还是需要那么多的script标签来引用这些文件,script标签或者link标签过多的话是会影响页面加载性能的。为了进一步优化页面的加载性能,我们需要把多个文件合并压缩成一个文件,然后在页面中引入这个压缩后的文件即可,这样就减少了引入标签的使用。当然在合并压缩的过程中还要考虑到模块文件之间的依赖关系。
首先a.js,b.js,c.js文件代码修改如下:
a.js
function gulpHello(s){
alert("this is gulp firstDemo: hello world!");
alert("do something...");
alert(s);
}
b.js
gulpHello("这是b.js传入的参数");
function Person(name,age){
this.name = name;
this.age = age;
this.sayName = function(){
alert(this.name);
}
}
c.js
var ps = new Person("z3", 30);
ps.sayName();
可以明显看出3个js文件中存在这依赖关系,b.js依赖于a.js,c.js依赖于b.js,那么我们需要引入gulp-concat模块来合并文件,在本地项目中安装该模块,gulpfile.js代码修改如下:
//引入gulp插件
var gulp = require("gulp");
//引入gulp-uglify模块,用于压缩js
var uglify = require("gulp-uglify");
//引入gulp-watch-path模块
var watchPath = require("gulp-watch-path");
//引入gulp-rename模块,用于重命名压缩后的文件
var rename = require("gulp-rename");
//引入gulp-concat模块
var concat = require("gulp-concat");
//文件之间的依赖关系
var pathFile = ["./script/a.js","./script/b.js","./script/c.js"];
//自定义任务,firstGulp为自定义任务名
gulp.task("firstGulp",function(){
gulp.src("./script/a.js")
.pipe(uglify())
.pipe(gulp.dest("./dest"))
})
//新增一个auto的任务
gulp.task("auto",function(){
//watch()监听a.js文件的变动,如果变动,就执行firstGulp任务
//如果监听script下所有文件,只需把第一个参数改成script/*.js
//gulp.watch("./script/a.js",["firstGulp"]);
gulp.watch("./script/*.js", function(event){
gulp.src(pathFile)
.pipe(uglify())
//合并压缩为common.js
.pipe(concat("common.js"))
//给压缩后的文件添加.min后缀
.pipe(rename({suffix: ".min"}))
.pipe(gulp.dest("./dist"));
})
})
//default为gulp默认任务
gulp.task("default",["auto"])
压缩后的common.min.js如下:
可以看到,已经把3个文件的js代码合并压缩到了一个文件中了,说明已经实现了合并压缩js文件。
对于js文件的压缩差不多就ok了,后面的文章会继续讲解gulp对于css,less,html以及图片的处理,还有文件自动添加版本号的功能。
总结
- 安装nodejs
- 全局和本地安装gulp
- 安装gulp插件
- 新建gulpfile.js文件
- 通过命令提示符运行gulp任务
- gulp常用插件
插件名 | 作用 |
---|---|
gulp-uglify | 用于压缩js |
gulp-watch-path | 用于筛选改动的文件 |
gulp-rename | 用于重命名压缩后的文件 |
gulp-concat | 用于合并文件 |
此系列文章是对gulp前端自动构建工具的使用以及总结,文中如有不正之处,还望指正。
原创文章,站在前辈们的经验上的总结,文中如有不正之处,还望指正!