一、简介
-
前端常见打包构建工具:
gulp
、webpack
…gulp
是基于流
的打包构建工具。webpack
是基于js
文件的打包构建工具。
-
什么是
流
?-
流文件
:一种文件传输的格式,一段一段的文件传输,全部下载完成后再转换成指定文件格式,例如视频、音频、压缩包下载。 -
流格式
:从头到尾的一个过程,从源
开始一步一步,每一个步骤都需要依赖上一步的结果,最终给出一个完成的成品。
gulp
是基于流
格式的一种打包构建工具。 -
-
依赖环境
-
依赖与
node
环境进行开发 -
底层封装的内容主要用到了
node
里面的文件读写(http
、fs
)
-
-
作用
-
对于
css
文件可以进行压缩,转码(自动添加前缀)
(例如:scss -》css -》添加前缀 -》压缩 ....
) 。 -
对于
js
文件可以进行压缩,转码(ES6 转 ES5)
。 -
对于
html
文件可以进行压缩,转码(对格式的转换)
。 -
对于
静态资源文件
的处理,对于第三方文件
的处理 …
-
二、安装
-
gulp
使用的主流版本分为gulp@3.x
、gulp@4.x
,本篇使用4.x
版本。 -
安装
# 安装全局 gulp,基础库,如果不安装全局会报错 # zsh: command not found: gulp $ npm i gulp -g # 如果 mac 有权限限制的话,用这个 $ sudo npm i gulp -g # 安装项目 gulp,基础库 $ npm i gulp -D
后续
gulp
的插件(用于压缩css
、js
等任务要用到的)都安装到devDependencies
。 -
检查是否安装成功(
4.x
输出的是cli
版本号,3.x
输出的是gulp 3.9.0
版本号)$ gulp -v CLI version: 2.3.0 Local version: Unknown
-
运行指令(下面案例中体现使用场景)
$ gulp xxx
-
创建一个
gulpfile.js
文件,这个是gulp
配置文件,后续的执行任务都写在这个配置文件中,gulp
会执行一遍配置中的任务。
三、常用 API
gulp 的常用 API
+ 前提: 下载 gulp 第三方, 导入以后使用
1. gulp.task()
=> 语法: gulp.task(任务名称, 任务处理函数)
=> 作用: 创建一个基于流的任务
=> 例子: gulp.task('htmlHandler', function () {
// 找到 html 源文件, 进行压缩, 打包, 放入指定目录
})
2. gulp.src()
=> 语法: gulp.src(路径信息)
=> 作用: 找到源文件
=> 书写方式
2-1. gulp.src('./a/b.html')
-> 找到指定一个文件
2-2. gulp.src('./a/*.html')
-> 找到指定目录下, 指定后缀的文件
2-3. gulp.src('./a/**')
-> 找到指令目录下的所有文件
2-4. gulp.src('./a/** /*')
-> 找到 a 目录下所有子目录里面的所有文件
2-5. gulp.src('./a/** /*.html')
-> 找到 a 目录下所有子目录里面的所有 .html 文件
3. gulp.dest()
=> 语法: gulp.dest(路径信息)
=> 作用: 把一个内容放入指定目录内
=> 例子: gulp.dest('./abc')
-> 把他接收到的内容放到 abc 目录下
4. gulp.watch()
=> 语法: gulp.watch(路径信息, 任务名称)
=> 作用: 监控指定目录下的文件, 一旦发生变化, 从新执行后面的任务
=> 例子: gulp.watch('./src/pages/*.html', htmlHandler)
-> 当指定目录下的 html 文件发生变化, 就会执行 htmlHandler 这个任务
5. gulp.series()
=> 语法: gulp.series(任务1, 任务2, 任务3, ...)
=> 作用: 逐个执行多个任务, 前一个任务结束, 第二个任务开始
6. gulp.parallel()
=> 语法: gulp.parallel(任务1, 任务2, 任务3, ...)
=> 作用: 并行开始多个任务
7. pipe()
=> 管道函数
=> 所有的 gulp API 都是基于流
=> 接收当前流, 进入下一个流过程的管道函数
=> 例子:
gulp.src().pipe(压缩任务).pipe(转码).pipe(gulp.dest('abc'))
三、常用插件
gulp 常用插件
+ gulp 的各种插件就是用来执行各种各样的压缩混淆转码任务的
1. gulp-cssmin
=> 下载: npm i gulp-cssmin -D
=> 导入: const cssmin = require('gulp-cssmin')
=> 导入以后得到一个处理流文件的函数
=> 直接再管道函数里面执行就好了
2. gulp-autoprefixer
=> 下载: npm i gulp-autoprefixer -D
=> 导入: const autoPrefixer = require('gulp-autoprefixer')
=> 导入以后得到一个处理流文件的函数
=> 直接再管道函数里面使用, 需要传递参数
-> { browsers: [要兼容的浏览器] }
3. gulp-sass
=> 下载: npm i gulp-sass -D
-> 很容易报错, 基本下载不成功
-> 为什么: 因为 gulp-sass 依赖另一个第三方, node-sass
=> node-sass 很难下载成功
=> 以前都是再一个地方下载, 后来 node-sass 自己单独有一个下载地址
=> 如果不进行单独的 node-sass 下载地址配置, 就很容易失败
-> 解决: 给 node-sass 单独配置一个下载地址
=> 下载 node-sass 从这个单独的地址下载, 下载其他的东西还是统一地址
-> node-sass 单独下载地址
=> $ set SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/
=> 单独配置一个下载地址, 只有下载 node-sass 的时候会使用
-> 过程
1. $ set SASS_BINARY_SITE=https://npm.taobao.org/mirrors/node-sass/
2. $ npm i node-sass -D
3. $ npm i gulp-sass -D
=> 导入: const sass = require('gulp-sass')
=> 导入以后得到一个可以处理流文件的函数, 直接再管道函数里面执行就可以了
4. gulp-uglify
=> 把 JS 文件压缩的
=> 下载: npm i -D gulp-uglify
=> 导入: const uglify = require('gulp-uglify')
=> 导入以后得到一个可以处理流文件的函数
=> 直接再管道函数中使用就可以了
=> 注意: 你不能写 ES6 语法, 一旦有了 ES6 语法就会报错
5. gulp-babel
=> 专门进行 ES6 转 ES5 的插件
=> gulp-babel 的版本
-> gulp-babel@7: 大部分使用再 gulp@3 里面
-> gulp-babel@8: 大部分使用再 gulp@4 里面
=> 下载:
-> gulp-babel 需要依赖另外两个包, 要一起下载
-> 另外两个包: @babel/core @babel/preset-env
=> 导入:
-> 只要导入一个包就够了, 他会自动导入另外两个包
-> const babel = require('gulp-babel')
=> 导入以后得到一个可以处理流文件的函数
=> 直接再管道函数内部使用, 需要传递参数
6. gulp-htmlmin
=> 下载: npm i -D gulp-htmlmin
=> 导入: const htmlmin = require('gulp-htmlmin')
=> 导入以后得到一个可以处理流文件的函数
=> 直接再管道函数里面调用, 需要传递参数
7. del
=> 下载: npm i -D del
=> 作用: 删除文件目录
=> 导入: const del = require('del')
=> 导入以后得到一个函数, 直接使用传递参数就可以了
8. gulp-webserver
=> 作用: 启动一个基于 node 书写的服务器
=> 下载: npm i -D gulp-webserver
=> 导入: const webserver = require('gulp-webserver')
=> 导入以后得到一个处理流文件的函数
=> 在管道函数内调用就可以了, 需要传递参数
9. gulp-file-include
=> 作用: 再一个 html 页面里面导入一个 html 片段
=> 下载: npm i -D gulp-file-include
=> 导入: const fileInclude = require('gulp-file-include')
=> 导入以后得到一个处理流文件的函数
=> 在管道函数内调用就可以了, 需要传递参数
三、案例需求
-
打包自己的项目
1、要确定好自己的目录结构
2、要分开源码和打包后的内容
例如:打包
pages/index.html
代码,打包完毕放在哪?同级目录下,再次创建叫做
pages
的文件夹?不行
,因为不能创建同名文件夹。同级目录下,创建叫做
views
的文件夹?不行
,因为页面中的资源路径会找不到,路径变了。必须要保证打爆前后的目录接口一致,这样才不会导致资源文件路径找不到等问题:
-
创建一个叫做
src
的目录(表示源码) -
创建一个叫做
dist
的目录(存放打包后的文件)
-
-
案例项目结构
- my_project 项目 - dist 打包文件(没有会自行创建,每次打包会删除在重新创建) - src 源码 + pages html + css css + js js + sass sass(需要将 sass 转成 css 进行使用) + images 图片 + videos 视频 + audios 音频 + lib 第三方文件 + fonts 字体图标文件
-
案例项目
gulpfile.js
配置// gulp 配置文件 // 0. 导入第三方 // 0-1. 导入 gulp const gulp = require('gulp') // 0-2. 导入 gulp-cssmin const cssmin = require('gulp-cssmin') // 0-3. 导入 gulp-autoprefixer const autoPrefixer = require('gulp-autoprefixer') // 0-4. 导入 gulp-sass const sass = require('gulp-sass') // 0-5. 导入 gulp-uglify const uglify = require('gulp-uglify') // 0-6. 导入 gulp-babel const babel = require('gulp-babel') // 0-7. 导入 gulp-htmlmin const htmlmin = require('gulp-htmlmin') // 0-8. 导入 del const del = require('del') // 0-9. 导入 gulp-webserver const webserver = require('gulp-webserver') // 0-10. 导入 gulp-file-include const fileInclude = require('gulp-file-include') // 1. 创建任务 // 1-1. 创建一个打包 css 的任务 const cssHandler = function () { return gulp .src('./src/css/*.css') // 1. 找到内容 .pipe(autoPrefixer()) // 2. 自动添加前缀 .pipe(cssmin()) // 3. 压缩 .pipe(gulp.dest('./dist/css/')) // 4. 放到指定目录 } // 1-2. 创建一个打包 sass 文件的任务 const sassHandler = function () { return gulp .src('./src/sass/*.scss') .pipe(sass()) .pipe(autoPrefixer()) .pipe(cssmin()) .pipe(gulp.dest('./dist/sass/')) } // 1-3. 创建一个打包 js 文件的任务 const jsHandler = function () { return gulp .src('./src/js/*.js') // 1. 找到 js 文件 .pipe(babel({ // babel@7, presets: ['es2015'] presets: ['@babel/env'] })) .pipe(uglify()) .pipe(gulp.dest('./dist/js/')) } // 1-4. 创建一个打包 html 文件的任务 const htmlHandler = function () { return gulp .src('./src/pages/*.html') // .pipe(fileInclude({ // 根据你的配置导入对应的 html 片段,也就是组件 // prefix: '@-@', // 你自定义的一个标识符 // basepath: './src/components' // 基准目录, 你的组件文件都在哪一个目录里面 // })) .pipe(htmlmin({ // 通过你配置的参数来进行压缩 // collapseWhitespace: true, // 表示移出空格 removeEmptyAttributes: true, // 表示移出空的属性(仅限于原生属性) collapseBooleanAttributes: true, // 移出 checked 类似的布尔值属性 removeAttributeQuotes: true, // 移出属性上的双引号 minifyCSS: true, // 压缩内嵌式 css 代码(只能基本压缩, 不能自动添加前缀) minifyJS: true, // 压缩内嵌式 JS 代码(只能基本压缩, 不能进行转码) removeStyleLinkTypeAttributes: true, // 移出 style 和 link 标签上的 type 属性 removeScriptTypeAttributes: true, // 移出 script 标签上默认的 type 属性 })) .pipe(gulp.dest('./dist/pages/')) } // 1-5. 创建一个打包 images 文件的任务 const imgHandler = function () { return gulp .src('./src/images/**') .pipe(gulp.dest('./dist/images/')) } // 1-6. 创建一个打包 videos 文件的任务 const videoHandler = function () { return gulp .src('./src/videos/**') .pipe(gulp.dest('./dist/videos/')) } // 1-7. 创建一个打包 audios 文件的任务 const audioHandler = function () { return gulp .src('./src/audios/**') .pipe(gulp.dest('./dist/audios/')) } // 1-8. 创建一个打包 第三方 的任务 const libHandler = function () { return gulp .src('./src/lib/**/*') .pipe(gulp.dest('./dist/lib/')) } // 1-9. 创建一个打包 fonts 文件的任务 const fontHandler = function () { return gulp .src('./src/fonts/**/*') .pipe(gulp.dest('./dist/fonts/')) } // 1-10. 创建一个删除 dist 目录的任务 const delHandler = function () { // del 直接执行就可以了, 不需要流 // 参数以数组的形式传递你要删除的文件夹 return del(['./dist/']) } // 1-11. 创建一个启动 服务器 的任务 const webHandler = function () { return gulp .src('./dist') .pipe(webserver({ host: 'www.gx.com', // 域名(可以配置自定义域名) port: '8080', // 端口号 livereload: true, // 当文件修改的时候, 是否自动刷新页面 open: './pages/login.html', // 默认打开哪一个文件(从 dist 目录以后的目录开始书写) proxies: [ // 配置你的所有代理 // 每一个代理就是一个对象数据类型 // 注意: 如果你没有代理, 不要写空对象 { // 代理标识符 source: '/dzm1', // 代理目标地址 target: 'https://www.dzm.com/api/' }, { source: '/dzm2', target: 'https://www.xyq.com/api/' }, { source: '/dzm3', target: 'https://www.xxx.com/api/' } ] })) } // 1-12. 创建一个监控任务 const watchHandler = function () { // 使用 gulp.watch() gulp.watch('./src/sass/*.scss', sassHandler) gulp.watch('./src/css/*.css', cssHandler) gulp.watch('./src/js/*.js', jsHandler) gulp.watch('./src/pages/*.html', htmlHandler) } // 2. 导出任务(这种单个导出需要单个执行) // 2-1. 导出打包 css 的任务 // module.exports.cssHandler = cssHandler // // 2-2. 导出打包 sass 的任务 // module.exports.sassHandler = sassHandler // // 2-3. 导出打包 js 的任务 // module.exports.jsHandler = jsHandler // // 2-4. 导出打包 html 的任务 // module.exports.htmlHandler = htmlHandler // // 2-5. 导出打包 images 的任务 // module.exports.imgHandler = imgHandler // // 2-6. 导出打包 videos 的任务 // module.exports.videoHandler = videoHandler // // 2-7. 导出打包 audios 的任务 // module.exports.audioHandler = audioHandler // // 2-8. 导出打包 第三方 的任务 // module.exports.libHandler = libHandler // // 2-9. 导出打包 fonts 的任务 // module.exports.fontHandler = fontHandler // // 2-10. 导出删除 dist 目录的任务 // module.exports.delHandler = delHandler // 3. 配置一个默认任务 // 默认任务的作用就是把所有的任务一起执行了 // 要么使用 gulp.series(), 要么使用 gulp.parallel() // 这两个方法的返回值是一个函数, 返回值可以直接被当作任务函数使用 // 使用 task 的方式创建一个 default 任务 // 方式1: // gulp.task('default', () => {}) // 方式2: // module.exports.default = () => {} // 举例:创建一个默认任务(这种就可以一起执行,不需要单个导出执行) // module.exports.default = gulp.parallel(cssHandler, sassHandler, jsHandler, htmlHandler, imgHandler, videoHandler, audioHandler, libHandler, fontHandler) // 配置一个默认任务 // 这个是完整的流程:1、删除dist 2、创建压缩到dist 3、启用本地代理(也可以使用 nginx 代替)4、热更新监听文件变化进行编译 module.exports.default = gulp.series( delHandler, gulp.parallel(cssHandler, sassHandler, jsHandler, htmlHandler, imgHandler, videoHandler, audioHandler, libHandler, fontHandler), webHandler, watchHandler )
-
组件使用案例,不清楚可自行查查。