yeoman webapp gulpfile.js配置解析

jiangfulai 2019-06-26

安装与使用

  • 全局安装yogenerator-webapp
$ npm install --global yo generator-webapp
  • 利用generator-webapp脚手架构建自己的项目目录:
$ mkdir my-webapp
$ cd my-webapp
$ yo webapp
  • 运行在开发环境,预览并观察更改:
$ gulp serve

这将启动本地Web服务器,在默认浏览器中打开http://localhost:9000并查看文件以进行更改,通过LiveReload自动重新加载浏览器。

  • 运行在测试环境,在浏览器中运行测试:
$ gulp serve:test
  • 构建生产环境下的项目:
$ gulp
  • 预览生产版本,查看一切是否正常运行:
$ gulp serve:dist
  • 获取可用任务的列表:
$ gulp --tasks

配置与核心插件

app->.tmp

使用.tmp目录来编译像SCSS文件这样的资源。它优先于app,所以如果你有一个app/main.scss 模板编译.tmp/main.csshttp://localhost:9000会指向.tmp/main.css,这是我们想要的。
yeoman webapp gulpfile.js配置解析

上图可见其引入的样式文件是.tmp/main.css,控制台显示的是source map映射文件(main.scss)

【gulpfile.js配置 --- app->.tmp】

//app目录下的scss文件和js文件编译到.tmp目录下
gulp.task('styles', () => {
  return gulp.src('app/styles/*.scss')
    .pipe($.plumber())
    .pipe($.if(dev, $.sourcemaps.init()))
    .pipe($.sass.sync({
      outputStyle: 'expanded',
      precision: 10,
      includePaths: ['.']
    }).on('error', $.sass.logError))
    .pipe($.autoprefixer({browsers: ['> 1%', 'last 2 versions', 'Firefox ESR']}))
    .pipe($.if(dev, $.sourcemaps.write()))
    .pipe(gulp.dest('.tmp/styles'))
    .pipe(reload({stream: true}));
});

gulp.task('scripts', () => {
  return gulp.src('app/scripts/**/*.js')
    .pipe($.plumber())
    .pipe($.if(dev, $.sourcemaps.init()))
    .pipe($.babel())
    .pipe($.if(dev, $.sourcemaps.write('.')))
    .pipe(gulp.dest('.tmp/scripts'))
    .pipe(reload({stream: true}));
});
//app下的html文件更新对js和css文件的引用路径
gulp.task('html', ['styles', 'scripts'], () => {
  return gulp.src('app/*.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()))
    .pipe(gulp.dest('dist'));
});

下图显示了在同域名下html引用.tmp目录下的css和js文件,同时也保存了其对map文件的映射
yeoman webapp gulpfile.js配置解析
yeoman webapp gulpfile.js配置解析

browser-sync

var gulp = require('gulp');
var browserSync = require('browser-sync').create();// require 加载 browser-sync 模块

var sass = require('gulp-sass');
var reload = browserSync.reload;

// 静态服务器 + 监听 scss/html 文件
gulp.task('serve', ['sass'], function() {

    // .init 启动服务器
    browserSync.init({
        server: "./app"
    });

    gulp.watch("app/scss/*.scss", ['sass']);
    gulp.watch("app/*.html").on('change', reload);
});

// scss编译后的css将注入到浏览器里实现更新
gulp.task('sass', function() {
    return gulp.src("app/scss/*.scss")
        .pipe(sass())
        .pipe(gulp.dest("app/css"))
        .pipe(reload({stream: true}));
});

gulp.task('default', ['serve']);
  • 配置参数

    • .create( name ):创建Browsersync实例
    • .reload( arg ):该 reload 方法会通知所有的浏览器相关文件被改动,要么导致浏览器刷新,要么注入文件,实时更新改动
    • .active:一个简单的true/false标志,你可以用它来确定是否有一个当前运行Browsersync实例
    • .init( config, cb )

      • server:使用内置的静态服务器创建基本的HTML / JS / CSS的网站。
      • ui:Browsersync通过单独的端口访问可视化控制页面。可视化界面允许控制所有的设备,同步推送更新等等。
      • notify:是否显示浏览器中的任何通知
  • eg. server配置
// Serve files from the app directory
server: "app"

// Serve files from the current directory
server: true

// Serve files from the app directory with directory listing
server: {
    baseDir: "app",
    directory: true
}

// Multiple base directories
server: ["app", "dist"]

// Serve files from the app directory, with a specific index filename
server: {
    baseDir: "app",
    index: "index.htm"
}

// The static file server is based on expressjs/serve-static, 
// so we inherit all of their options, like trying a default extension
// when one isn't specified
// https://github.com/expressjs/serve-static
server: {
    baseDir: "app",
    serveStaticOptions: {
        extensions: ["html"]
    }
}

// Since version 1.2.1
// The key is the url to match
// The value is which folder to serve (relative to your current working directory)
server: {
    baseDir: "app",
    routes: {
        "/bower_components": "bower_components"
    }
}

【gulpfile.js配置 --- browserSync.init】

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']);
    gulp.watch('app/scripts/**/*.js', ['scripts']);
    gulp.watch('app/fonts/**/*', ['fonts']);
    gulp.watch('bower.json', ['wiredep', 'fonts']);
  });
});

