gulp是前端自动化构建工具之一,可以使用gulp搭建一些不是那么复杂的项目,比如静态官网
1.使用到的依赖
// package.json
{
"name": "gulp",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"start": "cross-env NODE_ENV=development gulp serve",
"build": "cross-env NODE_ENV=production gulp build"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.18.5",
"@babel/plugin-transform-runtime": "^7.18.5",
"@babel/preset-env": "^7.18.2",
"browser-sync": "^2.27.10",
"cross-env": "^7.0.3",
"del": "^6.1.1",
"fs-extra": "^10.1.0",
"gulp": "^4.0.2",
"gulp-autoprefixer": "^8.0.0",
"gulp-babel": "^8.0.0",
"gulp-cssmin": "^0.2.0",
"gulp-dart-sass": "^1.0.2",
"gulp-htmlmin": "^5.0.1",
"gulp-if": "^3.0.0",
"gulp-nunjucks-render": "^2.2.3",
"gulp-sourcemaps": "^3.0.0",
"gulp-uglify": "^3.0.2"
},
"dependencies": {
"@babel/runtime": "^7.18.3"
}
}
2.编译html文件
- 下载依赖
npm i gulp-htmlmin gulp-nunjucks-render -D
在项目根目录中新建gulpfile.js文件,开始编写gulp任务
- html文件主要就是引入模板文件和压缩
const htmlmin = require('gulp-htmlmin'); // 压缩html
const nunjucksRender = require('gulp-nunjucks-render') // render文件
// 页面文件编译
gulp.task('view', function () {
const options = {
removeComments: true, // 清除HTML注释
collapseWhitespace: true, // 压缩HTML
collapseBooleanAttributes: true, // 省略布尔属性
removeEmptyAttributes: true, // 删除所有空属性
removeScriptTypeAttributes: true, // 删除script标签上的type属性
removeAttributeQuotes: true, // 删除属性上的双引号
removeStyleLinkTypeAttributes: true, // 删除style和link标签上的type="text/css"属性
minifyJS: true, // 压缩页面JS
minifyCSS: true // 压缩页面CSS
}
return gulp
.src([srcResolve('**/*.html'), "!**/_*.html"])
.pipe(nunjucksRender({
path: ['src/']
}))
.pipe(gulpIf(isProduct, htmlmin(options)))
.pipe(gulp.dest(BUILD_PATH))
})
- 模板文件的使用
// _template.html
<header>
<h1>Header</h1>
</header>
// index.html
<!DOCTYPE html>
<html lang="en">
<head>
<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>Document</title>
<script src="/jquery-3.6.0.min.js"></script>
<script src="./js/index.js"></script>
</head>
<body>
{% include "template/_header.html" %}
<div id="root">Hello World!!!!</div>
</body>
</html>
3.编译样式文件
- 下载依赖
npm i gulp-cssmin gulp-autoprefixer gulp-dart-sass -D
- 对
css sass等文件的处理就是添加浏览器兼容前缀和压缩
const cssmin = require('gulp-cssmin'); // 压缩css
const autoprefixer = require('gulp-autoprefixer'); // css文件前缀自动补充
const dartSass = require('gulp-dart-sass'); // scss文件编译
// css文件编译
gulp.task('cssmin', function () {
return gulp
.src(srcResolve('**/*.css'))
.pipe(autoprefixer())
.pipe(gulpIf(!isProduct, sourceMaps.init()))
.pipe(gulpIf(isProduct, cssmin()))
.pipe(gulpIf(!isProduct, sourceMaps.write('./')))
.pipe(gulp.dest(BUILD_PATH))
})
// sass编译
gulp.task('sass', function () {
return gulp
.src(srcResolve('**/*.{scss,sass}'))
.pipe(dartSass.sync().on('error', dartSass.logError))
.pipe(autoprefixer())
.pipe(gulpIf(!isProduct, sourceMaps.init()))
.pipe(gulpIf(isProduct, cssmin()))
.pipe(gulpIf(!isProduct, sourceMaps.write('./')))
.pipe(gulp.dest(BUILD_PATH))
})
- 在使用
gulp-autoprefixer依赖之前,需要新建.browserslistrc文件来配置兼容的浏览器
last 2 versions
Android >= 5.0
更多配置可以参考:github.com/browserslis…
4.编译js文件
对于js文件的处理,需要引入babel来转译ES6以上的语法,转译完成后再进行压缩
- 下载babel相关依赖
其中@babel/runtime和@babel/plugin-transform-runtime两个插件是转译generator和async/await语法使用的
npm i @babel/runtime --save
npm i gulp-babel @babel/core @babel/preset-env @babel/plugin-transform-runtime -D
- 下载js压缩的依赖
npm i gulp-uglify -D
- 编写
.babelrc文件
{
"presets": ["@babel/preset-env"],
"plugins": [["@babel/plugin-transform-runtime"]]
}
- 编译js任务
// js文件编译
gulp.task('script', function () {
return gulp.src(srcResolve('**/*.js'))
.pipe(babel())
.pipe(gulpIf(!isProduct, sourceMaps.init()))
.pipe(gulpIf(isProduct, uglify()))
.pipe(gulpIf(!isProduct, sourceMaps.write('./')))
.pipe(gulp.dest(BUILD_PATH))
})
5.图片,多媒体文件的处理
图片和多媒体文件只要直接复制到编译目录即可
// 复制图片文件
gulp.task('image', function () {
return gulp.src(srcResolve('**/*.{png,jpg,jpeg,gif}'))
.pipe(gulp.dest(BUILD_PATH))
})
// 复制视频文件
gulp.task('media', function () {
return gulp
.src(srcResolve('**/*.{mp3,wav,mp4,flv}'))
.pipe(gulp.dest(BUILD_PATH))
})
6.静态目录的处理
在项目一般都有静态文件目录,用于存放一些不用处理的文件(比如jquery),直接复制到dist目录下即可
- 下载复制目录的依赖
npm i fs-extra -D
// 静态文件目录复制(不需要编译的文件放这里,比如jquery)
gulp.task('copy', async function (done) {
try {
await fsExtra.copy('./public/', BUILD_PATH)
console.log('[Copyfiles] Success!')
done()
} catch (error) {
console.log('[Copyfiles] get an error' + error)
}
})
7.本地服务器/监听文件变化
使browser-sync依赖启动本地服务器
- 下载依赖
npm i browser-sync -D
- 编写监听任务
const webServer = require('browser-sync').create();
// 本地服务器/监听任务
gulp.task('watch', function () {
webServer.init({
server: BUILD_PATH,
port: 3000,
watch: true,
open: false,
ui: false,
uglify: false
});
// 文件监听
gulp.watch('./src/**/*.html', gulp.series('view', (done) => {
webServer.reload();
done();
}));
gulp.watch('./src/**/*.js', gulp.series('script', (done) => {
webServer.reload();
done();
}))
gulp.watch('./src/**/*.css', gulp.series('cssmin', (done) => {
webServer.reload();
done();
}))
gulp.watch('./src/**/*.{scss,sass}', gulp.series('sass', (done) => {
webServer.reload()
done();
}))
gulp.watch('./src/**/*.{png,jpg,jpeg,gif}', gulp.series('image', (done) => {
webServer.reload()
done()
}))
})
8.清除目录任务
- 下载依赖
npm i del -D
- 编写任务
const del = require('del'); // 清空目录
// 清空目录
gulp.task('clean', async function (done) {
try {
await del([BUILD_PATH]);
console.log('[CleanFile] Success!')
done();
} catch (error) {
console.log('[CleanFile] get an error' + error);
}
});
9.项目中的其它代码
// 是否生产环境
const isProduct = process.env.NODE_ENV === 'production'
// 源码目录
const SRC_PATH = path.resolve(__dirname, 'src');
// 构建目录
const BUILD_PATH = path.resolve(__dirname, 'dist')
/**
* 源码目录拼接文件后缀方法
* @param {String} dir
* @returns
*/
function srcResolve(dir) {
return path.resolve(SRC_PATH, dir);
}
10.编写启动脚本
// 本地任务
gulp.task('serve', gulp.series('clean', gulp.parallel('copy', 'image', 'media', 'view', 'script', 'cssmin', 'sass'), 'watch'))
// 编译任务
gulp.task('build', gulp.series('clean', gulp.parallel('copy', 'image', 'media', 'view', 'script', 'cssmin', 'sass')))
11.完整的配置代码
const gulp = require('gulp'); // gulp
const htmlmin = require('gulp-htmlmin'); // 压缩html
const uglify = require('gulp-uglify'); // 压缩js
const babel = require('gulp-babel'); // babel
const webServer = require('browser-sync').create(); // 本地服务器
const del = require('del'); // 清空目录
const fsExtra = require('fs-extra'); // 复制文件夹
const nunjucksRender = require('gulp-nunjucks-render') // render文件
const cssmin = require('gulp-cssmin'); // 压缩css
const autoprefixer = require('gulp-autoprefixer'); // css文件前缀自动补充
const dartSass = require('gulp-dart-sass'); // scss文件编译
const gulpIf = require('gulp-if');
const sourceMaps = require('gulp-sourcemaps'); // 生成map文件
const path = require('path');
// 是否生产环境
const isProduct = process.env.NODE_ENV === 'production'
// 源码目录
const SRC_PATH = path.resolve(__dirname, 'src');
// 构建目录
const BUILD_PATH = path.resolve(__dirname, 'dist')
/**
* 源码目录拼接文件后缀方法
* @param {String} dir
* @returns
*/
function srcResolve(dir) {
return path.resolve(SRC_PATH, dir);
}
// 清空目录
gulp.task('clean', async function (done) {
try {
await del([BUILD_PATH]);
console.log('[CleanFile] Success!')
done();
} catch (error) {
console.log('[CleanFile] get an error' + error);
}
});
// 静态文件目录复制(不需要编译的文件放这里,比如jquery)
gulp.task('copy', async function (done) {
try {
await fsExtra.copy('./public/', BUILD_PATH)
console.log('[Copyfiles] Success!')
done()
} catch (error) {
console.log('[Copyfiles] get an error' + error)
}
})
// 复制图片文件
gulp.task('image', function () {
return gulp.src(srcResolve('**/*.{png,jpg,jpeg,gif}'))
.pipe(gulp.dest(BUILD_PATH))
})
// 复制视频文件
gulp.task('media', function () {
return gulp
.src(srcResolve('**/*.{mp3,wav,mp4,flv}'))
.pipe(gulp.dest(BUILD_PATH))
})
// 页面文件编译
gulp.task('view', function () {
const options = {
removeComments: true, // 清除HTML注释
collapseWhitespace: true, // 压缩HTML
collapseBooleanAttributes: true, // 省略布尔属性
removeEmptyAttributes: true, // 删除所有空属性
removeScriptTypeAttributes: true, // 删除script标签上的type属性
removeAttributeQuotes: true, // 删除属性上的双引号
removeStyleLinkTypeAttributes: true, // 删除style和link标签上的type="text/css"属性
minifyJS: true, // 压缩页面JS
minifyCSS: true // 压缩页面CSS
}
return gulp
.src([srcResolve('**/*.html'), "!**/_*.html"])
.pipe(nunjucksRender({
path: ['src/']
}))
.pipe(gulpIf(isProduct, htmlmin(options)))
.pipe(gulp.dest(BUILD_PATH))
})
// js文件编译
gulp.task('script', function () {
return gulp.src(srcResolve('**/*.js'))
.pipe(babel())
.pipe(gulpIf(!isProduct, sourceMaps.init()))
.pipe(gulpIf(isProduct, uglify()))
.pipe(gulpIf(!isProduct, sourceMaps.write('./')))
.pipe(gulp.dest(BUILD_PATH))
})
// css文件编译
gulp.task('cssmin', function () {
return gulp
.src(srcResolve('**/*.css'))
.pipe(autoprefixer())
.pipe(gulpIf(!isProduct, sourceMaps.init()))
.pipe(gulpIf(isProduct, cssmin()))
.pipe(gulpIf(!isProduct, sourceMaps.write('./')))
.pipe(gulp.dest(BUILD_PATH))
})
// sass编译
gulp.task('sass', function () {
return gulp
.src(srcResolve('**/*.{scss,sass}'))
.pipe(dartSass.sync().on('error', dartSass.logError))
.pipe(autoprefixer())
.pipe(gulpIf(!isProduct, sourceMaps.init()))
.pipe(gulpIf(isProduct, cssmin()))
.pipe(gulpIf(!isProduct, sourceMaps.write('./')))
.pipe(gulp.dest(BUILD_PATH))
})
// 本地服务器/监听任务
gulp.task('watch', function () {
webServer.init({
server: BUILD_PATH,
port: 3000,
watch: true,
open: false,
ui: false,
uglify: false
});
// 文件监听
gulp.watch('./src/**/*.html', gulp.series('view', (done) => {
webServer.reload();
done();
}));
gulp.watch('./src/**/*.js', gulp.series('script', (done) => {
webServer.reload();
done();
}))
gulp.watch('./src/**/*.{png,jpg,jpeg,gif}', gulp.series('image', (done) => {
webServer.reload()
done()
}))
gulp.watch('./src/**/*.css', gulp.series('cssmin', (done) => {
webServer.reload();
done();
}))
gulp.watch('./src/**/*.{scss,sass}', gulp.series('sass', (done) => {
webServer.reload()
done();
}))
})
// 本地任务
gulp.task('serve', gulp.series('clean', gulp.parallel('copy', 'image', 'media', 'view', 'script', 'cssmin', 'sass'), 'watch'))
// 编译任务
gulp.task('build', gulp.series('clean', gulp.parallel('copy', 'image', 'media', 'view', 'script', 'cssmin', 'sass')))