1. 程式人生 > >Gulpfile.js任務分析

Gulpfile.js任務分析

//引入gulp
const gulp = require('gulp');  
//自動載入配置檔案中的已安裝外掛,不需要一個一個require(package.json中宣告的依賴)
const gulpLoadPlugins = require('gulp-load-plugins');   
//瀏覽器同步,快速響應檔案更改並自動重新整理頁面
const browserSync = require('browser-sync').create();  
//清除檔案,支援一個回撥函式,類似grunt-contrib-clean 
const del = require('del');  
//將bower.json中安裝的庫及依賴(dependence)引進html中,通過識別HTML的註釋來識別插入位置
const wiredep = require('wiredep').stream;  
//task非同步併發執行,解除任務間的依賴,增強task複用,一連串task順序執行,[]表示可併發執行
const runSequence = require('run-sequence');  

const $ = gulpLoadPlugins();
const reload = browserSync.reload;

var dev = true;

//預編譯Sass
gulp.task('styles', () => {
  return gulp.src('app/styles/*.scss')  //指明原始檔路徑 讀取其資料流
    .pipe($.plumber())          //錯誤處理,替換錯誤的pipe方法,使資料流正常執行
    .pipe($.if(dev, $.sourcemaps.init()))  //壓縮環境出現錯誤能找到未壓縮的錯誤來源
    .pipe($.sass.sync({             //預編譯Sass
      outputStyle: 'expanded',         //outputStyle : 巢狀輸出-- nested ,展開輸出 ----expanded,緊湊輸出 ——--compact,壓縮輸出 --- compressed
      precision: 10,                   //precision : 精度,小數後10位
      includePaths: ['.']              // 指明載入的@import scss的包含路徑
    }).on('error', $.sass.logError))
    //自動匹配瀏覽器支援的字尾,市場份額,每個瀏覽器最後2個版本,火狐版本
    .pipe($.autoprefixer({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']}))  
    .pipe($.if(dev, $.sourcemaps.write()))   //map檔案命名
    .pipe(gulp.dest('.tmp/styles'))    //指定輸出路徑
    .pipe(reload({stream: true}));     // 任務完成後重新整理頁面
});

//轉化ES6的JS
gulp.task('scripts', () => {
  return gulp.src('app/scripts/**/*.js')
    .pipe($.plumber())
    .pipe($.if(dev, $.sourcemaps.init()))       //初始化
    .pipe($.babel())                            // 編譯,ES6轉為ES5
    .pipe($.if(dev, $.sourcemaps.write('.')))   //生成sourcemap檔案,路徑為.
    .pipe(gulp.dest('.tmp/scripts'))
    .pipe(reload({stream: true}));              
});

function lint(files) {
  return gulp.src(files)
    .pipe($.eslint({ fix: true }))
    .pipe(reload({stream: true, once: true}))
    .pipe($.eslint.format())
    .pipe($.if(!browserSync.active, $.eslint.failAfterError()));
}

gulp.task('lint', () => {
  return lint('app/scripts/**/*.js')
    .pipe(gulp.dest('app/scripts'));
});
gulp.task('lint:test', () => {
  return lint('test/spec/**/*.js')
    .pipe(gulp.dest('test/spec'));
});

//將CSS合併壓縮,JS合併壓縮,html壓縮,加上時間戳避免快取
gulp.task('html', ['styles', 'scripts'], () => {  ////先執行styles scripts任務
  return gulp.src('app/*.html')
   //useref:根據註釋將HTML需要合併壓縮的區塊找出來並對檔案進行合併,不負責程式碼壓縮
    .pipe($.useref({searchPath: ['.tmp', 'app', '.']})) 
    .pipe($.if(/\.js$/, $.uglify({compress: {drop_console: true}})))
    .pipe($.if(/\.css$/, $.cssnano({safe: true, autoprefixer: false})))
    .pipe($.if(/\.html$/, $.htmlmin({
      collapseWhitespace: true, //壓縮HTML
      minifyCSS: true,  //壓縮頁面裡的CSS
      minifyJS: {compress: {drop_console: true}},  //壓縮頁面裡的JS
      processConditionalComments: true,
      removeComments: true,   //清除HTML註釋
      removeEmptyAttributes: true,  //刪除所有空格作屬性值
      removeScriptTypeAttributes: true, //刪除<script>的type="text/javascript"
      removeStyleLinkTypeAttributes: true  //刪除<style>和<link>的type="text/css"
    })))
    .pipe(gulp.dest('dist'));
});

//壓縮圖片,通過對比圖片大小,可以看出壓縮了多少
gulp.task('images', () => {
  return gulp.src('app/images/**/*')
    .pipe($.cache($.imagemin()))         //使用gulp-cache只壓縮修改的圖片,沒有修改的圖片直接從快取檔案讀取
    .pipe(gulp.dest('dist/images'));
});

//引用字型檔案
gulp.task('fonts', () => {
  ////main-bower-files會從bower.json檔案裡尋找定義好的主要檔案路徑
  return gulp.src(require('main-bower-files')('**/*.{eot,svg,ttf,woff,woff2}', function (err) {})
    .concat('app/fonts/**/*')) ////將bootstrap-sass的fonts和app下我們自己選用的fonts合併起來
    .pipe($.if(dev, gulp.dest('.tmp/fonts'), gulp.dest('dist/fonts')));
});

gulp.task('extras', () => {
  return gulp.src([
    'app/*',
    '!app/*.html'
  ], {
    dot: true
  }).pipe(gulp.dest('dist'));
});

//刪除任務
gulp.task('clean' , function(){
   return gulp.src([
      'dist', //刪除dist整個資料夾
      'dist/test/**/*', //刪除dist下的test寫任意子資料夾裡的檔案
      '!package.json'  //不刪除package.json檔案
     ] ).pipe($.clean());
});
// gulp.task('clean', del.bind(null, ['.tmp', 'dist']));

//本地建站和自動重新整理
gulp.task('serve', () => {
  runSequence(['clean', 'wiredep'], ['styles', 'scripts', 'fonts'], () => {
    browserSync.init({
      notify: false,
      port: 9000,
      server: {
        baseDir: ['.tmp', 'app'],  //確定根目錄
        routes: {
          '/bower_components': 'bower_components'
        }
      }
    });

    gulp.watch([    //監測檔案變化 實行重新載入
      'app/*.html',
      'app/images/**/*',
      '.tmp/fonts/**/*'
    ]).on('change', reload);

    gulp.watch('app/styles/**/*.scss', ['styles']);  //監測變化 執行styles任務
    gulp.watch('app/scripts/**/*.js', ['scripts']);
    gulp.watch('app/fonts/**/*', ['fonts']);
    gulp.watch('bower.json', ['wiredep', 'fonts']);
  });
});

gulp.task('serve:dist', ['default'], () => {
  browserSync.init({
    notify: false,
    port: 9000,
    server: {
      baseDir: ['dist']
    }
  });
});

gulp.task('serve:test', ['scripts'], () => {
  browserSync.init({
    notify: false,
    port: 9000,
    ui: false,
    server: {
      baseDir: 'test',
      routes: {
        '/scripts': '.tmp/scripts',
        '/bower_components': 'bower_components'
      }
    }
  });

  gulp.watch('app/scripts/**/*.js', ['scripts']);
  gulp.watch(['test/spec/**/*.js', 'test/index.html']).on('change', reload);
  gulp.watch('test/spec/**/*.js', ['lint:test']);
});

// inject bower components
gulp.task('wiredep', () => {
  gulp.src('app/styles/*.scss')
    .pipe($.filter(file => file.stat && file.stat.size))
    .pipe(wiredep({
      ignorePath: /^(\.\.\/)+/
    }))
    .pipe(gulp.dest('app/styles'));

  gulp.src('app/*.html')
    .pipe(wiredep({
      exclude: ['bootstrap-sass'],
      ignorePath: /^(\.\.\/)*\.\./
    }))
    .pipe(gulp.dest('app'));
});

gulp.task('build', ['lint', 'html', 'images', 'fonts', 'extras'], () => {
  return gulp.src('dist/**/*').pipe($.size({title: 'build', gzip: true}));
});

gulp.task('default', () => {
  return new Promise(resolve => {
    dev = false;
    runSequence(['clean', 'wiredep'], 'build', resolve);
  });
});


 

參考:https://blog.csdn.net/SeekerTime/article/details/70325162