上一篇的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文件夾裏的文件正確便可。