yeoman webapp gulpfile.js配置解析

Browsersync / 说明文档

wiredep

将Bower依赖自动注入HTML文件中。使用--save安装Bower软件包会将软件包作为依赖项添加到项目的bower.json文件中。 该库(wiredep)读取该文件(.html),然后读取bower.json文件的每个依赖项。 基于两者间关联,它决定了脚本在源代码中的占位符之间注入之前必须包含的顺序。

<html>
<head>
  <!-- bower:css -->
  <!-- endbower -->
</head>
<body>
  <!-- bower:js -->
  <!-- endbower -->
</body>
</html>


var wiredep = require('wiredep').stream;

gulp.task('bower', function () {
  gulp.src('./src/footer.html')
    .pipe(wiredep({
      optional: 'configuration',
      goes: 'here'
    }))
    .pipe(gulp.dest('./dest'));
});

main-bower-files

通过读取并分析bower.json文件里override属性里main路径下定义的插件及相关依赖,返回一个文件数组。

如果第一个参数是String,Array或RegExp的类型,它将被用作过滤器,否则将被用作选项。
读取您的bower.json,遍历您的依赖关系,并返回在bower.json的由main属性的值组成的对象数组。
如果将一个overrides 属性添加到您自己的bower.json中,则可以复写执行。
var mainBowerFiles = require('main-bower-files');
var files = mainBowerFiles([[filter, ]options][, callback]);
  • 直接使用
var gulp = require('gulp');
var mainBowerFiles = require('main-bower-files');

gulp.task('TASKNAME', function() {
    return gulp.src(mainBowerFiles())
        .pipe(/* what you want to do with the files */)
});
  • 也可以增加配置
var gulp = require('gulp');
var mainBowerFiles = require('main-bower-files');

gulp.task('TASKNAME', function() {
    return gulp.src(mainBowerFiles(/* options */), { base: 'path/to/bower_components' })
        .pipe(/* what you want to do with the files */)
});

run-sequence & del

run-sequence 的作用就是控制多个任务进行顺序执行或者并行执行
del 全局删除文件/文件夹.

var gulp = require('gulp');
var runSequence = require('run-sequence');
var del = require('del');

// This will run in this order:
// * build-clean
// * build-scripts and build-styles in parallel
// * build-html
// * Finally call the callback function
gulp.task('build', function(callback) {
  runSequence('build-clean',
              ['build-scripts', 'build-styles'],
              'build-html',
              callback);
});

gulp.task('build-clean', function() {
    // Return the Promise from del()
    return del(['tmp/*.js', '!tmp/unicorn.js']).then(paths => {
    console.log('Deleted files and folders:\n', paths.join('\n'));
   });
});

gulp插件

gulp-sourcemaps

提供source map支持。如果调用 sourcemaps.write 不给任何参数,不会生成一个 .map 的文件,默认会将文件对照表信息全部写入转码编译后的文件末端。这样很不友好。(一般这个对照表的信息量还是很大的,这对生产线上浏览器请求加载文件无疑是无用额外的开销,手动去除也是一件很低效费时的工作。)
我们可以给它加个参数。这样指定输出路径之后,文件编译转码完只会在最后一行只会写入对 Source Map 的文件引用,而 Source Map 对照表本身(.map文件)会被输出到指定的路径下

//@ sourceMappingURL=_srcmap/BearD01001.js.map
var gulp = require('gulp');
var plugin1 = require('gulp-plugin1');
var plugin2 = require('gulp-plugin2');
var sourcemaps = require('gulp-sourcemaps');
 
