1. Gulp
-
初始化
package.json
文件yarn init # or npm init
-
安装
gulp
模块yarn add gulp --dev
-
在项目根目录下创建
gulpfile.js
入口文件,在里面定义一些需要gulp
执行的构建任务
2. 基本使用
/*
gulpfile.js
gulp 的入口文件
gulp 的任务函数都是异步的
*/
// 可以通过调用回调函数标识任务完成
exports.foo = done => {
console.log('foo task working~')
done() // 标识任务执行完成
}
// default 是默认任务
// 在运行可以省略任务名参数
exports.default = done => {
console.log('default task working~')
done()
}
// 注意 v4.0 之前需要通过 gulp.task() 方法注册任务
const gulp = require('gulp');
gulp.task('bar', done => {
console.log('bar task working~');
done();
});
gulp-basis
3. 组合任务
const { series, parallel } = require('gulp');
const task1 = done => {
setTimeout(() => {
console.log('task1 working~');
done();
}, 1000)
}
const task2 = done => {
setTimeout(() => {
console.log('task2 working~');
done();
}, 1000)
}
const task3 = done => {
setTimeout(() => {
console.log('task3 working~');
done();
}, 1000);
}
// 让多个任务按照顺序依次执行
exports.foo = series(task1, task2, task3);
// 让多个任务同时执行
exports.bar = parallel(task1, task2, task3);
series
parallel
4. 异步任务
exports.callback = done => {
console.log('callback task~');
done();
}
exports.callback_error = done => {
console.log('callback task');
done(new Error('task failed'));
}
exports.promise = () => {
console.log('promise task');
// resolve()中不需要传入值,因为gulp会自动忽略
return Promise.resolve();
}
// or
exports.promise_error = () => {
console.log('promise task')
return Promise.reject(new Error('task failed'))
}
const timeout = time => {
return new Promise(resolve => {
setTimeout(resolve, time)
})
}
exports.async = async () => {
await timeout(1000);
console.log('async task');
}
exports.stream = () => {
const readStream = fs.createReadStream('package.json');
const writeStream = fs.createWriteStream('temp.txt');
readStream.pipe(writeStream);
return readStream;
}
// => 等价于
exports.stream = () => {
const readStream = fs.createReadStream('package.json');
const writeStream = fs.createWriteStream('temp.txt');
readStream.pipe(writeStream);
readStream.on('end', () => {
done();
});
}
5. Gulp核心工作原理
读取流 -> 插件转换流做处理 -> 写入流
yarn add gulp-clean-css gulp-rename --dev
const { src,dest } = require('gulp');
const cleanCSS = require('gulp-clean-css');
const rename = require('gulp-rename');
exports.default = () => {
return src('src/*.css')
.pipe(cleanCSS()) // 转换为压缩后的代码
.pipe(rename({ extname: '.min.css' })) // 重命名扩展名
.pipe(dest('dist'))
}
6. 样式编译任务
6.1 对所有 scss
文件进行拷贝
const { src,dest } = require('gulp');
const rename = require('gulp-rename');
const style = () => {
return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
.pipe(dest('dist'))
}
module.exports = {
style
}
6.2 安装gulp-sass
对style进行转换
yarn add gulp-sass --dev
安装
gulp-sass
时,会安装node-sass
const sass = require('gulp-sass');
const style = () => {
return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
.pipe(sass({ outputStyle: 'expanded' })) // expanded: 将转换后的样式代码完全展开
.pipe(dest('dist'))
}
注意:
sass
模块工作时会忽略以_
开头的文件,因此这些文件不会被转换
7. js
编译任务
7.1 对所有 js
文件进行拷贝
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(dest('dist'))
}
module.exports = {
style,
script
}
7.2 安装gulp-babel
对js进行转换
const babel = require('gulp-babel');
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(babel())
.pipe(dest('dist'))
}
注意:这里命令行使用
yarn gulp script
后会报Error: Cannot find module '@babel/core'
因为
babel
安装时候不像gulp-sass
那样自动安装了css的转换模块node-sass
babel
只是一个转换平台,我们需要自己去安装转换模块
7.3 安装@babel/core
转换模块和@/babel/preset-env(会将ECMAScript全部的新特性进行转换)
yarn add @babel/core @babel/preset-env --dev
7.4 对js
进行转换
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('dist'))
}
8. HTML
模板文件编译任务
8.1 安装模板引擎转换插件
# 这里使用的是swig模板
yarn add gulp-swig --dev
8.2 对html
进行转换
const swig = require('gulp-swig');
const data = {
menus: [
{
name: 'Home',
icon: 'aperture',
link: 'index.html'
},
{
name: 'Contact',
link: '#',
children: [
{
name: 'About',
link: 'https://weibo.com/zceme'
}
]
}
],
pkg: require('./package.json'),
date: new Date()
}
const page = () => {
// 如果要转换的 html 目录不只在src下,可以使用 src/**/*.html
return src('src/*.html', { base: 'src' })
.pipe(swig({ data }))
.pipe(dest('dist'))
}
module.exports = {
style,
script,
page
}
9. 组合任务
const { src,dest,parallel } = require('gulp');
// paralle 里的任务可以同时执行
const compare = paralle(style, script, page);
module.exports = {
compare
}
10. 图片和字体文件编译任务
10.1 安装gulp-imagemin
yarn add gulp-imagemin --dev
注意:这里可能会报一些
c++
的二进制文件没安装成功
10.2 对图片进行压缩
const imagemin = require('gulp-imagemin');
const image = () => {
return src('src/assets/images/**', { base: 'src' })
.pipe(imagemin())
.pipe(dest('dist'))
}
10.3 对字体进行压缩
const font = () => {
return src('src/assets/fonts/**', { base: 'src' })
.pipe(imagemin())
.pipe(dest('dist'))
}
// paralle 里的任务可以同时执行
const compare = parallel(style, script, page, image, font);
11. 其它文件及文件清除编译任务
11.1 对其它文件进行拷贝
const extra = () => {
return src('public/**', { base: 'public' })
.pipe(dest('dist'))
}
const build = parallel(compare, extra);
module.exports = {
build
}
11.2 自动清除dist
下的文件
1. 安装 del
yarn add del --dev
2. 清除dist下的文件
const { src,dest,parallel, series } = require('gulp');
const del = require('del');
const clean = () => {
return del(['dist'])
}
// series 按顺序依次执行
const build = series(clean, parallel(compare, extra));
module.exports = {
build
}
12. 自动加载插件
12.1 安装gulp-load-plugins
yarn add gulp-load-plugins --dev
12.2 使用
const loadPlugin = require('gulp-load-plugins');
const plugins = loadPlugin();
// 将所有通过 gulp-xx 引入的文件 可以全部替换成 plugins.xx
// example
const babel = require('gulp-babel');
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('dist'))
}
// =>
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('dist'))
}
13 热更新开发服务器
13.1 安装browser-sync
(支持修改代码后自动热更新到浏览器中)
yarn add browser-sync --dev
13.2 使用
const browserSync = require('browser-sync');
const bs = browserSync.create(); // 会自动创建一个开发服务器
const serve = () => {
bs.init({
notify: false, // 取消右上角提示
port: 2000, // 端口,默认 3000
// open: false, // 是否自动打开浏览器
files: 'dist/**', // 监听哪些文件改变后浏览器自动更新
server: {
baseDir: 'dist', // 网站根目录
routes: {
'/node_modules': 'node_modules' // 对打包后的 /node_modules 路径进行处理
}
}
})
}
module.exports = {
build,
serve
}
14. 监视 src
变化以及构建过程优化
14.1 监视 src
各文件变化
const { src,dest,parallel, series, watch } = require('gulp');
const serve = () => {
watch('src/assets/styles/*.scss', style);
watch('src/assets/scripts/*.js', script);
watch('src/*.html', page);
watch('src/assets/image/**', image);
watch('src/assets/fonts/**', font);
watch('public/**', extra);
bs.init({
notify: false,
port: 2000,
// open: false,
files: 'dist/**',
server: {
baseDir: 'dist',
routes: {
'/node_modules': 'node_modules'
}
}
})
}
14.2 构建优化
const serve = () => {
watch('src/assets/styles/*.scss', style);
watch('src/assets/scripts/*.js', script);
watch('src/*.html', page);
/*
watch('src/assets/image/**', image);
watch('src/assets/fonts/**', font);
watch('public/**', extra);
*/
watch([
'src/assets/image/**',
'src/assets/fonts/**',
'public/**'
], bs.reload);
bs.init({
notify: false,
port: 2000,
// open: false,
files: 'dist/**', // 下面介绍不使用 files 来监听
server: {
baseDir: ['dist','src','public'],
routes: {
'/node_modules': 'node_modules'
}
}
})
}
const compare = parallel(style, script, page);
// 上线之前执行的任务
const build = series(clean, parallel(compare, extra, image, font));
// 应该先编译脚本,样式等 在编译 serve
const develop = series(compare, serve);
module.exports = {
clean,
build,
develop
}
// 注意:这部分不是优化,只是有些代码写法不是用 files监听,而是用的以下方式
const style = () => {
return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
.pipe(plugins.sass({ outputStyle: 'expanded' })) // expanded: 将转换后的样式代码完全展开
.pipe(dest('dist'))
.pipe(bs.reload({ stream: true }))
}
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('dist'))
.pipe(bs.reload({ stream: true }))
}
const page = () => {
return src('src/*.html', { base: 'src' })
.pipe(plugins.swig({ data }))
.pipe(dest('dist'))
.pipe(bs.reload({ stream: true }))
}
const serve = () => {
watch('src/assets/styles/*.scss', style);
watch('src/assets/scripts/*.js', script);
watch('src/*.html', page);
watch([
'src/assets/image/**',
'src/assets/fonts/**',
'public/**'
], bs.reload);
bs.init({
notify: false,
port: 2000,
// open: false,
server: {
baseDir: ['dist','src','public'],
routes: {
'/node_modules': 'node_modules'
}
}
})
}
15. useref
文件引用处理
15.1 安装gulp-userg
yarn add gulp-useref --dev
15.2 使用
const useref = () => {
return src('dist/*.html', { base: 'dist' })
.pipe(plugins.useref({ searchPath: ['dist', '.'] })) // 将代码中的构建注释转换
.pipe(dest('dist'))
}
module.exports = {
clean,
build,
develop,
useref
}
16. 文件压缩
16.1 安装html
,js
,css
压缩插件
yarn add gulp-htmlmin gulp-uglify gulp-clean-css --dev
16.2 安装gulp-if
插件对不同文件类型进行判断
yarn add gulp-if --dev
16.3 使用
const useref = () => {
return src('dist/*.html', { base: 'dist' })
.pipe(plugins.useref({ searchPath: ['dist', '.'] })) // 将代码中的构建注释转换
// 压缩html js css
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(plugins.if(/\.html$/, plugins.htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true
})))
.pipe(dest('release')) // 这里不能也写 'dist' 避免读写冲突
}
17. 重新规划构建过程
// gulp 的入口文件
const { src,dest,parallel, series, watch } = require('gulp');
const loadPlugin = require('gulp-load-plugins');
const plugins = loadPlugin();
const del = require('del');
const browserSync = require('browser-sync');
const bs = browserSync.create();
// 网页所需要的数据
const data = { }
const clean = () => {
return del(['dist', 'temp']) // temp: 临时生成的目录
}
const style = () => {
return src('src/assets/styles/*.scss', { base: 'src' }) // 第二个参数:转换的基本路径
.pipe(plugins.sass({ outputStyle: 'expanded' })) // expanded: 将转换后的样式代码完全展开
.pipe(dest('temp'))
.pipe(bs.reload({ stream: true }))
}
const script = () => {
return src('src/assets/scripts/*.js', { base: 'src' })
.pipe(plugins.babel({ presets: ['@babel/preset-env'] }))
.pipe(dest('temp'))
.pipe(bs.reload({ stream: true }))
}
const page = () => {
return src('src/*.html', { base: 'src' })
.pipe(plugins.swig({ data }))
.pipe(dest('temp'))
.pipe(bs.reload({ stream: true }))
}
const image = () => {
return src('src/assets/images/**', { base: 'src' })
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const font = () => {
return src('src/assets/fonts/**', { base: 'src' })
.pipe(plugins.imagemin())
.pipe(dest('dist'))
}
const extra = () => {
return src('public/**', { base: 'public' })
.pipe(dest('dist'))
}
const serve = () => {
watch('src/assets/styles/*.scss', style);
watch('src/assets/scripts/*.js', script);
watch('src/*.html', page);
/* watch('src/assets/image/**', image);
watch('src/assets/fonts/**', font);
watch('public/**', extra);
*/
watch([
'src/assets/image/**',
'src/assets/fonts/**',
'public/**'
], bs.reload);
bs.init({
notify: false,
port: 2000,
// open: false,
// files: 'dist/**',
server: {
baseDir: ['temp','src','public'],
routes: {
'/node_modules': 'node_modules'
}
}
})
}
const useref = () => {
return src('temp/*.html', { base: 'dist' })
.pipe(plugins.useref({ searchPath: ['dist', '.'] })) // 将代码中的构建注释转换
// html js css
.pipe(plugins.if(/\.js$/, plugins.uglify()))
.pipe(plugins.if(/\.css$/, plugins.cleanCss()))
.pipe(plugins.if(/\.html$/, plugins.htmlmin({
collapseWhitespace: true,
minifyCSS: true,
minifyJS: true
})))
.pipe(dest('dist'))
}
const compare = parallel(style, script, page);
// 上线之前执行的任务
const build = series(
clean,
parallel(
series(compare, useref),
extra,
image,
font
)
);
const develop = series(compare, serve);
module.exports = {
clean,
build,
develop
}
// package.json
{
"name": "gulp-cli",
"version": "1.0.0",
"main": "index.js",
"license": "MIT",
"scripts": {
"clean": "gulp clean",
"build": "gulp build",
"develop": "gulp develop"
},
"dependencies": {
"bootstrap": "4.4.1"
},
"devDependencies": {
"@babel/core": "^7.12.3",
"@babel/preset-env": "^7.12.1",
"browser-sync": "^2.26.13",
"del": "^6.0.0",
"gulp": "^4.0.2",
"gulp-babel": "^8.0.0",
"gulp-clean-css": "^4.3.0",
"gulp-htmlmin": "^5.0.1",
"gulp-if": "^3.0.0",
"gulp-imagemin": "^7.1.0",
"gulp-load-plugins": "^2.0.5",
"gulp-sass": "^4.1.0",
"gulp-swig": "^0.9.1",
"gulp-uglify": "^3.0.2",
"gulp-useref": "^4.0.1"
}
}
// .gitignore
dist
temp
网友评论