使用gulp搭建轻量级前端开发环境
运用背景:使用 React、vue 这些大型前端框架来开发一些复杂交互的页面,第一步搭框架可能就会费很多精力。在中小型项目中,没有复杂交互下,有可能您的网页只是嵌入到大型前端 APP 的一部分,业务逻辑不复杂,更多的只是展示页面,而简单的不用任何的模板框架又不能复用页面的公共部分,一点不大的修改可能涉及到每个页面的变更,严重影响开发效率。如果您正面临此问题,那么您有必要阅读下去,这个使用 Gulp 搭建的框架核心功能是模板复用。
场景分析:但是在我的上一份工作当中由于是混合式的开发,并且项目开始的时候没有去很好的规划,导致项目后期,每个版本的更新上线,总会影响到其他没有修改更新的页面(原因有很多:不小心修改错误、或者调试完之后忘记修改状态等等),这时候我们就将gulp运用到了项目当中,专门针对一些页面弱关联或者简单的h5页面(说明页之类的)
初始化gulp项目
1、在确保你的电脑里装了node的情况下,打开命令行执行以下代码全局安装gulp:
npm install --global gulp
2、初始化项目
npm init
npm install gulp --save-dev
- 命令窗口执行npm init初始化项目,之后你的文件夹中就会自动生成一个package.json文件
- 命令窗口执行npm install gulp --save-dev,在项目当中安装gulp
新建gulpfile.js文件
在根目录下建立gulpfile.js文件,gulpfile.js文件主要放置配置项(图片压缩、js合并压缩、sass引入处理等等),但在写配置项之前我们先要了解一下gulp的一些简单的API
1、gulp.task ------ 创建一个任务
语法:gulp.task('任务名称', done => { // 任务的名称啦
.........
done()
})
2、gulp.src ----- 类似于webpack的entry,匹配找到要执行的任务文件
语法:gulp.src('要执行的任务文件').pipe(对任务文件的操作)
3、 gulp.dest ------ 执行任务的出口
语法:gulp.dest('文件的去处目录')
4、gulp.watch ----- 监测文件的变化
语法:gulp.watch('监测的文件目录', ['执行的操作'])
我们做个简单的demo,感受一下gulp的用法
const gulp = require('gulp')
// 创建一个createDeme的任务
gulp.task('createDemo', done => {
console.log('this is a demo')
gulp.src('./src/**/*.js')
.pipe(gulp.dest(./dist))
done()
})
在命令窗口运行gulp createDemo
以上就是一个最简单的任务,我们将 src 目录下所有的 js 文件通过 pipe(管道) 导流到 dist 目录中,如果当前没有此目录,便会新建一个。
下面我们主要讲一下gulp常用API的用法
一、gulp.task
gulp.task 主要用于创建一个任务,可以接受两个参数
- 任务名称
- 任务函数(可选)或者任务数组(可选)
定义一个任务,需要给这个任务起一个唯一的名字,但我们想要执行这个任务的时候可以执行以下命令
gulp 任务名称
gulp.task的第二个参数可以是一个数组,数组中的值是任务名的集合,当执行此任务的时候会先执行数组中的任务
const gulp = require('gulp');
gulp.task('script', () => {
gulp.src('./src/**/*.js')
.pipe(gulp.dest('./dist'))
})
gulp.task('css', () => {
gulp.src('./src/**/*.css')
.pipe(gulp.dest('./dist'))
})
gulp.task('copy',['script'], () => {
gulp.src(copyPath)
.pipe(gulp.dest('./dist'))
})
gulp.task('default', ['script','css']);
在上面的事例中,在执行copy任务的时候,首先会执行script任务,执行default任务的时候,会先依次执行script和css任务
但是当存在异步操作的时候,下一个任务并不会等到上一个任务完成之后才执行,如下:
gulp.task('default', ['copy','script'])
gulp.task('script', () => {
console.log('script');
})
gulp.task('copy', () => {
console.log('copy1')
setTimeout(() => {
console.log('copy2');
}, 3000);
})
上面的例子中会先输出copy1,依次是script,然后三秒后输出copy2,如果希望copy执行完成之后才执行script,有三种方式:
第一种方式:
// 添加依赖['copy']
gulp.task('script', ['copy'], () => {
console.log('script');
})
gulp.task('copy', (cb) => {
console.log('copy1')
setTimeout(() => {
console.log('copy2');
// 标志异步执行结束
cb();
}, 3000);
})
上面例子中在执行script任务的时候,首先会执行copy任务,回调完成之后才会执行script
第二种方式:
// 添加依赖['copy']
gulp.task('script', ['copy'], () => {
console.log('script');
})
gulp.task('copy', () => {
return gulp.src('./temp/*.js')
// 异步操作文件流
.pipe()
.pipe(gulp.dest('./dist')
})
第三种方式:
const Q = require('q'); //一个著名的异步处理的库 https://github.com/kriskowal/
// 添加依赖['copy']
gulp.task('script', ['copy'], () => {
console.log('script');
})
const deferred = Q.defer();
console.log('copy1')
setTimeout(() => {
console.log('copy2');
deferred.resolve();
}, 3000);
return deferred.promise;
二、gulp.src
gulp.src是一个用于读取文件的API
可以接受一个路径字符串或者数组作为参数来选择所要读取的文件,并输出一个可以被输入到plugins的stream(文件流)
gulp 使用node-glob方式获取匹配文件,常用的几种方式:
glob:是由普通字符和/或通配字符组成的字符串,用于匹配文件路径。可以利用一个或多个 glob 在文件系统中定位文件
- js/app.js 匹配 js 目录下的 app.js 文件
- js/*.js 匹配 js 目录下所有以 .js 结尾的文件
- js/**/*.js 匹配 js 目录及其所有子目录下以 .js 结尾的文件。
- !js/app.js 匹配 js 目录下除 app.js 外的所有文件。
- css/*.{css,less,sass}(逗号后不要加空格) 匹配 css 目录下以 .css , .less , .sass 结尾的文件。
三、gulp.dest
接受一个路径字符串,将返回的管道的中间或者末尾使用的流的对象(Vinyl),写到对用路径文件里面。
在gulp通过src读取文件的时候,都会生成一个Vinyl对象(虚拟文件格式),Vinyl对象用来表示文件的路径、内容、其他元数据等,每个Vinyl对象通过管道(pipe)传递的时候,都可以运用插件进行转换
四、gulp.watch
监听 globs 并在发生更改时运行任务。任务与任务系统的其余部分被统一处理
同 gulp.src ,它接受一个路径字符串或数组作为第一个参数用于选择将要监控文件,第二个参数可以是一个任务列表数组或者回调函数。当监控到文件变化时将会执行它们。
// 假设你已经有一个 script 任务。
gulp.task('watch', () => {
gulp.watch('./view/*.html',['script'])
})
此时运行gulp watch命令,此时但我们的./view/*.html文件发生变化的时候,就会执行script任务
五、plugins
我们通常会使用一些 npm 模块来方便实际开发。这些模块的使用方法也很简单——通过管道流处理文件。
var gulp = require('gulp'),
jshint = require('gulp-jshint'),
uglify = require('gulp-uglify'),
concat = require('gulp-concat');
gulp.task('js', function () {
return gulp.src('js/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'))
.pipe(uglify())
.pipe(concat('app.js'))
.pipe(gulp.dest('build'));
});
在上面的例子中,我们对 js 目录下的 .js 文件依次进行了 jshint()、jshint.reporter()、uglify()、concat()、gulp.dest()操作。
到此,我们已经将gulp的一些常用API大致介绍完了。我们来做个简单的demo,这个demo包括简单的js压缩,文件合并,css压缩,sass功能
const gulp = require('gulp');
const imagemin = require('gulp-imagemin') // 图片压缩
const uglify = require('gulp-uglify') // js压缩
const sass = require('gulp-sass') // sass编译
const concat = require('gulp-concat') // 代码合并
const clean = require('gulp-clean') // 清除dist文件夹
const del = require('del') // 文件删除
const browserSync = require('browser-sync') // 热更新
gulp.task('copyHtml', done => { // 选取src目录下的所有html文件, 输出到dist文件下面
gulp.src('src/view/*.html')
.pipe(gulp.dest('dist'))
done()
})
gulp.task('imagemin', done => { // 选取src/images下面的所有图片
gulp.src('src/images/*')
.pipe(imagemin()) // 调取插件imagemin
.pipe(gulp.dest('dist/images')) // 输出压缩后的图片目录
done()
})
gulp.task('sass', done => {
gulp.src('src/css/*') // 获取scss文件
.pipe(sass().on('error', sass.logError)) // 执行sass插件并检查错误
.pipe(gulp.dest('dist/css')) // 输出scss文件的路径
done()
})
gulp.task('jsOperating', done => { // 合并压缩js文件
gulp.src('src/**/*.js') // 获取js目录下的所有js文件s
.pipe(concat('main.js')) // 合并为main.js文件
.pipe(uglify()) // 压缩js代码
.pipe(gulp.dest('dist/js'))
done()
})
gulp.task('clean', done => {
del('dist/**/*')
done()
})
// 打包
gulp.task('build', gulp.parallel('jsOperating', 'sass', 'imagemin','copyHtml'))
// 监测文件变化及热更新
gulp.task('watch', () => {
browserSync.init({
server: {
baseDir: 'dist' // 在 dist 目录下启动本地服务器环境,自动启动默认浏览器
}
})
gulp.watch('src/js/*.js', gulp.parallel('jsOperating'));
gulp.watch('src/css/*', gulp.parallel('sass'));
gulp.watch('src/view/*.html', gulp.parallel('copyHtml'));
gulp.watch('src/imagemin/*', gulp.parallel('imagemin'));
})
// 默认配置
gulp.task('default', gulp.series('clean', 'build', 'watch'))
- 注:命令行运行gulp -v ,注意自己的全局安装的gulp和本地gulp版本不一样的话,创建watch的任务运用gulp.watch需要运用gulp的series()和parallel()进行嵌套组合才可以运行,否则会报错
这里我把常用的gulp插件列一下
1、gulp-sass(sass编译)
2、gulp-autoprefixer(添加CSS3前缀)
3、gulp-clean-css(压缩CSS)
4、gulp-include(文件包含)
5、gulp-concat(文件合并)
6、del(文件删除)
7、gulp-uglify(压缩js)
8、run-sequence(队列执行)
9、browser-sync(浏览器同步刷新)
10、gulp-babel(js编译)
11、gulp-imagemin(图片压缩)
12、gulp-rename(重命名)
13、gulp-clean(删除文件/文件夹)
14、gulp-htmlmin(html压缩)
15、gulp-if(是否运行插件)
16、require-dir(引入整个文件夹文件)
17、gulp-eslint(eslint代码检查)
18、gulp-eslint(eslint代码检查)
19、gulp-load-plugins(加载gulp插件)
...