gulp.task('javascript', function() {
  gulp.src('src/**/*.js')
    .pipe(sourcemaps.init())
      .pipe(plugin1())
      .pipe(plugin2())
    .pipe(sourcemaps.write('../maps'))
    .pipe(gulp.dest('dist'));
});

JavaScript Source Map 详解

gulp-useref

解析HTML文件中的构建块,以替换对未优化的脚本或样式表的引用。合并成一个文件,但不负责代码压缩

var gulp = require('gulp'),
    useref = require('gulp-useref');

gulp.task('default', function () {
    return gulp.src('app/*.html')
        .pipe(useref())
        .pipe(gulp.dest('dist'));
});


<!-- build:<type>(alternate search path) <path> <parameters> -->
... HTML Markup, list of script / link tags.
<!-- endbuild -->
  • type(类型):或者js,css或remove; remove将完全删除构建块而不生成文件
  • alternate search path(备用搜索路径):(可选)默认情况下,输入文件是相对于处理文件。备用搜索路径允许更改
  • path(路径):优化文件的文件路径,目标输出
  • parameters(参数):应该添加到标签的额外参数

完整形式的示例如下所示:

<html>
<head>
    <!-- build:css css/combined.css -->
    <link href="css/one.css" rel="stylesheet">
    <link href="css/two.css" rel="stylesheet">
    <!-- endbuild -->
</head>
<body>
    <!-- build:js scripts/combined.js -->
    <script type="text/javascript" src="scripts/one.js"></script>
    <script type="text/javascript" src="scripts/two.js"></script>
    <!-- endbuild -->
</body>
</html>

生成的HTML将是:

<html>
<head>
    <link rel="stylesheet" href="css/combined.css"/>
</head>
<body>
    <script src="scripts/combined.js"></script>
</body>
</html>

gulp-if

var gulpif = require('gulp-if');
var uglify = require('gulp-uglify');
var beautify = require('gulp-beautify');

var condition = function (file) {
  // TODO: add business logic
  return true;
}

//If condition returns true, uglify else beautify, then send everything to the dist folder
gulp.task('task', function() {
  gulp.src('./src/*.js')
    .pipe(gulpif(condition, uglify(), beautify()))
    .pipe(gulp.dest('./dist/'));
});


//Only uglify the content if the condition is true, but send all the files to the dist folder
gulp.task('task2', function() {
  gulp.src('./src/*.js')
    .pipe(gulpif(condition, uglify()))
    .pipe(gulp.dest('./dist/'));
});

gulp-load-plugins(自动加载插件)

var gulp = require('gulp');
var gulpLoadPlugins = require('gulp-load-plugins');
var plugins = gulpLoadPlugins();
  • 使用gulp-clone和gulp-clean-css这两个插件的时候,就可以使用plugins.clone和plugins.cleanCss来代替了,也就是原始插件名去掉gulp-前缀,之后再转换为驼峰命名。
  • 实质上gulp-load-plugins是为我们做了如下的转换

    plugins.clone= require(‘gulp-clone’);
    plugins.cleanCss= require(‘gulp-clean-css’);

  • gulp-load-plugins并不会一开始就加载所有package.json里的gulp插件,而是在我们需要用到某个插件的时候,才去加载那个插件。
  • 因为gulp-load-plugins是通过你的package.json文件来加载插件的,所以必须要保证你需要自动加载的插件已经写入到了package.json文件里,并且这些插件都是已经安装好了的。

gulp-autoprefixer

var autoprefixer = require('gulp-autoprefixer');

gulp.src('./css/*.css')
    .pipe(autoprefixer())                   // 直接添加前缀
    .pipe(gulp.dest('dist'))

gulp.src('./css/*.css')
    .pipe(autoprefixer({
        browsers: ['last 2 versions'],      // 浏览器版本
        cascade:true                       // 美化属性,默认true
        add: true                           // 是否添加前缀,默认true
        remove: true                        // 删除过时前缀,默认true
        flexbox: true                       // 为flexbox属性添加前缀,默认true
    }))
    .pipe(gulp.dest('./dist'))

browsers参数详解 (传送门):

  • last 2 versions: 主流浏览器的最新两个版本
  • last 1 Chrome versions: 谷歌浏览器的最新版本
  • last 2 Explorer versions: IE的最新两个版本
  • last 3 Safari versions: 苹果浏览器最新三个版本
  • Firefox >= 20: 火狐浏览器的版本大于或等于20
  • iOS 7: IOS7版本
  • Firefox ESR: 最新ESR版本的火狐
  • > 5%: 全球统计有超过5%的使用率

