zoukankan      html  css  js  c++  java
  • 【转载】腾讯2016公司代码报告总结

    2016年腾讯公司代码报告已经正式发布,记录下开发过程中遇到的问题,以及一些使用过的东西。
    查看请微信扫码:


    腾讯2016公司代码报告前端篇

    1.使用gulp来开发自动化。在开发中,我们会遇到很多重复性的工作,比如更新代码后刷新浏览器、压缩图片、压缩js、编译sass等等。gulp可以使这些重复性的工作都帮你干了。gulp的使用可以参见gulp官网。 贴出下我使用的gulp脚本(注释很多,一目了然)。

    var gulp = require('gulp');
    // sass 插件
    var sass = require('gulp-sass');
    // 自动同步浏览器插件
    var browserSync = require('browser-sync');
    // 合并文件的插件
    var useref = require('gulp-useref');
    // 压缩js插件
    var uglify = require('gulp-uglify');
    var gulpIf = require('gulp-if');
    // 压缩css插件
    var cssnano = require('gulp-cssnano');
    // 压缩图片插件
    var imagemin = require('gulp-imagemin');
    // 压缩png图片的插件
    var pngquant = require('imagemin-pngquant');
    // 缓存插件,可以加快编译速度
    var cache = require('gulp-cache');
    // 删除文件插件
    var del = require('del');
    // 同步运行任务插件
    var runSequence = require('run-sequence');
    // 给css3属性添加浏览器前缀插件
    var autoprefixer = require('gulp-autoprefixer');
    // sourcemap 插件
    var sourcemaps = require('gulp-sourcemaps');
    var lazypipe = require('lazypipe');
    // 合成sprite图片插件
    var spritesmith = require('gulp.spritesmith');
    var imageminOptipng = require('imagemin-optipng');
    // 编译sass文件,添加css3属性浏览器前缀,reload 浏览器
    gulp.task('sass', function () {
     return gulp.src('./src/scss/**/*.scss')
         .pipe(sass())
         .pipe(autoprefixer())
         .pipe(gulp.dest('./src/css'))
         .pipe(browserSync.reload({stream: true}));
    });
    // 自动更新浏览器任务
    gulp.task('browserSync', function () {
     browserSync.init({
         server: {
             baseDir: 'src'
         }
     })
    });
    // 合并文件任务
    // 在html设置需要合并的文件:
    //  <!--build:js js/flexible.min.js -->
    //      <script src="js/flexible_css.js"></script>
    //      <script src="js/flexible.js"></script>
    //  <!-- endbuild-->
    // 执行任务后,会编译成 : <script src="js/flexible.min.js"></script>
    // 同时会把 flexible_css.js 和 flexible.js 合并成 flexible.min.js
    gulp.task('useref', function () {
     return gulp.src('./src/*.html')
         .pipe(useref({}, lazypipe().pipe(sourcemaps.init, { loadMaps: true })))
         .pipe(gulpIf('*.js', uglify()))
         .pipe(gulpIf('*.css', cssnano()))
         .pipe(sourcemaps.write('maps'))
         .pipe(gulp.dest('dist'));
    });
    // 图片压缩任务
    gulp.task('images', function () {
     return gulp.src('./src/img/**/*.+(png|jpg|gif|svg)')
         .pipe(imagemin({
             progressive: true,
             svgoPlugins: [{removeViewBox: false}],
             use: [pngquant()]
         }))
         .pipe(gulp.dest('dist/img'));
    });
    // 合并sprite图任务
    gulp.task('sprite', function () {
     var spriteData = gulp.src('./src/img/sprite/**/*.png')
         .pipe(spritesmith({
             imgName: 'sprite.png',
             cssName: 'sprite.scss',
             imgPath: '../img/sprite/sprite.png',
             cssFormat: 'scss',
             padding: 10
         }));
     return spriteData.pipe(gulp.dest('./src/img/sprite/'))
    });
    // 删除build目录
    gulp.task('clean:dist', function () {
     return del.sync('dist');
    });
    // 清除缓存
    gulp.task('cache:clear', function (cb) {
     return cache.clearAll(cb)
    });
    // 监控任务,当有sass文件,html文件,js文件改动的时候,刷新浏览器
    gulp.task('watch', ['browserSync', 'sass'], function () {
     gulp.watch('./src/scss/**/*.scss', ['sass']);
     gulp.watch('./src/*.html', browserSync.reload);
     gulp.watch('./src/js/**/*.js', browserSync.reload);
    });
    // 构建最终输出文件
    gulp.task('build', function (callback) {
     runSequence('clean:dist', ['sass', 'useref', 'images', 'fonts'], callback);
    });
    // gulp 默认执行任务
    gulp.task('default', function (callback) {
     runSequence(['sass', 'browserSync', 'watch'], callback);
    });
     

    2.在开发移动端页面的时候,我们需要兼容各种机型,iphone的机型相对来说比较少,但是android的机型却是多种多样,如果按照以前pc上开发页面的经验使用px来开发,肯定会遇到各种兼容问题。虽然可以用media query来适配,但是这种适配将是一个非常繁琐的事情。那有没有更好的解决办法呢?当然是有的。在这里推荐淘宝的可伸缩布局方案 lib-flexible
    实现原理见: https://github.com/amfe/article/issues/17
    需要注意的地方是: 在设置字体的时候需要根据dpr来调整字体大小(如果不设置会导致dpr高的手机因为缩放系数小而导致文字在手机上看起来很小)。如下代码所示:

    [data-dpr="1"] .preloader,[data-dpr="1"] .swiper-slide  {
      font-size: 18px;
    }
    
    [data-dpr="2"] .preloader,[data-dpr="2"] .swiper-slide  {
      font-size: 36px;
    }
    [data-dpr="2.5"] .preloader,[data-dpr="2.5"] .swiper-slide {
      font-size: 45px;
    }
    [data-dpr="2.75"] .preloader,[data-dpr="2.75"] .swiper-slide {
      font-size: 49px;
    }
    [data-dpr="3"] .preloader,[data-dpr="3"] .swiper-slide {
      font-size: 64px;
    }
    [data-dpr="4"] .preloader,[data-dpr="4"] .swiper-slide {
      font-size: 72px;
    }

    3.为了更快的呈现页面,页面使用到的图片第一时间并不加载,而是在预加载界面才加载图片,当然同时也可以加载js和其他多媒体文件等。大家可以在网上找到一些预加载的开源组件,或者自己写一个预加载的组件。

    4.为了减少http请求数,可以把一些小的图片合并成一张雪碧图。默认spritesmith 生成的雪碧图代码是通过像素来定位的。但是我们页面使用的rem。如果使用默认生成的雪碧图代码会导致图片显示并不完整。解决办法是通过background-position 百分比来实现。具体实现原理参见:移动端适配之雪碧图(sprite)背景图片定位
    自己写了一个sass方法来把spritesmith生成的sass代码转换为background-position的实现。如下:

    //spritesmith  生成的sprite.sass,主要是需要获取到sprite图片中各图片的大小,用来计算background-position的值。大概如下代码所示:
     $cloud-b: (686px, 0px, -686px, 0px, 800px, 306px, 1486px, 1173px, '../img/sprite/sprite.png', 'cloud-b', );
    
    // sass方法
    
    $base: 72px;
    @function rem($size) {
      $remSize: $size / $base;
      @return #{$remSize}rem;
    }
    @mixin bgPostion($sprite){
      $iconX:nth($sprite, 1);
      $spriteWidth:nth($sprite, 7);
      $iconWidth:nth($sprite, 5);
      $iconY:nth($sprite, 2);
      $spriteHeight:nth($sprite, 8);
      $iconHeight:nth($sprite, 6);
      $x:0;
      $y:0;
      @if $iconX != 0{
        $x: ($iconX / ($spriteWidth - $iconWidth)) * 100%;
      }
      @if $iconY != 0{
        $y: ($iconY / ($spriteHeight - $iconHeight)) * 100%;
      }
      background-position: ( $x $y );
    }
    @mixin bg($sprite){
      $sprite-width:nth($sprite, 7);
      $sprite-height:nth($sprite, 8);
      background: transparent;
      background-repeat: no-repeat;
      background-size: rem($sprite-width), rem($sprite-height);
      width: rem(nth($sprite, 5));
      height: rem(nth($sprite, 6));
      @include bgPostion($sprite);
    }

    通过使用@include bg($cloud-b); 就可以引入sprite图片中相应的图片了。

    注意点: 在默认生成的sprite图片中各个小图片之间是没有间隔的。这导致使用上面的方法的时候在部分机型上会多显示1像素旁边图片的边框。解决办法是在生成sprite图片的时候参数设置padding值:

    gulp.task('sprite', function () {
        var spriteData = gulp.src('./src/img/sprite/**/*.png')
            .pipe(spritesmith({
                imgName: 'sprite.png',
                cssName: 'sprite.scss',
                imgPath: '../img/sprite/sprite.png',
                cssFormat: 'scss',
                padding: 10
            }));
        return spriteData.pipe(gulp.dest('./src/img/sprite/'))
    });

    在使用帧动画sprite图的时候,可以设置下图片排列算法,比如说横向排练,这样在使用的时候也比较方便。algorithm: 'left-right'

    5.在实现吹风的动画时,具体请看报告第三页,使用了svg来实现。主要是使用path的 stroke-dasharray 和stroke-dashoffset属性。原理可以参考帅气的SVG路径描边动画 (path animation) 实战应用](https://segmentfault.com/a/1190000007811310)
    不过在实现的时候,我们不单单需要风出现也需要风消失。实现的代码如下:

    .cls-wind{
          // 省略其他代码
          stroke-dasharray: 100px;
          stroke-dashoffset: 120px;
          animation:  winds 2s ease infinite;
        }
    @keyframes winds{
          from{
            stroke-dashoffset: 120px;
          }
          50%{
            stroke-dashoffset: 0;
          }
    
          to{
            stroke-dashoffset: -90px;
          }
    }

    注意点: 在使用AI或者PS生成svg图像的时候,生成的文件会有很多多余的信息。可以利用svgo 来处理多余的信息,图像的文件尺寸会减少很多。在这也提一下图片压缩,移动端流量是很宝贵的,图片的尺寸在保证效果的情况下越小越好,但是我在使用过程中发现imagemin 的压缩效果并不是非常理想,虽然可以压缩一点,但是效果不明显。后面使用tinypng 压缩对比的时候,发现tinypng的压缩效果非常好,一般都能压缩个50%的大小,并且压缩后的图片在手机上的表现肉眼几乎看不出来。所以,个人建议在正式发布的时候,使用tinypng把你需要使用到的图片都压缩一遍。

    6.在使用css3动画的时候,我们应该尽量避免浏览器的reflow,reflow会针对整个页面进行重排,比较耗费性能。在实现报告中报告内容下拉的效果时,一开始使用的变换元素的height来实现。代码大概如下:

    @keyframes conten-action{
      from{
        height:0;
      }
      to{
        height:5rem;
      }
    }

    但是这样在一些低端的机型上表现不是很好。后面换成通过变换background-size 来实现,可以明显的感觉到在那些低端的机型上动画流畅了很多。代码大概如下:

    @keyframes content-action{
           from{
              background-size: 100% 0%;
              opacity: 0;
            }
            20%{
              background-size: 100% 20%;
              opacity: 0;
            }
            to{
              background-size: 100% 100%;
              opacity: 1;
            }
    }

    当然css3的动画性能优化还有很多其他方面可以探索。我这就只记录我碰到的情况了。

    7.在报告最后一页,会有一个火箭发射的效果。一开始想使用css3来实现,后面讨论说使用css3工作量太大了,可以使用视频来播放这个动画,现在已经有很多h5页面是用视频来实现的,说明视频方案已经是很成熟了。
    我们目前只支持微信端,这里说明的情况都是针对微信的情况。
    现在微信都已经支持了video的playsinline属性,同时放开的playsinline的权限,好像在去年年底之前还需要向微信申请白名单才可以,现在已经不需要了。playsinline可以让视频内嵌在h5页面中播放,这样会让用户感觉这个视频就是h5的一部分,使用体验上会好很多。我使用的video代码如下:

    <video class="video" id="video" x-webkit-airplay="allow" playsinline webkit-playsinline preload="auto" src="./video/rocket.mp4"></video>

    在开始测试的时候发现,虽然视频可以内嵌播放了,但是在视频上会出现一个全屏和一个小窗的按钮。点击全屏按钮,视频会全屏播放,播放完还会显示广告。。。点击小窗按钮,视频会缩小成小窗。这两个按钮对于报告来说,就是画蛇添足了。后面了解到这两个按钮是可以隐藏的,但是需要向浏览器x5内核那边申请白名单。申请后白名单后,按钮就不会出现了

    andriod的机器不支持autoplay,一定需要有交互(touch,click等)来能播放,所以在第一页的时候当用户touchstart的时候,调用下video.play();video.pause().同时,iphone不支持preload,在第一页调用了video.play(),会触发视频的下载,在最后需要播放的时候,视频可以顺利的播放。

    视频初始化在各个手机上表现的形式并不一样,但是又需要有一个表现一致的效果。解决办法是,在还没有进入到最后一页的时候,设置video的宽高都为1px,等进入到最后一页的时候,在把宽度设为100%,高度设为auto。同时把视频的第一帧设为最后一页的背景图,这样每个人看到的第一眼画面都是一样的。这里需要注意一点,在设置背景图的时候background-size应该设置为cover,不然在播放视频的时候,如果视频的宽高比跟手机宽高比不一样会导致第一帧跳动的感觉,体验上会打折扣。

    在视频播放完后,会有文字再显示出来。 开始的做法是监听videoend 事件,但是这在iphone 上会出现屏幕黑一下,再出现文字。体验上又会打折扣了。问题引起的原因,应该是视频播放完了,播放器的变成了黑色,就像在pc上播放完,播放器黑掉一样。解决的办法是: 设置一个定时器监听video的currentTime,当currentTime距离视频播放的时候还差几百毫秒的时候,显示文字,隐藏视频。大概的代码如下:

    var videoTimer = setInterval(function () {
            if(video[0].currentTime > 6.5){
                if(!videoEnd){
                    $(".check").show();
                    $(".pub").show();
                    $(".p2").css({'opacity': 1});
                    $(".check").addClass('check-ani');
                    $(".pub").addClass('check-ani');
                    $(".dong").addClass('bounceInDown');
                    $(".wish").addClass('wish-ani');
                    videoEnd = 1;
                }
            }
        }, 200);

    不过这需要在制作视频的时候把这一段的时间留出来,同时也要考虑视频结束时跟文字出来之间的衔接,这可以跟设计师讨论研究了。

    难题: 在iphone上偶尔会出现,视频不会播放。但是如果刷新下页面视频就可以正常的播放了。 在用测试机来重现这种情况的时候,又没有遇到,不好定位到具体是啥原因。 现在只有一个猜测的原因:因为 video的play()方法即使是调用了,但是也不一定保证会播放。猜测可能是视频没有缓冲好,在调用play() 方法后,视频并没有播放成功。 后面也是采取了定时去调用video的play()方法来尝试解决这个问题,现在热度也过了,也没有收到视频没有播放的反馈。如果各位客官有碰到视频没有播放的情况,麻烦留言通知声。 在监听视频有没有播放,是通过video 的timeupdate的事件来判断,timeupdate事件在iOS和Android上表现一致。具体的代码如下:

    var videoPlayed = false;
    video.on("timeupdate", function () {
            videoPlayed = true;
        });
    
    // 到第九页时判断
    if(pageIndex === 9){
      videoPlayed = false;
      videoPlayedTimer = setInterval(function () {
      if(!videoPlayed){
                 playVideo();
                 }
      }, 300);
     playVideo();
    }

    补充:
    8.使用视频的时候,开始设计师导出的视频有1M多,这在移动端感觉还是有点太大了,况且视频只有7s。 后来使用了ffmpeg来压缩一下,视频大小减少了很多。从最终的1.8M 减少到了330kb。同时在各个手机上的视频清晰度变化肉眼是很难发现的。
    我使用的是ffmpeg默认的转换参数,当然大家也可以根据需要自己调整。
    ffmpeg -i r.mp4 r1.mp4

    目前能想到的点,就这些了。大家如果看到有什么地方错了,也请指出来,共同学习 ^_^。

    文章转载自:http://www.jianshu.com/p/40a41bdbe054

  • 相关阅读:
    Nginx PHP页面找不到总是返回404
    Bing每日一图
    Vue3
    PHP PDO相关
    IIS 搭建FTP
    vue根据环境不同设置不同的入口文件
    Vue生成打包报告
    Vue项目在执行build命令期间中移除所有consol.log
    Nprogress 的使用
    Vue报错处理
  • 原文地址:https://www.cnblogs.com/lekko/p/6472390.html
Copyright © 2011-2022 走看看