使用Gulp构建前端开发环境,适用于多静态页的项目。 主要完成Less与ES6的编译,代码压缩,雪碧图生成、js语法检查与实时刷新。 主要运用了现成的gulp插件并对个别插件代码进行修改以满足个人需求。 首先默认已安装了node与npm,且已熟悉相关用法。
初始化项目
创建package.json
执行
npm init
引导创建一个package.json文件,用来保存项目配置信息与模块依赖。
创建目录结构
dev
|--- css
|--- img
|--- js
dist
|--- css
|--- img
|--- js
src
|--- less
|--- img
|--- js src中为原始代码 dev为目前为简化逻辑做的中间层 dist中为gulp构建代码
安装gulp与相关插件
安装gulp
我们要将gulp安装两次
首先进行全局安装
npm install -g
再切换至项目目录
npm install gulp --save-dev
所有功能依赖插件的安装
我们选择将http-server安装至全局
npm install http-server
其余本地依赖可根据package.json进行npm install
列举部分插件: 编译Less文件(gulp-less) 添加css前缀(gulp-autoprefixer) 压缩css(gulp-minify-css) js代码校验(gulp-jshint) ES6代码编译(gulp-babel、babel-preset-es2015) 合并js文件(gulp-concat) 压缩js代码(gulp-uglify) 雪碧图生成(gulp-css-spriter) 压缩图片(gulp-imagemin) 自动刷新页面(gulp-livereload) 图片缓存(gulp-cache) 任务提醒(gulp-notify)
建立任务
创建gulpfile.js
在根目录下创建gulpfile.js
加载插件
在gulpfile.js中编写
var gulp = require('gulp'),
//less的编译
less = require('gulp-less'),
//雪碧图合成
sprite = require('gulp-css-spriter'),
//自动添加css前缀
autoprefixer = require('gulp-autoprefixer'),
//压缩css
minifycss = require('gulp-minify-css'),
//js代码校验
jshint = require('gulp-jshint'),
//ES6代码编译
babel = require('gulp-babel'),
//压缩js代码
uglify = require('gulp-uglify'),
//图片压缩
imagemin = require('gulp-imagemin'),
rename = require('gulp-rename'),
//合并js文件
concat = require('gulp-concat'),
//更改提醒
notify = require('gulp-notify'),
cache = require('gulp-cache'),
//自动刷新页面
livereload = require('gulp-livereload');
由于除了gulp插件以外,其他的插件需要分别加载比较麻烦,我们可以使用gulp-load-plugins插件来一次性加载所有package.json中所有gulp插件,用法如下。
var gulpLoadPlugins = require('gulp-load-plugins'),
plugins = gulpLoadPlugins();
//此时所有的gulp插件都可以以下方式调用
plugins.jshint();
plugins.uglify();
img相关任务
分两步完成
//完成图片压缩
gulp.task('img', function() {
return gulp.src('src/img/**/*')
.pipe(cache(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })))
.pipe(gulp.dest('dev/img'))
});
//完成除待生成雪碧图外的图片的转移
gulp.task('images', ['img'], function() {
return gulp.src('dev/img/**/[^spicon_]*')
.pipe(gulp.dest('dist/img'))
.pipe(notify({ message: 'Images move complete' }));
});
js相关任务
//出于目前业务流程的考虑未做js合并
gulp.task('scripts', function() {
//js代码校验
return gulp.src('src/js/*.js')
.pipe(jshint())
.pipe(jshint.reporter('default'))
//js代码编译
.pipe(babel({
presets: ['es2015']
}))
.pipe(gulp.dest('dev/js'))
//给文件添加.min后缀
.pipe(rename({ suffix: '.min' }))
//压缩脚本文件
.pipe(uglify())
//输出压缩文件到指定目录
.pipe(gulp.dest('dist/js'))
//提醒任务完成
.pipe(notify({ message: 'Scripts complete' }));
});
css相关任务
//less编译
gulp.task('toCss', function() {
return gulp.src('src/less/*')
.pipe(less())
//添加前缀
.pipe(autoprefixer('last 2 version', 'safari 5', 'ie 8', 'ie 9', 'opera 12.1', 'ios 6', 'android 4'))
.pipe(gulp.dest('dev/css'))
.pipe(notify({message:'toCss complete'}))
});
//处理雪碧图并压缩css
gulp.task('stylesWithSprite',function(){
var timestamp = +new Date();
return gulp.src('dev/css/*.css')
.pipe(spriter({
// 生成的spriter的位置
'spriteSheet': 'dist/img/sprite_'+timestamp+'.png',
// 生成样式文件图片引用地址的路径
'pathToSpriteSheetFromCSS': './img/sprite_'+timestamp+'.png'
}))
// 给文件添加.min后缀
.pipe(rename({ suffix: '.min' }))
//压缩样式文件
.pipe(minifycss())
//输出压缩文件到指定目录
.pipe(gulp.dest('dist/css'))
//提醒任务完成
.pipe(notify({ message: 'Styles complete' }));
})
由于gulp-css-spriter插件会将所有样式名为background-image的图片都合并为雪碧图,不符合我们的需求,而插件未提供相应配置,所以我们需要对其代码做一定修改。 我们设计所需处理为雪碧图的图片命名格式为spicon_.。 找到gulp-css-spriter/lib/map-over-styles-and-transform-background-image-declarations.js 将对应位置添加正则匹配,修改为如下代码
//判断url是否包含spicon_
if(transformedDeclaration.property === 'background-image'&&/spicon_/i.test(transformedDeclaration.value)){
return cb(transformedDeclaration,declarationIndex,declarations);
}
//判断url是否包含spicon_
else if(transformedDeclaration.property === 'background'&&/spicon_/i.test(transformedDeclaration.value)){
var hasImageValue = spriterUtil.backgroundURLRegex.test(transformedDeclaration.value);
if(hasImageValue){
return cb(transformedDeclaration,declarationIndex,declarations);
}
}
并且我们希望生成的雪碧图中有一定的间距,gulp-css-spriter依赖spritesmith插件,前者未提供此配置,而后者中提供了此项配置,我们同样通过修改源代码完成此需求 找到gulp-css-spriter/index.js 将对应部分改为
'spritesmithOptions': {padding:5},
html相关任务
只做了文件复制移动
gulp.task('html', function() {
//js代码校验
return gulp.src('src/*.html')
.pipe(gulp.dest('dev'))
.pipe(gulp.dest('dist'))
//提醒任务完成
.pipe(notify({ message: 'html complete' }));
});
事件监听部分
gulp.task('watch', function() {
gulp.watch('src/less/*.less', ['toCss1']);
gulp.watch('src/less/*.css', ['toCss2']);
gulp.watch('src/*.html', ['html']);
gulp.watch('src/js/*.js', ['jsMove']);
gulp.watch('src/js/my/*', ['scripts']);
gulp.watch('src/images/**/*', ['img']);
livereload.listen();
gulp.watch(['dev/**/*']).on('change', livereload.changed);
});
最终build指令
gulp.task('build', sequence(['images', 'jsMove', 'scripts', 'toCss1','toCss2','html'], 'stylesWithSprite'));
gulp 命令执行
gulp watch
在项目根目录执行指令
gulp watch
;
进入dev目录
执行指令
http-server
;
激活浏览器liveReload扩展程序;
键入localhost:8080/file.html
gulp build
在项目根目录执行
gulp build