上一篇的gulp配置很简单,主要就是为了demo的查看和调试,这一篇则会相对详细一些,包括压缩合并打时间戳等。css
在互联网环境比较好的城市,须要多人协做的,大一点的项目应该都用上了模块化(这里主要指commonjs和ES6模块系统,不是再早的require.js和sea.js)。代码也会更注重如何分离和注入,而再也不是单纯的合并。html
可是在不少小公司,开发模式或技术都仍是比较传统的,或者一些小项目也彻底不须要用上那些比较前沿的技术。mongodb
因此这篇配置就主要为了这样的中小项目。express
包管理工具:yarn v0.24.5json
自动化构建工具:gulp v4.0gulp
yarn add global gulpjs/gulp#4.0后端
var gulp = require('gulp'), pug = require('gulp-pug'), less = require('gulp-less'), //当发生异常时提示错误 确保本地安装gulp-notify和gulp-plumber notify = require('gulp-notify'), plumber = require('gulp-plumber'), sourcemaps = require('gulp-sourcemaps'), browserSync = require('browser-sync').create() reload = browserSync.reload; var LessAutoprefix = require('less-plugin-autoprefix'), autoprefix = new LessAutoprefix({ browsers: ['last 2 versions'] }); // 文件路径 var paths = { pug: { src: 'src/pug/pages/*.pug', dest: 'dev/html/', watch: 'src/pug/**/*.pug' }, less: { src: 'src/less/**/*.less', dest: 'dev/css/', watch: 'src/less/**/*.less' }, js: { src: 'src/js/**/*.js', dest: 'dev/js/', watch: 'src/js/**/*.js' }, img: { src: 'src/img/**/*', dest: 'dev/img/', watch: 'src/img/**/*' } } // 启动 browserSync 服务,本身启动server,而且为浏览器实时刷新提供服务 gulp.task('browserSync', function() { return browserSync.init({ server: { baseDir: './' }, files: './dev/**/*' }); }) // 将pug文件转换为html gulp.task('pug', function buildHTML() { return gulp.src(paths.pug.src) .pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')})) .pipe(pug()) .pipe(gulp.dest(paths.pug.dest)); }); // 编译less文件 gulp.task('less', function() { return gulp.src(paths.less.src) .pipe(plumber({errorHandler: notify.onError('Error: <%= error.message %>')})) .pipe(sourcemaps.init()) .pipe(less({ plugins: [autoprefix] })) .pipe(sourcemaps.write()) .pipe(gulp.dest(paths.less.dest)); }) // 复制js文件 gulp.task('js', function() { return gulp.src(paths.js.src) .pipe(gulp.dest(paths.js.dest)); }) // 复制img文件 gulp.task('img', function() { return gulp.src(paths.img.src) .pipe(gulp.dest(paths.img.dest)); }) // 监听文件变化 gulp.task('watch', function() { gulp.watch(paths.pug.watch, gulp.parallel('pug')) gulp.watch(paths.less.watch, gulp.parallel('less')) gulp.watch(paths.js.watch, gulp.parallel('js')) gulp.watch(paths.img.watch, gulp.parallel('img')) }) // 默认任务,在命令行输入`gulp`来启动任务 gulp.task('default', gulp.parallel('watch', 'browserSync', 'pug', 'less', 'js'))
gulp-pug这个插件是用来编译pug模板的,也就是之前的jade模板,pug模板是一个很强大的先后端通用的模板引擎,并且学习也很简单,具体用法能够看我另一篇关于pug的教程文章——基于express+mongodb+pug的博客系统——pug篇。浏览器
你们知道gulp在监放任务的过程当中,若是某个环节出了错误,gulp就会被中断,而后得从新启动gulp任务才行,这是一件很麻烦的事。这里能够经过gulp-notify和gulp-plumber两个插件来避免gulp任务中断。babel
var gulp = require('gulp'), del = require('del'), pug = require('gulp-pug'), less = require('gulp-less'), cleanCSS = require('gulp-clean-css'), base64 = require('gulp-tobase64'), // img64 = require('gulp-imgbase64'), imagemin = require('gulp-imagemin'), babel = require('gulp-babel'), uglify = require('gulp-uglify'), rev = require('gulp-rev'), // 添加时间戳 revCollector = require('gulp-rev-collector'); var LessAutoprefix = require('less-plugin-autoprefix'), autoprefix = new LessAutoprefix({ browsers: ['last 2 versions'] }); // 文件路径 var paths = { pug: { src: 'src/pug/pages/*.pug', dest: 'dist/html/' }, less: { src: 'src/less/main.less', dest: 'dist/css/' }, js: { src: ['src/js/**/*.js', '!src/js/lib/*.js'], dest: 'dist/js/' }, img: { src: 'src/img/**/*', dest: 'dist/img/' } }; // 将pug文件转换为html gulp.task('pug', function() { return gulp.src(paths.pug.src) .pipe(pug()) .pipe(gulp.dest(paths.pug.dest)); }); // 编译less文件 gulp.task('less', function() { return gulp.src(paths.less.src) .pipe(less({ plugins: [autoprefix] })) .pipe(base64({ maxsize: 8 })) .pipe(cleanCSS({ compatibility: 'ie8' // 兼容性前缀保留 })) .pipe(rev()) .pipe(gulp.dest(paths.less.dest)) .pipe(rev.manifest()) .pipe(gulp.dest('rev/css')) }); // 压缩图片 gulp.task('img', function() { return gulp.src(paths.img.src) .pipe(imagemin({ optimizationLevel: 3, progressive: true, interlaced: true })) .pipe(gulp.dest(paths.img.dest)); }); // 编译JS文件 gulp.task('js', function() { return gulp.src(paths.js.src) .pipe(babel({ presets: ['es2015'] })) .pipe(uglify()) .pipe(rev()) .pipe(gulp.dest(paths.js.dest)) .pipe(rev.manifest()) .pipe(gulp.dest('rev/js')); }); // 引用的外部 JS 库,不须要作压缩和打时间戳等处理 // 因此直接复制就行 gulp.task('copyJs', function() { return gulp.src('src/js/lib/*.js') .pipe(gulp.dest('dist/js/lib/')) }) // 替换加了MD5时间戳的文件 gulp.task('rev', gulp.series(gulp.parallel('img64', 'less', 'js'), function() { return gulp.src(['rev/**/*.json', 'dist/html/*.html']) .pipe(revCollector({ replaceReved: true })) .pipe(gulp.dest(paths.pug.dest)); })); // Clean 任务执行前,先清除以前生成的文件 gulp.task('clean', function() { return del('dist/') }); // 默认任务,在命令行输入`gulp`来启动任务 gulp.task('default', gulp.series('clean', gulp.series('img', gulp.parallel('rev', 'copyJs'))))
在生成环境中,代码须要压缩合并,另外在每次代码更新发布新版本时,为了用户客户端能下载更新代码,因此咱们还须要给CSS和JS文件打上时间戳。less
gulp-rev这个插件就专门给文件打MD5戳的,打完MD5戳以后,HTML文件里的引用固然也须要更改,若是每一个都去手动更改确定会是一件很麻烦的事,因此咱们还须要gulp-rev-collector这个插件来帮咱们替换打了MD5戳的文件。
gulp-imgbase64,这个插件能够指定html文件中,哪些img元素转换为base64,须要更加个性化转换的可使用这个插件。
XXX——
| — dist
| — html
| — css
| — img
| — js
| — lib
| — dev
| — html
| — css
| — img
| — js
| — lib
| — src
| — pug
| — components
| — pages
| — layout.pug
| — less
| — pages
| — main.less
| — reset.less
| — common.less
| — feature.less
| — img
| — js
| — lib
src文件夹里是主要的业务代码,这里面是须要长期维护的代码。
dev文件夹是开发时gulp生成代码的地方。
dist文件夹是生成时gulp生成代码的地方。
在这份配置里,我并无像其余不少人那样,把开发时经过gulp生成的代码也放在src文件夹里,由于那样会形成不少引用上的麻烦,并且把开发和生产的代码环境都分开,能很好保持src文件夹里的纯净,不会有任何杂乱代码。
因此一些没通过gulp处理的文件,我会直接把它们复制到dev或者dist文件夹里对应的位置。
dist文件夹在每次gulp任务生成代码前都会被清空,因此咱们不用关心dist文件夹里的内容。
而dev文件夹可能会有不少冗余文件,但咱们也不须要担忧它会对咱们形成任何影响,文件删除或覆盖都不重要,只须要保证src文件夹里的文件正确便可。