各浏览器的标识:

  • Android for Android WebView.
  • BlackBerry or bb for Blackberry browser.
  • Chrome for Google Chrome.
  • Firefox or ff for Mozilla Firefox.
  • Explorer or ie for Internet Explorer.
  • iOS or ios_saf for iOS Safari.
  • Opera for Opera.
  • Safari for desktop Safari.
  • OperaMobile or op_mob for Opera Mobile.
  • OperaMini or op_mini for Opera Mini.
  • ChromeAndroid or and_chr
  • FirefoxAndroid or and_ff for Firefox for Android.
  • ExplorerMobile or ie_mob for Internet Explorer Mobile.

gulp-cached

gulp-cached 可以将第一次传递给它的文件内容保留在内存中,如果之后再次执行 task,它会将传递给它的文件和内存中的文件进行比对,如果内容相同,就不再将该文件继续向后传递,从而做到了只对修改过的文件进行增量编译。

var cache = require('gulp-cached');

gulp.task('lint', function(){
  return gulp.src('files/*.js')
    .pipe(cache('linting'))
    .pipe(jshint())
    .pipe(jshint.reporter())
});

gulp.task('watch', function(){
  gulp.watch('files/*.js', ['lint']);
});

gulp.task('default', ['watch','lint']);

gulp 中的增量编译
gulp-changed的使用:只编译改动过的文件

gulp-filter

使用全局正则匹配模式对原始文件的子集进行过滤。 当完成操作并想要所有的原始文件时,只需使用restore恢复流。

var filter = require('gulp-filter');

const f = filter(['**', '!*/index.js']);
gulp.src('js/**/*.js')
    .pipe(f)                        // 过滤掉index.js这个文件
    .pipe(gulp.dest('dist'));

const f1 = filter(['**', '!*/index.js'], {restore: true});
gulp.src('js/**/*.js')
    .pipe(f1)                       // 过滤掉index.js这个文件
    .pipe(uglify())                 // 对其他文件进行压缩
    .pipe(f1.restore)               // 返回到未过滤执行的所有文件
    .pipe(gulp.dest('dist'));       // 再对所有文件操作,包括index.js

gulp-htmlmin

var gulp = require('gulp'),
    htmlmin = require('gulp-htmlmin');
 
gulp.task('testHtmlmin', function () {
    var options = {
        removeComments: true,//清除HTML注释
        collapseWhitespace: true,//压缩HTML
        collapseBooleanAttributes: true,//省略布尔属性的值 <input checked="true"/> ==> <input />
        removeEmptyAttributes: true,//删除所有空格作属性值 <input id="" /> ==> <input />
        removeScriptTypeAttributes: true,//删除<script>的type="text/javascript"
        removeStyleLinkTypeAttributes: true,//删除<style>和<link>的type="text/css"
        minifyJS: true,//压缩页面JS
        minifyCSS: true//压缩页面CSS
    };
    gulp.src('src/html/*.html')
        .pipe(htmlmin(options))
        .pipe(gulp.dest('dist/html'));
});

gulp-imagemin

var gulp = require('gulp'),
    imagemin = require('gulp-imagemin');
 
gulp.task('testImagemin', function () {
    gulp.src('src/img/*.{png,jpg,gif,ico}')
        .pipe(imagemin())
        .pipe(gulp.dest('dist/img'));
});

gulp教程之gulp-imagemin

gulp-plumber

这个补丁插件用来解决gulp管道流的问题。简而言之,它将替换管道流的默认方式,并删除错误事件上的标准错误处理程序(默认情况下会错误地处理错误流)

var plumber = require('gulp-plumber');
var coffee = require('gulp-coffee');

gulp.src('./src/*.ext')
    .pipe(plumber())
    .pipe(coffee())
    .pipe(gulp.dest('./dist'));

gulp-uglify

Minify JavaScript with UglifyJS3.
var gulp = require('gulp'),
    uglify = require('gulp-uglify');
 
gulp.task('jsmin', function () {
    gulp.src('src/js/index.js')
        .pipe(uglify())
        .pipe(gulp.dest('dist/js'));
});

gulp教程之gulp-uglify

相关推荐