closertb / closertb.github.io

浏览issue 或 我的网站,即可查看我的所有博客
https://closertb.site
32 stars 0 forks source link

用gulp管理自己的前端开发任务及需要注意的坑 #6

Open closertb opened 5 years ago

closertb commented 5 years ago

写于:2017-07-10

关于gulp,grunt,webpack,刚走前端模块化的我,真的是傻傻分不清楚,幸好有大神各种答疑解惑,使我略知一二,你也想知道的,也许还想知道点啥,资源罗列:

  1. 中文官方文档
  2. 阮老师的gulp入门
  3. 我的参考;

本次开发,受尤大神知乎上的回答提示,没有采用vue-cli直接入手vue框架,而是采用vue全家桶+requireJs+gulp着手自己的前端构建,gulp为自己第一次使用,所以写下此文,算是对自己成长的一次记录。关于gulp,首先你得知道npm,node这些常识,其次官方的API应该细度加实践一下,其四个基本操作:gulp.task、gulp.src、gulp.dest、gulp.watch四个基本方法,需用知道是干什么的,该怎么用。gulp有什么用?文章将基于以下4条逐一展开讲:

  1. 搭建web服务器
  2. 优化资源,比如压缩CSS、JavaScript、压缩图片;
  3. 使用预处理器LESS,jade,JSX需要编译发布;
  4. 文件保存时自动重载浏览器;

先打地基

gulp官网的API用了寥寥几个字,写完了四个基本方法的调用,但task占了二分之一,足以见得他的重要,所以得好好研究。 当定义一个任务时,你可以定义它的前置任务,可以是一个列表,这个列表会以最大的并发数执行,待这个前置任务列表中所有任务执行完后,才会执行当前任务,但是这个列表中的所有任务都必须使用正确的异步执行方式。使用一个 callback,或者返回一个 promise 或 stream。熟读API项中的注意项
默认的,task 将以最大的并发数执行,也就是说,gulp 会一次性运行所有的 task 并且不做任何等待。如果你想要创建一个序列化的 task 队列,并以特定的顺序执行,你需要做两件事:

你可能或者见过下面这些task书写方式:

   //刚入门,多数人的写法
   gulp.task('revImg',function(){
    gulp.src('img/**/*')
    .pipe(gulp.dest('dist/img'))
    });

    //读过API,返回一个stream的写法
    gulp.task('revImg',function(){
    return gulp.src('img/**/*')
    .pipe(gulp.dest('dist/img'))
    });

    //读过API,接受一个 callback
    gulp.task('revImg',function(){
    return gulp.src('img/**/*')
    .pipe(gulp.dest('dist/img'))
    });
    //promise这种太高大上的,在gulp里还没用过;具体来看一段真实的演示代码;
        gulp.task('tC',function(){
            gulp.src('css/*.css')
            .pipe(contact('index.css'))
            .pipe(rev())
            .pipe(gulp.dest('dist/test'))
            .pipe(rev.manifest({merge:true}))
            .pipe(gulp.dest('dist/test'))
        });
        gulp.task('tJ',function(){
            gulp.src('js/main/require.js')
            .pipe(rev())
            .pipe(rev.manifest({merge:true}))
            .pipe(gulp.dest('dist/test'))
        });
        gulp.task('tt',['tC','tJ'],function(){
            gulp.src('img/**/*')
            .pipe(gulp.dest('dist/test'));
        })

开启一个本地web服务

