# GULP
- `gulp` 是一个项目开发的 **自动化打包构建工具**
- 基于 `node` 环境来运行的
## 什么是自动化打包构建工具
- 比如
- 我们在开发的过程中,会写到 `js` 文件,`css` 文件,等等
- 我们的项目如果想上线,那么一定要体积小一点,文件大小越小越好
- 而我们在写 `js` 文件的时候,会有很多 **换行/空格** 之类的东西
- 这些 **换行/空格** 都是占文件体积的一部分
- 那么我们在上线之前就要吧这些 **换行/空格** 尽可能的删除掉
- 我们又不能一个文件一个文件的去删除
- 就要用到一个自动化工具来帮助我们把这些多余的东西干掉
- 这个就是自动化工具的意义
- 常见的自动化打包构建工具
- `gulp`
- `webpack`
## 安装 GULP
- `gulp` 是一个依赖于 `node` 的环境工具
- 所以我们需要先安装一个 **全局 `gulp` 依赖**
- 直接使用 `npm` 去安装就可以了
```shell
# 使用 npm 安装全局依赖 gulp
# 我们这里安装一个4版本的就好了
$ npm install --global gulp
$ npm uninstall --global gulp
-
等待安装完毕就好了
-
这个全局环境一个电脑安装一次就好了
-
还是照例检查一下是否安装成功
$ gulp --version
使用 GULP
-
安装完毕以后,我们就可以使用 GULP 对我们的项目进行自动化构建了
-
首先我们要有一个项目
- gulp_demo 项目文件夹 - src 项目源码 + css css 文件夹 + js js 文件夹 + pages html 文件夹 + sass sass 文件夹 + lib 第三方文件夹
-
目录结构不一定都是这个样子
-
但是最好是一个便于管理的文件夹目录结构
-
因为是一个项目了,最好使用
npm
来帮我们管理一下- 这样可以记录我们的下载使用了那些依赖
-
所以在项目文件夹
gulp-demo
里面执行一个npm
初始化$ cd gulp_demo $ npm init -y
-
执行完毕之后,再来看一下我们的项目目录
- gulp_demo + src + package.json
项目 GULP 配置
-
我们之前已经安装过
gulp
全局依赖了 -
但是每一个项目都要在安装一次
gulp
的项目依赖 -
因为每一个项目的打包构建规则都不一样,所以不能全都配置成一个
-
所以我们要在项目里面再次进行
gulp
安装$ cd gulp_demo $ npm install -D gulp
- 项目中的
gulp
依赖要和全局gulp
环境保持版本一致
- 项目中的
-
接下来就是对这个项目进行打包构建的配置
-
gulp
的使用,要在项目目录下新建一个gulpfile.js
-
在这个
gulpfile.js
文件里面进行配置 -
然后使用
gulp
进行构建的时候就会按照gulpfile.js
文件里面的规则进行打包构建 -
再来看一下我们的目录结构
- gulp_demo + node_modules 依赖包目录 + src 项目源码 + gulpfile.js gulp 配置文件 + package-lock.json 依赖下载版本 json 文件 + package.json 项目管理 json 文件
-
接下来我们就是在
gulpfile.js
文件里面进行配置,让我们的打包构建可以生效
打包 CSS 文件
-
我们从简单的内容开始,先来打包构建
css
文件 -
其实就是在
gulpfile.js
里面进行一些配置 -
第一个事情就是引入
gulp
// 我是 gulpfile.js 文件 // 1. 引入 gulp const gulp = require('gulp')
-
gulp
是基于任务来完成构建的 -
所以我们要创建一个打包
css
的任务// 我是 gulpfile.js 文件 // 1. 引入 gulp const gulp = require('gulp')
-
这个时候我们自己完成不了,就需要借助一个第三方依赖
npm i -D gulp-cssmin
-
下载完毕以后,去文件中进行配置
const cssHandler = function() { return gulp.src('./src/css/*.css') .pipe(cssmin()) .pipe(gulp.dest('./dist/css')) } module.exports = { cssHandler }
gulp.src()
是指找到那些文件对其操作gulp.pipe()
是指要做什么gulp.dest()
是指输出到哪个目录下,如果没有这个目录存在会自动创建这个目录- 所以上面哪个
css
任务的意思就是- 把
./src/css/
目录下的所有文件 - 进行压缩
- 压缩完毕后放在
./dist/
下的css/
文件夹下
- 把
-
接下来,就是执行一下这个叫做
css
的任务就行了 -
直接在控制台使用指令
# 表示运行 gulpfils.js 配置文件中的 css 任务 $ gulp cssHandler
-
执行完毕以后,就会在
gulp_demo
目录下生成一个dist/
文件夹 -
里面就有我们压缩好的
css
文件
-
打包 SASS 文件
-
接下来我们解决一下
sass
的问题 -
因为有的时候我们开发要使用
sass
所以我们要解决一下sass
的问题 -
其实打包
sass
和css
差不多,只不过先要把sass
解析成css
- 把
sass
解析成css
- 压缩一下
- 放到对应的文件夹中
- 把
-
使用
gulp
解析sass
文件需要用到一个依赖npm install sass gulp-sass --save-dev
-
然后我们就去到配置文件里面进行配置就好了
const sass = require( 'gulp-sass' ) ( require ( 'sass' ) ) const sassHandler = function() { return gulp.src('./src/sass/*.scss') //在打包之前先进行转换 .pipe(sass()) .pipe(cssmin()) .pipe(gulp.dest('./dist/css')) } module.exports = { sassHandler }
- 我们的
sass
文件编译完以后也是css
文件,所以就也放在css
文件夹下就好了 - 就是要注意一下别和本来
css
文件夹下的文件重名就好了
- 我们的
-
然后就可以去命令行执行
sass
这个任务了# 执行 sass 任务 $ gulp sassHandler
打包 JS 文件
-
接下来就是打包一下
js
文件了 -
其实套路是一样的
-
先来做最简单的操作
-
压缩一下
js
文件 -
需要用到一个依赖
npm i -D gulp-uglify
-
然后依旧是去到配置文件中进行配置
const jsHandler = function(){ return gulp.src('./src/js/*.js') .pipe(uglify()) .pipe(gulp.dest('./dist/js')) } module.exports = { jsHandler }
-
然后我们去命令行执行
js
这个任务# 执行 js 任务 $ gulp jsHandler
编译 ES6 语法
- 之前我们学习
es6
的时候就说过 - 很多浏览器不是很认识
es6
的语法 - 我们要把他编译成
es5
的语法 - 所以我们在打包
js
文件的时候,就要转换一下 - 我们依旧是使用依赖来完成,只不过
es6
转es5
需要三个依赖
//注意点:使用8版本报错
npm i -D gulp-babel@7
//babel-core 的作用是把 js 代码分析成 ast ,方便各个插件分析语法进行相应的处理。有些新语法在低版本 js 中是不存在的,如箭头函数,函数默认值等,这种语言层面的不兼容只能通过将代码转为 ast,分析其语法后再转为低版本 js
//ast是源代码语法结构的一种抽象表示。它以树状的形式表现编程语言的语法结构,树上的每个节点都表示源代码中的一种结构
npm i -D babel-core
//可以根据配置的目标浏览器或者运行环境来自动将ES2015+的代码转换为es5
npm i -D babel-preset-env
//用于将部分ES6 语法转换为ES5 语法 箭头函数 class语法 const和let
npm i -D babel-preset-es2015
- 然后我们就去配置文件里面进行配置就可以了
//ES6转ES5
const jsHandler = function(){
return gulp.src('./src/js/*.js')
//在压缩之前先进行转换
.pipe(babel({
presets: ['es2015']
}))
.pipe(uglify())
.pipe(gulp.dest('./dist/js'))
}
module.exports = {
jsHandler
}
-
引入以后,只要在压缩之前执行一下转码就可以了
-
注意要传递一个参数
-
然后再次执行
js
任务就可以了
# 执行 js 任务
$ gulp jsHandler
打包 HTML 文件
-
接下来就要把
html
文件解决一下了 -
还是一个套路
-
压缩
html
文件需要一个依赖npm i -D gulp-htmlmin
-
下载好以后去到配置文件中进行配置
const htmlmin = require('gulp-htmlmin') const htmlHandler = function(){ return gulp.src('./src/**/*.html') .pipe(htmlmin({ removeComments: true,//清除HTML注释 collapseWhitespace: true,//压缩HTML collapseBooleanAttributes: true,//省略布尔属性的值 <input checked="true"/> ==> <input checked /> removeEmptyAttributes: true,//删除所有空格作属性值 <input id="" /> ==> <input /> removeScriptTypeAttributes: false,//删除<script>的type="text/javascript" removeStyleLinkTypeAttributes: true,//删除<style>和<link>的type="text/css" minifyJS: true,//压缩页面JS minifyCSS: true//压缩页面CSS })) .pipe(gulp.dest('./dist/html')) } module.exports = { htmlHandler }
- 这样就配置完毕了
-
接下来就是去命令行运行一下
html
任务# 运行 html 任务 $ gulp htmlHandler
处理 LIBS 和 IMG 文件
-
接下来我们就是处理
libs
和img
里面的文件了 -
因为这些都是第三方的文件和一些图片之类的信息
-
不需要压缩处理,只要给我转到
dist
文件夹下就可以了 -
所以不需要依赖,直接处理就行
const libsHandler = function(){ return gulp.src('./src/libs/**') .pipe(gulp.dest('./dist/libs')) } const imgHandler = function(){ return gulp.src('./src/img/**') .pipe(gulp.dest('./dist/img')) } module.exports = { libsHandler, imgHandler }
-
接下来就是去命令行执行
lib
任务和static
任务# 执行任务 $ gulp libsHandler $ gulp imgHandler
批量执行任务
-
我们的几个和文件相关的任务都配置完毕了
-
但是我们不能在开发过程中一个任务一个任务的去执行
-
不方便也不是很只能
-
所以我们要统一执行任务
-
这个时候就需要进行一个配置,让几个任务一起执行一下
-
这个不需要依赖,我们只需要配置一个叫做
default
的任务 -
gulp
在运行的时候会默认执行default
任务 -
gulp.parallel()
用于并行执行,一起执行(同时) -
gulp.series()
用于串行(顺序)执行,先执行第一个,再执行第二个//配置一个默认任务 module.exports.default = gulp.parallel(sassHandler, jsHandler, htmlHandler, libsHandler, imgHandler) module.exports.default = gulp.series(sassHandler, jsHandler, htmlHandler, libsHandler, imgHandler) 区别: 当使用 parallel() 组合多个任务时,一个任务的错误将结束整个任务组合的结束,但是其他并行的任务可能会执行完,也可能没有执行完。 当使用 series() 组合多个任务时,任何一个任务(task)的错误将导致整个任务组合结束,并且不会进一步执行其他任务。
- 这样配置完毕以后,当你运行
gulp
的时候,会自动执行default
任务 - 然后
default
任务就会把后面数组中写的几个任务并行执行了
- 这样配置完毕以后,当你运行
-
接下来就是去命令行里面运行
gulp
# 运行 gulp,会默认执行 default 任务 $ gulp
清除 DIST 文件夹
-
当你在编译的时候,如果第一次编译有一个叫做
a.css
的文件,他会帮你编译 -
后来你把
a.css
文件改名字了,改叫b.css
,再次进行编译的时候 -
会给你新生成一个
b.css
文件在dist
文件夹中 -
之前的
a.css
文件也不会消失 -
那么这样就不是很好了
-
我们比较好的做法是
- 在执行所有的编译之前
- 先把
dist
文件夹删除掉 - 然后再执行所有的编译操作
-
这样就不会用多余的文件留下了
-
这个时候我们就要使用一个依赖
npm i -D del
-
然后去配置文件里面配置一个任务
//清除任务 const del = require('del') //配置css任务 const delHandler = function(){ return del(['./dist/']) } //按顺序执行任务,先执行完毕删除任务,在执行并行任务 module.exports.default = gulp.series( delHandler, gulp.parallel(sassHandler, jsHandler, htmlHandler, libsHandler, imgHandler) )
-
执行
default
任务# 执行 default 任务 $ gulp
自动打开浏览器
-
我们的打包工作已经完成了
-
接下来要是能再打包完毕自动帮我把浏览器打开就好了
-
省的我自己去开了
-
这个时候是可以做到的
-
需要一个依赖
npm i -D gulp-webserver
-
然后进行配置
//服务器任务 const server = require('gulp-webserver') // 创建一个 webserver 任务 const serverHandler = function () { return gulp .src('./dist') .pipe(server({ host: 'localhost', // 配置打开浏览器的域名 port: 3000, // 配置打开浏览器的端口号 livereload: true, // 自动刷新浏览器 open: './index.html' // 默认打开 dist 文件夹下的哪个文件 })) } module.exports.default = gulp.series( delHandler, gulp.parallel(sassHandler, jsHandler, htmlHandler, libsHandler, imgHandler, server), serverHandler )
- 因为我们打开浏览器应该再所有压缩任务都完成以后
- 再把浏览器打开
- 所以我们把他排在任务的第三个队列上
-
这个
webserver
会自动帮我们启动一个服务器 -
是一个
node
的服务器 -
所以我们的页面也相当于是在服务器上打开的
修改内容自动刷新
-
我们刚才再配置
webserver
的时候有一个自动刷新的功能被我们开启了 -
但是我们修改一些文件的时候发现并没有自动刷新
-
这个是因为,我们只是开启了自动刷新,但是你修改文件以后并没有自动帮我们重新编译
-
那么
dist/
文件夹下的内容就不会更改,那么刷新就没有意义 -
所以我们应该再制作一个任务,当文件夹下的内容修改的时候,自动帮我们从新编译
-
这个不需要任何依赖,我们只需要配置一个监控文件改变的任务就行了
// 创建一个 watch 任务 const watch = function () { gulp.watch('./src/css/**', cssHandler) gulp.watch('./src/sass/**', sassHandler) gulp.watch('./src/js/**', jsHandler) gulp.watch('./src/pages/**', htmlHandler) gulp.watch('./src/lib/**', libsHandler) gulp.watch('./src/static/**', imgHandler) } module.exports.default = gulp.series( delHandler, gulp.parallel(sassHandler, jsHandler, htmlHandler, libsHandler, imgHandler), server watch )
- 因为再文件压缩完毕以后,我们就可以开始监控了
- 所以把这个
watch
任务和webserver
任务并行就可以了
-
接下来我们就可以再命令行运行
gulp
了# 运行 gulp $ gulp
-
这个时候,我们只要进行代码书写就可以了
-
随着我们写完,会自动帮我们打包编译,并且自动进行浏览器刷新的