了解 gulp
-
前端自动化打包构建工具
- 打包就是把文件 压缩, 整合, 移动, 混淆
-
常用构建工具
- gulp: 基于流的打包构建工具
- webpack: 基于 js 文件的打包构建工具
-
什么是流
- 流文件
- 一种文件传输格式
- 一段一段的文件传输
- 网络在线视频
- 流格式
- 从头到尾的一个过程
- 需要从 源 开始一步步经过加工
- 每一个步骤依赖上一步的结果
- 最终会出一个完整的成品
- gulp 是基于 流格式 的打包工具
- scss => css => 前缀 => 压缩
- 流文件
-
gulp 的依赖环境
- 依赖于 node 环境进行开发
- 底层封装内容就是 node 里面的读写文件(fs 和 http 模块)
-
gulp 的作用
- 对于 css 文件
- 压缩
- 转码( 自动添加前缀, SCSS 转CSS)
- 对于 JS 文件
- 压缩
- 转码( ES6 转 ES5 )
- 对于 html 文件
- 压缩
- 转码( 对格式的转换 )
- 对静态资源文件的处理
- 对第三方文件的处理
- 对于 css 文件
-
gulp 的安装
- 是一个 js 相关的工具
- 直接用 npm 安装
- 需要安装在电脑环境里面, 一次安装 多次使用
- 打开命令行, 输入指令
$ npm install --global gulp
- mac:
$ sudo npm install --global gulp
-
gulp 的检测
gulp --version
-
gulp 的卸载
$ npm uninstall --global gulp
-
gulp 的版本
-
gulp @3.9.1
-
gulp @4 => gulp cli 2.2.0
- 19年1月开始迭代
-
gulp 的使用
源码和打包后的内容
- 源码一般放在 src 文件夹种
- 打包后一般在 dist 文件夹中
- 文件分开是因为打包后要上传服务器, 集中放在一起便于一起上传
1. 准备好一个项目
- 目录结构
- 源码和打包的分开
- 结构
- xiaomi
- src
- pages
- css 正常来说 css 和 sass 文件夹只需要一个
- js
- sass
- images
- videos
- audios
- lib 第三方(swiper, jQuery)
- fonts
- src
- xiaomi
2. 准备一个 gulpfile.js 文件
- 是必需的
- 是 gulp 打包的依据
- 每一个项目都需要一个 gulpfile.js 文件
- 在这个文件里进行本项目的打包配置
- gulp 运行的时候, 会自动读取 gulpfile.js 文件里的配置
- 注意: 直接卸载与 src 同级的根目录
3. 在项目里再次安装 gulp
- 注意: 项目里的 gulp 是以第三方模块的形式出现的
- 是专门配置打包流程的 API
- 在 src 同级的项目文件夹打开命令行 输入
npm init
gulp 分为两种
- 全局依赖 gulp
- 一台电脑安装一次就够,以后使用就可以了
- 在命令行内提供 gulp xxx 的能力
- 任何地方安装 输入
$ npm install --global gulp
- 项目依赖第三方 gulp
- 每个项目都要安装一次
- 作为第三方包引入, 再导入之后, 可以使用
gulp.xxx()
方法- 需要切换到项目目录, 输入
$ npm install gulp
- package.json 记录的第三方依赖
- dependencies
- 表示项目的 项目依赖
- 例如 jQuery, Swiper
- 项目运行需要用的的内容, 将来上线后也需要用到的内容
- devDependencies
- 表示项目的 开发依赖
- 比如 gulp
- 项目开发阶段会用到的, 上线之后不会用
- 所以如果要把 gulp 放在 devDependencies 里面
- 需要在命令行内输入
$ npm install --dev gulp
, 或者$ npm install -D gulp
-
- 需要在命令行内输入
- dependencies
4. 在 gulpfile.js 里书写配置文件
- 书写该项目的打包流程
- 打包完毕之后, 按照打包流程去执行 gulp 指令, 运行 gulpfile.js 文件
gulp 的常用 api
-
gulp.task()
-
语法:
gulp.task(任务名称, 任务处理函数)
-
作用: 创建一个基于流的任务
-
例子
-
gulp.task('htmlHandler', function () { // 找到 html 源文件, 进行压缩打包, 放入指定目录 })
-
-
-
gulp.src()
- 语法:
gulp.src(路径信息)
- 作用:找到源文件
- 书写方式:
gulp.src('./a/b.html')
找到指定文件gulp.src('./a/*.html')
指定目录下, 找到指定后缀文件gulp.src('./a/**')
指定目录下, 所有文件gulp.scr('./a/** /*')
a 目录下, 所有子目录里的所有文件gulp.src('./a/** /*.html')
a 目录下, 所有子目录里所有 指定后缀文件
- 语法:
-
gulp.dest()
- 语法:
gulp.dest(路径信息)
- 作用: 把一个内容放到指定目录内
- 一般是打包好之后, 用这个 api
- 语法:
-
gulp.watch()
-
语法:
gulp.watch(路径信息, 任务名称)
-
作用: 监控指定目录下的文件, 一旦发生变化, 从新执行后面的任务
-
例子:
gulp.watch('./src/pages/*.html', htmlHandler)
- 监控指定目录下的 html 文件变化, 如有变化就执行 htmlHandler 任务
-
-
gulp.series()
- 语法:
gulp.series(任务1, 任务2, 任务3)
- 作用: 执行多个任务, 前一个结束 (流被 return 出去之后)), 后一个开始
- 语法:
-
gulp.parallel()
- 语法:
gulp.parallel(任务1, 任务2, 任务3)
- 作用: 并行执行多个任务
- 语法:
-
pipe()
-
管道函数
-
所有的 gulp API 都是基于流
-
接收当前流, 进入下一个流过程的管道函数
-
例子
-
gulp.src().pipe(压缩任务).pipe(转码).pipe(gulp.dest('./a'))
-
-
-
执行的时候直接在 gulpfile.js 目录下, 打开命令行, 输入
$ npm cssHandler
gulp 常用的插件
- gulp 的插件就是用来执行各种压缩转码任务的
gulp-cssmmin
- 下载:
npm i gulp-cssmin -D
- 导入:
const cssmin = require('gulp-cssmin')
- 导入后得到一个处理流文件的函数
- 直接在管道函数里执行
- 压缩过程中会自动总结重复的样式
gulp-autoprefixer
- 下载:
npm i gulp-autoprefixer
- 导入:
const autoPrefixer = require('gulp-autoprefixer')
- 导入后得到一个处理流文件的函数
- 在管道函数内使用, 需要传递参数
{browsers:[需要兼容的浏览器]}
- 可以不传递参数, 需要在 package.json 里面, 加一项
"browserlist"(小写) = ["last 2 versions","IOS < 7", "FireFox" <20]
gulp-sass
-
下载:
npm i gulp-sass -D
-
很容易报错, 下载不成功
-
原因
- gulp-sass 依赖另一个第三方 node-sass
- node-sass 很难下载成功
-
解决
- 需要给 node-sass 单独配置一个下载地址
$ set sass_binary_site=https://npm.taobao.org/mirrors/node-sass/
$ npm i node-sass -D
$ npm i gulp-sass -D
-
-
导入:
const sass = require('gulp-sass')
- 导入后管道函数内直接执行就可以了
-
sass 转码的使用
- 如果需要导入 sass 文件的时候
- 就把 变量 混合器 定义在 .sass 文件中
- gulp 配置只会转码 .scss 文件
- sass 中的 变量和混合器不会被转码
- 当转码 .scss 文件的时候, 会自动读取和解析 .sass 文件里面的变量
gulp-uglify
-
下载:
npm i -D gulp-uglify
-
导入:
const uglify = require('gulp-uglify')
-
作用: 压缩 js 文件的, 但是不认识 ES6
- 需要用 gulp-babel: 把 ES6 转换成 ES5
- 但有坑
- 需要用 gulp-babel: 把 ES6 转换成 ES5
gulp-babel
- 专门进行 ES6 转 ES5 的插件
- 版本问题
- gulp-babel@7: 使用在 gulp@3 里面
- gulp-babel@8: 使用在 gulp@4 里面
- 下载:
- gulp-babel 需要依赖另外两个包, 都需要下载
- @babel/core 和 @ babel/preset-env
- gulp-babel 需要依赖另外两个包, 都需要下载
- 导入: 导入一个就够, 其它会自动导入
- 在管道函数内使用, 需要传递参数
- 8版本:
{ presets:['@babel/env'] }
- 7版本:
{ presets:['es2015']}
- 8版本:
gulp-htmlmin
- 下载:
npm i -D gulp-htmlmin
- 导入:
const htmlmin = require('gulp-htmlmin')
-
管道函数内使用需要传参, 来决定如何压缩
{collapseWhitespace: true}
移除空格{removeEmptyAttributes: true}
去除空的属性, 仅限于原生属性{collapseBooleanAttributes: true}
checked = “checked” 会变成 checkedremoveAttributesQuotes: true}
移除双引号, 一般 属性 = 后面的值可以不加双引号, 只有多个属性同时存在才必须加{minifyCSS: true}
压缩内嵌式 css 代码, 只能是基本压缩, 不能其它处理{minifyJS: true}
压缩内嵌式 js 代码, 基本压缩, 不能 ES6
图片问题
- 在开发环境中, 图片不需要自己压缩
- 大图片都是线上地址
- UI 处理好的图片, 压缩过了
- 直接
src().pipe(gulp.dest())
- 没必要 下载 gulp-image7
- 7级压缩,无损压缩, 压缩效果不大, 甚至有时候文件变大
视频, 音频和图片一样
- 直接
src().pipe(gulp.dest())
第三方包, 字体等
- 都不需要压缩转码, 直接移到 dist
- 因为 dist 需要是一个完整的项目
配置默认任务
-
默认任务的作用就是把所有任务一起执行
-
是否有先后顺序为判断依据
- 有先后 用 gulp.series()
- 没先后 用 gulp.parallel()
- 两个方法的返回值都是函数, 返回值都可以直接当任务函数使用
-
两种方式创建 default 任务
gulp.task('default', () => {})
module.exports.default = () => {}
-
之所以 需要命名为
default
, 是因为可以直接$gulp
后面不用接任何关键字, 直接运行
创建一个删除任务
- 如果每次打包不删除 dist 文件夹
- 在更改 src 中文件的文件名后, 会重新在 dist 中打包一个新文件名的文件, 而旧文件依然存在
- 所以每次打包之前, 需要执行一个删除 dist 文件夹的任务
插件 del
- 下载:
npm i -D del
- 作用:删除文件目录
- 导入:
const del = require('del')
- 以数组的形式传递要删除的文件夹
gulp 启动服务器
利用 gulp 启动一个服务器
- gulp 是基于 node 环境的工具
- node 可以作为服务器语言
- 所以 gulp 可以启动一个 基于 node 的服务器
- 根目录为 dist
- 如果 src 为根目录, sass 文件没有被转码, 无法使用
'../sass/index.css'
, 无法被找到
- 如果 src 为根目录, sass 文件没有被转码, 无法使用
插件 gulp-webserver
-
作用: 启动一个基于 node 的服务器
-
下载:
npm i -D gulp-webserver
还是在项目根目录 -
导入:
const webserver = require('gulp-webserver')
-
导入后得到一个处理流文件的函数
-
管道函数内调用, 需要传递参数, 来配置服务器
-
const webHandler = function () { return gulp .src('./dist') .pipe(webserver({ host: 'localhost', port: '8080', livereload: true, open: './pages/login.html' // 起始页 })) }
-
-
启动服务配置自定义域名
- 找到电脑中 hosts 文件
C:/windows/system32/drivers/etc/hosts
- 注意: 找到那个没有后缀的 hosts 文件
- 添加一行内容
127.0.0.1 www.xx.com
- 找到电脑中 hosts 文件
gulp-webserver
配置代理
-
proxy: [ { source: "/td", // 代理标识符 target: "https://xxx.com/server", // 代理目标地址 }, ],
-
注意:
- 如果没有多余代理, 不要写空对象
- 如果想用代理, 那么必须是在 gulp-websever 启动的服务器上
- 可以代理一个目录, 目录中所有文件都可以跨域访问
添加监控任务检测文件变化
-
const watchHandler = function () { gulp.watch('./src/sass/*.scss', sassHandler) gulp.watch('./src/css/*.css', cssHandler4) gulp.watch('./src/js/*.js', jsHandler) gulp.watch('./src/pages/*.html', htmlHandler) }
gulp 打包组件
场景
- 把重复的 html 单独拿出来, 写成 html 片段
- 单独拿出来的片段可以包含 css 和 js
- 也可以不包含
- 当压缩 html 的时候
- 在固定位置把写好的 html 片段引入进来
组件
- 一段可以包含 (css / js) 的一整套 html 结构片段
- 把页面的每一部分分成一段一段的 html 片段
- 最后组装在一起
插件 gulp-file-include
-
作用: 在一个 html 页面里导入另一个 html 片段
-
下载:
npm i -D gulp-file-include
还是在项目根目录 -
导入:
const webserver = require('gulp-file-include')
-
导入后得到一个处理流文件的函数
-
管道函数内调用, 压缩之前, 需要传递参数
-
.pipe(fileInclude({ prefix:'@-@', // 标识符 basepath: './src/components/' // 组件目录 }))
-
-
在 html 文件里导入时
-
语法:
自定义标识符include('要导入的文件路径', 'json格式自定义变量')
存疑, 应该是对象格式, key+双引号无法渲染 -
文件路径从 basepath以后开始书写
-
<!-- index.html --> <body> @-@include('./header.html',{ title: '首页', show: 'active'}) <hr> <h1>Index</h1> <hr> @-@include('./footer.html') </body> <!-- header.html --> <div class="header @-@active"> 样式的套用 header <h1>@-@title</h1> </div>
-
常把
<head>
标签也单独拿出来作为组件 -
<!-- index.html --> <head> @-@include('./src/components/head.html', { title: "index"}) </head> <!-- head.html --> <meta charset="UTF-8"> <meta http-equiv="X-UA-Compatible" content="IE=edge"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>@-@title</title>
-
还可以用于 js, css 的引入
-