zoukankan      html  css  js  c++  java
  • 前端自动化gulp遇上es6从 无知到深爱

    Gulp是什么?

    Gulp是前端自动化的工具,但Gulp能用来做什么

    1.搭建web服务器

    2.使用预处理器Sass,Less

    3.压缩优化,可以压缩JS CSS Html 图片

    4.自动将更新变化的代码实时显示在浏览器

    5.前端测试

    ......

    这些都不是他的全部功能,社区丰富的插件,为他提供了强大的后盾。

    首先下载gulp(前提默认你安装好了node,先 npm install,创建一个package.json)

    npm install gulp -g //全局安装
    npm install gulp --save-dev //本地安装并加入package.json

     一、安装各种神奇的插件

    接下来安装各种需要的插件:

    npm install babel-core babel-preset-es2015 browser-sync gulp gulp-autoprefixer gulp-babel gulp-cache gulp-clean gulp-cssnano gulp-htmlmin gulp-if gulp-imagemin gulp-load-plugins gulp-plumber gulp-sass gulp-size gulp-sourcemaps gulp-uglify gulp-useref gulp-rev-append main-bower-files wiredep --save-dev

    各种插件按需求自己选择,各自功能如下:

    1.babel-core babel-preset-es2015 gulp-babel   用于解析es6转换为es5

    2.browser-sync  服务器同步浏览

    3.gulp-autoprefixer  根据设置浏览器版本自动处理浏览器前缀

    4.gulp-cache  图片快取,只有更改过得图片会进行压缩

    5.gulp-clean 清空文件夹

    6.gulp-cssnano 压缩CSS代码

    7.gulp-htmlmin 压缩html

    8.gulp-if 用于判断

    8.gulp-imagemin 图片压缩

    9.gulp-load-plugins 自动加载(超级有用 省去一大堆代码)

    10.gulp-plumber 管道工 不会让错误爆出来 继续执行

    11.gulp-sass 预编译Sass

    12.gulp-size 统计管道里面内容的大小的,上面是用它来显示出压缩前后的大小用来对比用

    13.gulp-sourcemaps 当压缩的JS出错,能根据这个找到未压缩代码的位置 不会一片混乱代码

    14.gulp-uglify JS压缩

    15.gulp-useref 将html引用顺序的CSS JS 变成一个文件  

    例如:<!-- build:js scripts/main.js --> <script src="1.js"></script><script src="2.js"></script><!--endbuild--> 最后变成<script src="main.js"></script>

    16.gulp-rev-append html引用添加版本号

    17.main-bower-files 找到bower.json里配置的 overrides 下配置的main下的路径

    18.wiredep 在.html文件会把默认bower.json的配置自动注入到下面标签中去 <!-- bower:js --> <!-- endbower --> <!-- bower:css--> <!-- endbower -->

    接下来是用 bower安装 Jquery bootstrap-sass

    bower init //新建bower.json
    bower install jquery bootstrap-sass --save-dev //安装jquery bootstrap

     二、get Gulp的简单语法

    1.gulp.task(name[,deps],fn)

    说明:定义一个gulp任务

    name: 类型(必填):String 指定任务的名称(不应该有空格)

    deps:类型(可选):StringArray,该任务依赖的任务(执行name任务要先去执行的任务)

    gulp.task('A' , function(){
       console.log('A') 
    });
    gulp.task('B' , ['A'] , function(){ //运行B之前先去运行A
       console.log('B')
    });

    fn:类型(必填):Function 该任务调用的插件操作

    2.gulp.src(globs[, options])

    说明:src方法指定需要处理的源文件路径,返回当前文件流至可用插件

    globs: 类型(必填):String/StringArray  需要处理的源文件匹配符路径

    通配符路径匹配示例:

      “src/a.js”:指定具体文件;

      “*”:匹配所有文件    例:src/*.js(包含src下的所有js文件);

      “**”:匹配0个或多个子文件夹    例:src/**/*.js(包含src的0个或多个子文件夹下的js文件);

      “{}”:匹配多个属性    例:src/{a,b}.js(包含a.js和b.js文件)  src/*.{jpg,png,gif}(src下的所有jpg/png/gif文件);

      “!”:排除文件    例:!src/a.js(不包含src下的a.js文件);

    options:类型(可选):Object 三个属性 buffer read base

      options.buffer:类型:Boolean  默认:true 设置为false,将返回file.content的流并且不缓冲文件,处理大文件时非常有用;

      options.read:  类型:Boolean  默认:true 设置false,将不执行读取文件操作,返回null;

      options.base:  类型:String  设置输出路径以某个路径的某个组成部分为基础向后拼接

    gulp.src('client/js/**/*.js') 
      .pipe(minify())
      .pipe(gulp.dest('build'));  // Writes 'build/somedir/somefile.js'
     
    gulp.src('client/js/**/*.js', { base: 'client' })
      .pipe(minify())
      .pipe(gulp.dest('build'));  // Writes 'build/js/somedir/somefile.js'

     

    3.gulp.dest(path[,options])

    说明:处理完后文件输出的路径

    path:类型(必填):String or Function 指定文件输出路径,或者定义函数返回文件输出路径亦可

    options:  类型(可选):Object,有2个属性cwd、mode;

      options.cwd:  类型:String  默认:process.cwd():前脚本的工作目录的路径 当文件输出路径为相对路径将会用到;

      options.mode:  类型:String  默认:0777 指定被创建文件夹的权限;

     

    4.gulp.watch(glob[,opts],tasks) or gulp.task(glob [,opts ,cd])

    说明:watch方法用于监听文件变化,一被变化就执行指定任务

    glob:  需要处理的源文件匹配符路径。类型(必填):String or StringArray;

    opts:  类型(可选):Object 具体参看https://github.com/shama/gaze

    tasks:  类型(必填):StringArray 需要执行的任务的名称数组;

    cb(event):  类型(可选):Function 每个文件变化执行的回调函数;

    三、目录

    |--gulp_test
        |--app             //生产文件路径
            |--fonts
            |--images
    |--1.png
    |--scripts
    |--main.js
    |--index.js
    |--styles
    |--main.scss
    |--index.css
    |--index.html |--dist //发布文件路径 |--fonts |--images |--scripts |--styles |--index.html |--bower_components |--bootstrap-sass |--jquery |--node_modules |--各种插件 |--package.json |--bower.json

    app是我们新建的目录和文件夹,其余是按照上面操作自动生成的。

    首先在gulp_test下新建.babelrc (用于配置es6 语法) .bowerrc (用于定义bower的路径)两个文件

    .babelrc

    {
      "presets": [
        "es2015"
      ]
    }

    .bowerrc

    {
      "directory": "bower_components"
    }

    设置一下bower.json

    {
      "name": "gulp_test",
      "authors": [
        "QRL"
      ],
      "keywords": [
        "bower_components"
      ],
      "private": true,
      "devDependencies": {
        "jquery": "^3.0.0"
      },
      "overrides": {
        "bootstrap-sass": {
          "main": [
            "assets/stylesheets/_bootstrap.scss",
            "assets/fonts/bootstrap/*",
            "assets/javascripts/bootstrap.js"
          ]
        }
      },
      "dependencies": {"bootstrap-sass": "^3.3.6"}
    }

    app下的index.html内容

    <!doctype html>
    <html lang="">
      <head>
        <meta charset="utf-8">
        <meta name="description" content="">
        <meta name="viewport" content="width=device-width, initial-scale=1">
        <title>test gulp webapp</title>
    
        <link rel="apple-touch-icon" href="apple-touch-icon.png">
        <!-- Place favicon.ico in the root directory -->
    
        <!-- build:css styles/index_main.css -->   //这个注释的意思是 将两个css合并成一个index_main.css 注意顺序
        <link rel="stylesheet" href="styles/index.css">
        <link rel="stylesheet" href="styles/main.css">
        <!-- endbuild -->
      </head>
      <body>
      
        <div class="container">
          <div class="header">
            <ul class="nav nav-pills pull-right">
              <li class="active"><a href="#">Home</a></li>
              <li><a href="#">About</a></li>
              <li><a href="#">Contact</a></li>
            </ul>
            <h3 class="text-muted">Hello</h3>
          </div>
    
          <div class="jumbotron">
            <h1>Hello Gulp!</h1>
            <p class="lead">Always a pleasure scaffolding your apps.</p>
            <p><a class="btn btn-lg btn-success" href="#">Splendid!</a></p>
          </div>
    
          <div class="row marketing">
            <div class="col-lg-6">
              <h4>HTML5 Boilerplate</h4>
              <p>HTML5 Boilerplate is a professional front-end template for building fast, robust, and adaptable web apps or sites.</p>
              
              <h4>Sass</h4>
              <p>Sass is the most mature, stable, and powerful professional grade CSS extension language in the world.</p>
              
              <h4>Bootstrap</h4>
              <p>Sleek, intuitive, and powerful mobile first front-end framework for faster and easier web development.</p>
              <h4>Modernizr</h4>
              <p>Modernizr is an open-source JavaScript library that helps you build the next generation of HTML5 and CSS3-powered websites.</p>
              
            </div>
          </div>
    
          <div class="footer">
            <p>♥ from the Yeoman team</p>
          </div>
        </div>
        
        <!-- Google Analytics: change UA-XXXXX-X to be your site's ID. -->
        <script>
          (function(b,o,i,l,e,r){b.GoogleAnalyticsObject=l;b[l]||(b[l]=
          function(){(b[l].q=b[l].q||[]).push(arguments)});b[l].l=+new Date;
          e=o.createElement(i);r=o.getElementsByTagName(i)[0];
          e.src='https://www.google-analytics.com/analytics.js';
          r.parentNode.insertBefore(e,r)}(window,document,'script','ga'));
          ga('create','UA-XXXXX-X');ga('send','pageview');
        </script>
    
        <!-- build:js scripts/vendor.js --> //将以下js合并成一个,并更名为vendor.js
        <script src="/bower_components/jquery/dist/jquery.js"></script>
        <!-- endbuild -->
        
        <!-- build:js scripts/plugins.js --> //注意一下这里 待会会按照顺序变成一个plugins.js文件
         //是否遇到过这么多的插件引用,Ctrl+c Ctrl+v 还要细致的修改  请留意 wiredep 任务  留意下面的<!-- bower:js --><!-- endbower -->注释,这可不是随随便便的注释
        <!-- bower:js -->
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/affix.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/alert.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/dropdown.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/tooltip.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/modal.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/transition.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/button.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/popover.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/carousel.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/scrollspy.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/collapse.js"></script>
        <script src="/bower_components/bootstrap-sass/assets/javascripts/bootstrap/tab.js"></script>
        <!-- endbower -->
        <!-- endbuild -->
        
        <!-- build:js scripts/index_main.js -->   
        <script src="scripts/index.js"></script>
        <script src="scripts/main.js"></script>
        <!-- endbuild -->
      </body>
    </html>

    接下来最重要了,同样在gulp_test下新建gulpfile.babel.js(因为这里使用es6,所以需要将原本的gulpfile.js 更名为 gulpfile.babel.js )

    四、开始gulp之旅

    打开gulpfile.babel.js,开始操作

    首先写进以下代码:

    import gulp from 'gulp'; //引入gulp
    import gulpLoadPlugins from 'gulp-load-plugins'; //自动加载插件 省去一个一个require进来
    import browserSync from 'browser-sync'; //浏览器同步
    import {stream as wiredep} from 'wiredep'; //把bower 下载的文件引入到html文件中
    const $ = gulpLoadPlugins();
    const reload = browserSync.reload;

    接下来

     先尝试删除dist文件夹  终端运行 "gulp clean"

    gulp.task('clean' , function(){
       return gulp.src([
          'dist', //删除dist整个文件夹
          'dist/test/**/*', //删除dist下的test写任意子文件夹里的文件
          '!package.json'  //不删除package.json文件
         ] ).pipe($.clean());
    });

    预编译Sass

    gulp.task('styles' , ()=>{
       return gulp.src('app/styles/*.scss') //指明源文件路径 读取其数据流
            .pipe($.plumber()) //替换错误的pipe方法  使数据流正常运行
            .pipe($.sourcemaps.init()) //压缩环境出现错误能找到未压缩的错误来源
            .pipe($.sass.sync({        //预编译sass
                outputStyle: 'expanded', //CSS编译后的方式
                precision: 10,//保留小数点后几位
                includePaths: ['.']
            }).on('error', $.sass.logError))
            .pipe($.autoprefixer({browsers:['> 1%', 'last 2 versions', 'Firefox ESR']}))     //自动匹配浏览器支持的后缀
            .pipe($.sourcemaps.write('.'))  //map文件命名
            .pipe(gulp.dest('dist/styles'))  //指定输出路径
    });
    ../dist/styles目录下会生成 对应的 *.css 和 *.css.map

    转化es6的JS

    gulp.task('scripts' , ()=>{
        return gulp.src('app/scripts/**/*.js')
            .pipe($.plumber())
            .pipe($.sourcemaps.init())
            .pipe($.babel())    //靠这个插件编译
            .pipe($.sourcemaps.write('.'))
            .pipe(gulp.dest('dist/scripts'));     
    });
    ../dist/scripts目录下会生成 对应的 *.js 和 *.js.map

    压缩图片

    gulp.task('images',()=>{
        return gulp.src('app/images/**/*')
             .pipe ($.cache ($.imagemin ({ //使用cache只压缩改变的图片
                  optimizationLevel: 3,         //压缩级别
                  progressive: true, 
                  interlaced: true})
             )).pipe (gulp.dest ('dist/images'));
    });
    通过对比图片大小,可以看出压缩了多少

    引用字体文件

    gulp.task('fonts', () => {
        return gulp.src(require('main-bower-files')('**/*.   {eot,svg,ttf,woff,woff2}', function (err) {})  //main-bower-files会从bower.json文件里寻找定义好的主要文件路径
            .concat('app/fonts/**/*'))  //将bootstrap-sass的fonts和app下我们自己选用的fonts合并起来
    .pipe(gulp.dest('dist/fonts')); });
    ../dist/fonts目录下会生成 对应的文件

    接下来是最最有用的操作,将CSS合并压缩,JS合并压缩,html压缩,加上时间戳避免缓存

    gulp.task('html', ['styles' , 'scripts'], ()=>{   //先执行styles scripts任务
        var version = (new Date).valueOf() + '';
        var options = {
            removeComments: false,//清除HTML注释
            collapseWhitespace: true,//压缩HTML
            collapseBooleanAttributes: false,//省略布尔属性的值 <input checked="true"/> ==> <input />
            removeEmptyAttributes: false,//删除所有空格作属性值 <input id="" /> ==> <input />
            removeScriptTypeAttributes: false,//删除<script>的type="text/javascript"
            removeStyleLinkTypeAttributes: false,//删除<style>和<link>的type="text/css"
            minifyJS: false,//压缩页面里的JS
            minifyCSS: false//压缩页面里的CSS
        };
        return gulp.src('app/*.html')
            .pipe($.plumber())
            .pipe($.useref({searchPath: ['app', '.']}))  //将页面上 <!--endbuild--> 根据上下顺序合并
            .pipe($.if('*.js', $.uglify()))
            .pipe($.if('*.css', $.cssnano()))
            .pipe($.if('*.html', $.htmlmin(options)))
            .pipe($.replace('.js"></script>' , '.js?v=' + version + '"></script>'))   //这种方法比较不成熟 每一次的任务都会改变,不管文件是否被修改 
            .pipe($.replace('.css">' , '.css?v=' + version + '">'))
            .pipe(gulp.dest('dist'));
    });

     查看dist/index.html , 是否还记得

    是不是瞬间被吓到了,再也不用一个个压缩JS文件,再也不要担心缓存这种问题,再也不用因为页面的臃肿而烦恼,几行配置,一键搞定。

    优化上面的引用加版本号: 使用插件 gulp-rev-append

    import rev from 'gulp-rev-append'
    
    gulp.task('html', ['styles' , 'scripts'], ()=>{   //先执行styles scripts任务
       
        return gulp.src('app/*.html')
            .pipe($.plumber())
            .pipe($.useref({searchPath: ['app', '.']}))  //将页面上 <!--endbuild--> 根据上下顺序合并
            .pipe($.if('*.js', $.uglify()))
            .pipe($.if('*.css', $.cssnano()))
            .pipe(rev())       //为引用添加版本号
            .pipe($.if('*.html', $.htmlmin(options)))      
            .pipe(gulp.dest('dist'));
    });

    同时需要在index.html的引用后面加上 ?rev=@@hash

    <script src="scripts/index.js?rev=@@hash"></script>

    添加后的效果

    <script src="scripts/index.js?rev=200c90563a2be0adfd8c03f8e4162df7"></script>

    最重要是只要app/index.js里不发生改变,这个版本号就不会变化。

    接下来再学一个黑魔法——本地建站和自动刷新

    gulp.task('serve', ['styles','scripts','fonts'] , ()=>{
        browserSync({
            notify : false,
            port:9000,  //端口号
            server:{
                baseDir:['dist'], //确定根目录
                routes:{
                    '/bower_components': 'bower_components'
                }
            }
        });
    
        gulp.watch([      //监测文件变化 实行重新加载
            'app/*.html', 
            'app/images/**/*' 
        ]).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 serve 浏览器直接打开dist下的index.html,只要一修改监测的文件,浏览器立即刷新。

    小插曲:接下来解决 wiredep 任务,这个插件主要是用在bower下载文件,方便页面引用文件

    首先在app下新建一个 index_test.html

    <!DOCTYPE html>
    <html>
    <head lang="en">
        <meta charset="UTF-8">
        <title></title>
    
        <!--bower:css-->
        <!--endbower-->
    </head>
    <body>
        <p>Hellp wirdep</p>
        <a href="index.html">dianwo</a>
        <!-- bower:js -->
        <!-- endbower -->
    </body>
    </html>

    然后在gulpfile.babel.js中写上任务

    gulp.task('wiredep_test' , function(){
        gulp.src('./app/index_test.html')
        .pipe(wiredep({
                optional:'configuration',
                goes : 'here',
                ignorePath:/^(../)+/      //生成的路径忽略../   
            }))
        .pipe(gulp.dest('./app'))    //输出到原路径
    });

    然后运行一下,index_test.html 原本的<!-- bower:js --> <!-- endbower --> 变成

     <!-- bower:js -->
        <script src="bower_components/jquery/dist/jquery.js"></script>
        <script src="bower_components/bootstrap-sass/assets/javascripts/bootstrap.js"></script>
     <!-- endbower -->

    你或许很疑惑这是根据什么自动查找生成的啊?因为没有中文文档,自己摸索后是在bower.json里面配置的,review一下刚才的bower.json

      "devDependencies": {
        "jquery": "^3.0.0"
      },
      "overrides": {
        "bootstrap-sass": {
          "main": [
            "assets/stylesheets/_bootstrap.scss",
            "assets/fonts/bootstrap/*",
            "assets/javascripts/bootstrap.js"
          ]
        }
      },
      "dependencies": {"bootstrap-sass": "^3.3.6"}

    根据以上三个根据,起最大作用的是overrides,最终会根据这些进行生成。

    可以稍微测试一下,将bower.json做点小修改 ,增加jquery的选择

    "overrides": {
        "bootstrap-sass": {
          "main": [
            "assets/stylesheets/_bootstrap.scss",
            "assets/fonts/bootstrap/*",
            "assets/javascripts/bootstrap.js"
          ]
        },
        "jquery" :{
          "main":[
            "src/*.js"
          ]
        }
      }

    回头看看index_test.html  刚才的jquery.js 被src下的js代替

    <!-- bower:js -->
        <script src="bower_components/modernizr/modernizr.js"></script>
        <script src="bower_components/jquery/src/ajax.js"></script>
        <script src="bower_components/jquery/src/attributes.js"></script>
        <script src="bower_components/jquery/src/callbacks.js"></script>
        <script src="bower_components/jquery/src/core.js"></script>
        <script src="bower_components/jquery/src/css.js"></script>
        <script src="bower_components/jquery/src/data.js"></script>
        <script src="bower_components/jquery/src/deferred.js"></script>
        <script src="bower_components/jquery/src/deprecated.js"></script>
        <script src="bower_components/jquery/src/dimensions.js"></script>
        <script src="bower_components/jquery/src/effects.js"></script>
        <script src="bower_components/jquery/src/event.js"></script>
        <script src="bower_components/jquery/src/jquery.js"></script>
        <script src="bower_components/jquery/src/manipulation.js"></script>
        <script src="bower_components/jquery/src/offset.js"></script>
        <script src="bower_components/jquery/src/queue.js"></script>
        <script src="bower_components/jquery/src/selector-native.js"></script>
        <script src="bower_components/jquery/src/selector-sizzle.js"></script>
        <script src="bower_components/jquery/src/selector.js"></script>
        <script src="bower_components/jquery/src/serialize.js"></script>
        <script src="bower_components/jquery/src/traversing.js"></script>
        <script src="bower_components/jquery/src/wrap.js"></script>
        <script src="bower_components/bootstrap-sass/assets/javascripts/bootstrap.js"></script>
        <!-- endbower -->

    最后一步,就结束了

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

    这就是单独运行 gulp 就会执行default 然后执行我们想要的操作,同时可以根据size看到压缩后节省的空间。

    感谢您坚持看完,一步步跟着做,你会发现gulp原来辣么容易,前端自动化工具辣么方便。

    对于老项目也可以这样一步一步改造哦!

     声明:上述的 二、get Gulp的简单语法 摘抄于 Gulp中文网的API文档 。其余内容均属楼主一点一滴码出来的。

  • 相关阅读:
    堆和栈的区别!
    产品经理和程序员的爱恨情仇
    字符串MD5加密运算
    事件驱动模型。。。。有时间弄
    Apache服务器httpd.exe进程占用cpu超过50%的解决方法
    ZigBee Xbee S2通讯设置
    pipe-filter 真难找啊
    javacomm64位用不了,可以使用RXTXcomm for x64
    导入 sun.net.TelnetInputStream; 报错
    linux下gedit读取txt乱码解决办法
  • 原文地址:https://www.cnblogs.com/QRL909109/p/5620824.html
Copyright © 2011-2022 走看看