通常开发时,我们不可能一直写静态页面,我们需要在其他设备查看效果或者与后台的动态交互,使前端开发变得更有意义。所以与后端交付之前,你得有一个本地服务器来发布你的内容。直白点说,没有服务器,我们是通过这样的链接(file:///D:/vueProject/myblog/dist/index.html)访问我们的页面的,而有了服务器依赖,我们是通过这样的链接(http://localhost/)访问我们的页面的,应用上线的感觉,有没有?其实以前基于JavaWeb开发(tomcat)网页时,根本就没这档子事。闲话少扯,进入正题。利用gulp资源,开启一个服务器,你需要下载安装gulp-webserver这个插件,然后这样配置,源码

var gulp = require('gulp');
var webserver = require('gulp-webserver');
gulp.task("Server",function(){
  gulp.src('dist')  //你web资源的根目录
  .pipe(webserver({
    port:80,
    host:'127.0.0.1',
    liveload:true,
    directoryListing:{
      path:'index.html', //你web资源的起始页,在dist目录下
      enable:true
    }
  }))
});

基于以上,然后在命令行中输入gulp Server就可以开启一个本地端口为80(也可以为其他)的本地服务器,很简单有木有,但上面的服务器有一个问题,只有本机能访问,局域网内其他设备无法访问该站点,别信网上那些啥开防火墙,开端口胡扯的,根本没关系,因为gulp的web-server就只有这点功能,想要服务器局域网都能访问,在gulp-webserver官方文档的FAQ给出了解决方案:Set 0.0.0.0 as host option.

优化资源

gulp的主要功能就是文件的合并,压缩,MD5,由于我的前端JS是基于requireJS构建的,为了在页面加载时提高响应速度,就需要减少文件请求数量并压缩文件的大小,为了做这些操作,需要下载

文件更改保存时浏览器的自动重载(先跳过三)

在我们的开发过程中,我们经常会修改html,CSS,js文件,由于我们的生产目录与开发目录不一致,所以需要执行GULP命令来发布文件到生产目录。但是频繁的关闭服务与重启服务,这样就造成了很多时间浪费,所以我们需要利用gulp.watch来监视文件的改动,并将这些改动重新发布到生产目录,并重启服务(非手动)。由于个人觉得gulp-webServer与gulp-livereload的局限性,所以讲服务采用browser-sync来代替gulp-webServer,后者自身支持热更新,无需在浏览器安装任何插件(gulp-livereload需要安装livereload插件),直接上源码:

var browserSync = require("browser-sync").create(); //引入模块 
/*每次发布生产文件前,先将dist目录下的文件情况*/
gulp.task("clean",function () {
  return gulp.src([
    'rev-manifest.json',
    'dist/js/*.js',
    'dist/index.html'
  ]).pipe(clean());
});   
/*每次app.js变动时,需要清除rev-manifest.json文件中的映射,使其保证只有唯一的一个映射*/
gulp.task("JSreload",function(){
  return gulp.src(['rev-manifest.json', 'dist/js/*.js','dist/index.html']).pipe(clean());
})     
/*每次任务发起前,先清空温江,然后再依次发布文件,启动服务器,监听变动*/
gulp.task('server', ['clean'], function() {  
  runSequence(       
    "revImg",
    "revCss",
    "revJs",
    "optimizeJS",        //- - 文件合并与md5并去.js后缀
    "updateHtml"      //- 首页路径替换为md5后的路径
  );      
  browserSync.init({  
    port: 80,  
    server: {  
        baseDir: ['dist']  
    }  
  });  
//监控文件变化,自动更新 
  gulp.watch('js/app.js', function(){
      runSequence(
      "JSreload",
      'optimizeJS',           
      "updateHtml", 
      browserSync.reload     
    );       
  });  
  gulp.watch('css/*.css',  function(){
    runSequence(
      "revCss",
      browserSync.reload     
    );       
  });
  gulp.watch('index.html',  function(){
    runSequence(
      "updateHtml", 
      browserSync.reload    
    );       
  }); 
});
/*将server事务,注册为默认任务*/
gulp.task('default',['server']);    

基于以上操作,命令行运行gulp ,我们就开启了一个基于browserSync的本地服务器如下图所示,并且局域网内的设备都可以通过主机IP+port访问应用。 image

预处理器文件编译

暂时没用到,后面用到再增加,可以参考其他人的