Alloyteam Conf 2017 现场实录

6,486 阅读21分钟


首先是大佬登场介绍 AC 是每年一度的 Alloy Team 团队技术分享会,而前段时间 TFC 主要是邀请业界大牛的技术分享。AC 希望给开发者提供最好的参会体验,也希望现场的各位分享自己的故事。
插个开场舞图:

第一场:面向亿万级用户的 Web 同构直出

以兴趣部落为例讲解面向亿万用户的 Web 同构直出。
首先介绍了一些基本概念。
什么是直出?

以 Node 作为后端语言实现的服务端渲染页面并输出的技术。

什么是同构?

客户端与服务端可以共享部分代码

然后给出了两个二维码,让大家扫码体验哪个是直出前页面,哪个是直出后页面。


接下来主要分两部分内容继续议题,如何同构直出以及服务的高可用行。

如何改造直出

同构直出的三要素
  • DOM 一致性
    保持DOM一致性利用了 React 虚拟 DOM 的思想。服务端通过 ReactDomServer.renderToString 拼装 HTML 字符串,返回给浏览器。浏览器端根据服务端返回的数据 ReactDom.render 出真实 DOM。
  • Data 一致性
    保持数据一致性服务端通过http.request请求需要直出页面的数据,通过 store 保存数据,浏览器端通过Provider 中的 store 属性渲染服务器返回的数据。
    遇到的问题:前端代码不能在服务端执行,浏览器使用 ajax,Node端使用 http.request 如何解决。
    不能在服务端执行的前端代码通过打标签,使用构建工具处理。
    `_BROWSER_`;
    ...
    `_END_`;
  • Route 一致性
    前后端路由保持一致性,避免返回错误页面。
方案

通过直出框架机来实现。

  • 首先是项目构建
  • 接下来是 actions 提取。
    整个框架机的工作流如下:

高可用性

开发调试

框架集本地开发调试通过使用命令行工具包 fireDragon ,执行以下命令就可以啦。

npm link // 建立全局链接
firedragon init //初始化路由配置
firedragon // 读取路由配置文件,启动服务
容灾

容灾采用两种方式,框架机进行柔性处理,以及接入层转发。

压测

通过 wetest.qq.com 平台监控各项应用数据了解承受能力,找出性能瓶颈。

灰度

采用灰度发布,逐步扩大直出页面访问用户从 10 拓展到 3亿,服务器从 1 台拓展到 111 台。

监控告警

服务器层面从 CPU 使用率,CPU 性能,内存占用,磁盘 IO,网络 IO 监控。
运行时数据从脚本错误,测试,PV/UV,直出服质量,后台接口质量和染色日志。

第二场:大型 Web 项目可用性提升零脚本错误的实战

零脚本错误实战主要从下面五个方面展开讲解。

如何发现代码出了问题

客户反馈?老板连环夺命 call ? 经历了这些思考采用更高效的方案。

基础监控体系组成

体系组成分为三步,监听->上报->数据收集系统。

  • 监听
    使用 try-catchwindow-onerror
  • 上报
    发送 ajax请求或者直接使用 img
  • 数据收集系统
    • 提供上报接口
    • 存储上报数据
    • 数据分析展示

错误信息分析与优化

上报发现遇到很多 script error 错误,是由浏览器的同源策略导致的。
如何解决呢?script 标签添加 crossorigin属性,后端做 CORS 处理。

Web 安全与脚本错误

错误脚本分析基于 SourceMap 监控方案解决。
通过生成 SourceMap 文件维护源文件和处理后文件的映射关系,使用 VLQ 编码来存储映射。
或者使用开源的 sentry

CSP 内容安全策略

监控、上报白名单中的前端资源。

  • 使用方式
    HTML Meta 标签
    <meta http-equiv="Content-Security-Policy" content="script-src 'self'" >
    HTTP Header(响应头带上 CSP 的指令)
  • 配置
      使用上报(不拦截),拦截两种方式。
直接采用 https://

开发测试与脚本错误

推荐了两个插件,js-error-dialog报错弹窗和prettyjs代码格式化、高亮和错误展示。

第三场:如何构建后现代前端工程化开发体系

分享提问开发者开发的第一个网站为引导,引出前端工程化的议题,并且从开发环境、衔接和生产环境三个环节来讲述。

开发

开发工程化从三个主要环节进行,脚手架与命令行、组件化和接口联调。

  • 脚手架与命令行
    脚手架的搭建从5个要素考虑:快速部署与更新、团队约定、快速配置、页面性能、构建性能。
    alloy team 基于以上几点要素开发了 steamerjs。即装即用的插件式机制方便项目快速搭建,只需要键入以下几条命令就好啦:
      npm i -g steamerjs
      npm i -g steamer-plugin-kit
      npm i -g steamer-react
      steamer kit
  • 组件化
    组件化推荐采用跨项目组件的开发方式,把通用组件发布到公网 npm 或者 npm 私服,方便跨项目的组件复用。
    业内优秀的组件库如 element
  • 接口联调
    推荐了一些工具和插件,postman,easy-mock.com,steamer-plugin-mock

开发环境与生产环境衔接

  • 数据上报与错误监控
    主要采用一些成熟的市场方案。统计推荐百度统计 or 腾讯统计,性能监控推荐 wetest, 日志监控推荐 sentry.io
  • 持续集成
    开源项目可以使用 github + travis-ci,私有项目可以使用bitbucket + pipeline or github + pipeline
    代码规范推荐使用 IDE 提醒 + pre-Commit 检查。
    测试环境部署
    • 多域名测试环境
      对于纯Web站,不需要代理工具,测试便利。节省服务器。
    • 单域名多测试环境
      对于APP内嵌页面,可以方便测试。各测试环境独立,互不干扰。

生产环境

生产部署推荐使用腾讯云(此处有广告硬植入,哈哈~)

第四场:Service Worker 主题分享

首先介绍了什么是 Service Worker。
Service Worker 是浏览器后台运行 JS 处理网络请求和管理缓存相应的方法。Service Worker 提供了一个 Application Cache 的替代方案。

快速上手

最简单的 Service Worker 样例:

 if ('serviceWorker' in navigator) {
    navigator.serviceWorker.register('./sw.js')
 }

 // sw.js
 self.onfetch = (e) => {
    e.respondWith(new Response('Hello Service Worker!'))
 }

基础知识

  • 生命周期
    首次加载会经历 Installing -> Active,出错的话会进入 Error
  • 更新机制
    Service Worker 更新会经历 Installing -> Waiting -> Active,出错的话同样会进入 Error

工程实践

  • 兼容性

  • Service Worker 的 URL
    千万不要打版本号!!!正确的做法是保持 SW URL 不变,且与主页在同一域名下。

    xxx.com/xxx/sw.js
  • Dev Tool
    在 Chrome 调试工具 network 选项中,Size 栏为 from Service Worker就是启用了 Service Worker 加载的资源。

  • 自动构建
    业界比较成熟的是谷歌的 sw-precache。使用也很简单,一行命令搞定:

    sw-precache —config=sw-config.js
    // sw-config.js
    module.exports = {
      // 需要SW缓存的⽂文件,默认使⽤用缓存优先策略略
      staticFileGlobs: [
          'dist/cdn/**',
          'dist/webserver/**'
      ],
      // 前缀替换
      stripPrefixMulti: {
          'dist/cdn/': '//path/to/your/cdn/',
          'dist/webserver/': '//path/to/your/webserver'
      },
      // 输出路路径
      swFile: '/dist/webserver/sw.js',
      // 动态内容的缓存策略略
      runtimeCaching: [{
          // 对于所有url中带有 '/api/' 的请求,优先⽹网络请求,若离线,则使⽤用之前的缓存
          urlPattern: /\/api\//,
          handler: 'networkFirst'
      }]
    };

当然 sw-precache 也有一些缺陷,比如没有集成的 Runtime,不支持外部 CDN 资源。
考虑到这些缺陷,基于 sw-precache 做了一些改进解决这些缺点,命名为 create-sw。

  • 业务接入
    手机QQ-附近-颜值配对模块使用了该方案。约为 80% 的的安卓用户,因为安卓手机 QQ 内置腾讯浏览器采用 X5 内核,Service Worker API 支持率达到了 91%。采用 Service Worker 的有效率约为 50%。

为什么需要 Service Worker

  • 资源换成
  • 加载速度比 304 更快
  • 离线能力
  • 完全的缓存控制能力
  • 渐进式增强,无痛迁移

最后还提到了 PWA 实践,有兴趣可以详细了解。

第五场:Javascript 与机器学习

首先简单描述了人工智能的大背景,人工智能时代背景下每个人都需要了解或学习人工智能。之后推荐了一个前端深度学习库 deeplearn.js

分享目标

  • 掌握机器学习基本概念
    机器学习是生成算法的算法。人工神经网络是目前最流行的机器学习方法,神经网络由大量的人工神经元联结进行计算。
  • 掌握神经网络分类器
    主要从线性分类、异或分类和数据分类几个方面讲述,并且现场运行了数据分类的 Demo。

  • 掌握两种神经网络训练方法
    • 遗传算法变异神经网络
    • 反向传播矫正神经网络
  • 掌握遗传算法+神经网络的案例
    以 flappyBird 为例。通过随机生成一批种群 -> 执行设定的关卡程序 -> 待种群全部阵亡按照分数高地排序取前20% -> 对选出的20%以及由他们变异出的80%的种群进行下一轮关卡程序。
    继续第二步执行关卡程序直到关卡测试终止。
  • 掌握反向传播算法
    反向传播是“误差反向传播”的简称,是一种与最优化方法(如梯度下降法)结合使用的,用来训练人工神经网络的常见方法。该方法计算对网络中所有权重计算损失函数的梯度。这个梯度会反馈给最优化方法,用来更新权值以最小化损失函数。反向传播要求有对每个输入值想得到的已知输出,来计算损失函数梯度。因此,它通常被认为是一种监督式学习方法。
  • 掌握手写数字识别案例
    通过机器学习提高手写文字识别率。

总结

  • 任何可以使用 JS 写的,都会有 JS 写。
  • webgl 用来训练神经网络是不错的选择
  • AI 技能和数据库编程,网络编程一样会成为通用技能
  • 量子计算无法遍历所有神经网络权重树,还是需要研究算法
  • 机器学习在基础物理没有突破之前无法得到质的突破
  • 毁灭人类的一定是人类或者自然灾害,而不是人工智能

第六场:高效 H5 动画设计与性能优化

分享主要以兴趣部落送礼页面的实践为例,分以下几个话题讲述:

常用动画方案

  • GIF
    缺点明显
    • 是一张图片资源
    • 最多 256 种颜色
    • 支持全透明,不支持半透明
    • 不适用于”真彩色”-RGB
    • 动画质量遇资源体积成正比
  • APNG
    缺点明显
    • 也是一张图片资源
    • 非官方认可
    • 第一帧是 PNG,后续是拓展块
    • 支持度低
  • Video
    是一种不错的方案,不过带宽问题需要考虑。
    • 设置autoplay 属性自动播放
    • 设置 loop 属性控制循环
    • 视频长度很重要(12s-30s)
    • 带宽是个问题
  • SVG
    • 矢量无失真
    • 难以呈现复杂位图效果
    • 复杂动画具有渲染问题
  • Canvas
    推荐,也是业界主流的方式。
    • 可编程画布
    • 2D Context API
    • 单个 Dom 元素,无状态
    • WebGL
  • JS
    • 使用 JS 控制 DOM、CSS
    • 自身维护时间流和动画速度
  • CSS3
    • 过渡动画(transition)
    • 关键帧动画(keyframes)
    • 渲染引擎会使用跳帧保证动画的流畅性
    • 渲染引擎会停止或降低不可见元素动画的刷新频率


这么多方案选哪一种好呢?性能说话!可以使用 FPS 工具 stats.js 进行性能分析。

移动端屏幕适配

移动端的屏幕适配分为以下几种场景阐述:

  • 背景
    • 背景为纯色或渐变色,直接铺满
    • 背景为单张大图,设置为 cover
    • 背景为可重复性纹理,直接 repeat 就好
  • 主体
    • 主体区域默认 iphone6 基准尺寸
    • 基于主体区定位的元素
    • 默认屏幕居中缩放
    • 采用 rem 保持页面完整性及好的用户体验
      如何界定主体区域?
  • 边缘元素
    • 音乐图片、操作指引等主体无关元素
    • 处于屏幕固定位置,基于屏幕定位

性能监控遇优化

需考虑内存消耗和帧率,推荐工具 stats.js 和 Chrome developTool。

  • 使用 GPU 硬件加速

    • 避免频繁重绘和重排
    • 避免 width 和 height,使用 transform:scale(x)
    • 避免 margin、top / left,使⽤用 transform: translate(x, y)
    • 元素创建后,⽴立即设置 transform: translateZ(0) 或 translate3d(0,0,0)
    • 元素会使⽤用独⽴立的 layer 参与渲染
  • 图片压缩

  • 性能问题
    性能的监控使用之前推荐的 stats.js 就好。分析发现 translate 的表现明显优于 background。
    测试过程中发现动画有锯齿,卡顿明显,有可能是图片太大导致的。

  • 性能调试 timeline
    锯齿是如何产生的呢?

    • FPS 降低时,GPU 罢工
    • 大图 -> 丢帧
    • 大图烧显卡
  • 帧动画图片性能
    帧动画到底用不用合图?建议不要合图使用 HTTP2.0 即可。合图之后的雪碧图会有空白区域,一个动画大概 40 - 50 帧的图片,单张图片要 500 500 px,合并图后达到 4000px 3000px。

  • 帧动画优化方案 - zip 压缩包

    • 资源打包,减少请求数
    • 避免单个⼤大图渲染瓶颈
    • 前端解压使用jszip stuk.github.io/jszip/
    • jszip解析出ArrayBuffer,base64 ? Blob
    • URL.createObjectURL(blob)
      使用zip 动画资源 CDN 部署,max-age和前端缓存加速。
  • 帧动画优化方案 - indexedDB

  • 硬件加速 will-change

    • 提前通知浏览器元素哪些属性会发生动画
    • 浏览器预优化
    • 不能过多滥用
  • 兼容性问题 CSS3 动画控制

    • 使用 setTimeout 的 CSS3 动画结束后回调误差大
    • CSS3 Animation提供了动画事件 animationStart & animationEnd
    • 部分机器不支持
    • 降级使用JavaScript实现精准控制
  • 兼容性问题 FPS 控制

    • setTimeout/setInterval。执行时不准确
    • 使用 requestAnimationFrame
    • 与浏览器刷新频率保持一致
    • IOS 全部支持,Android 支持率约 89%
  • 限制帧率 RAF
    一般建议保证 60 FPS 的帧率。如果不限制帧率的时候,使用 RAF 自由发挥,但需要注意资源包体积。

  • 兼容性问题 canvas Retina适配
    250px 250px 的原图到 500px 500px 的画布上发现变模糊了,原因是设备像素比 window.devicePixelRatio 导致的。可以画在 500px * 500px 的 Canvas 上再 scale(0.5)。

性能评分

导致性能问题的原因可能是机器性能低,内存紧张,帧率低。
性能评分的原理是页面创建一定数量的DOM,并添加 transform 和 opacity 变化。根据帧率衡量机器性能。

  • 性能评分方法
    首先在页面创建 200 个正方形 DIV 元素。
    每个 DIV 宽度和高度均为 100px,DIV 初始位置的中心点与页面的中心点重合。
    设置时间 t1 和 t2,在每一帧周期内对页面中每个 DIV 进行随机位移、缩放和透明度变换。
    开始时间 t1,结束时间 t2,帧数为 n
    fps = 1000 * n/t
    取帧率的10倍为性能评分
    ``` score = floor( 10000 * n / t)
    分级
  • 提高性能措施
    • 减少帧数(图片数)
    • 减少装饰及动画复杂度
    • 取消特效
    • 使用 @1x 图片

自动化与可配置性

产品频繁新增/更换礼物,如果每次更换都修改代码无疑是不可取的。因此需要把动画效果改为可配置,定义统一配置文件,动画资源由 packageID 唯一标识,礼物配置与动画资源分离。

  • “常规操作”
    • 礼物 “面板” 懒加载
    • 礼物 “配置” 预加载
    • 礼物面板 “图片” 预加载
    • 面板呼起时送礼 “动画资源” 预加载
    • 送礼 “动画资源” 缓存 indexDB

课程资源

github.com/Caesor/AC-H…

第七场:在 ES7 时代下的异步处理机制

Javascript 语言的执行环境是单线程的。如果一个任务耗时很长,就会阻塞后面的任务,导致页面无响应。于是,Javascript 将任务的执行模式分为同步和异步。

原生 Javascript 解决异步的方式

  • 回调函数
    回调函数优点和缺点都很明显。
    优点是简单、容易理解和部署。
    缺点是不利于代码的阅读和维护、高度耦合、流程混乱,而且每个任务只能指定一个回调函数。
  • 事件监听
    与回调不同。添加事件监听,在异步函数触发监听事件处理逻辑。
  • 发布/订阅
    发布/订阅与“事件监听”,类似,但优于后者。可以监控程序运行,并且实现多任务绑定。

通过 jQuery 解决异步方式

通过jQuery when方法同样可以实现类似于 Promise 对象的功能。并且通过 when 可以使得多个异步并行请求,然后获取返回值进行回调处理
通过 done 或者 then 两种方式进行回调。

通过 Promise 解决异步方式

promise的功能是可以将复杂的异步处理轻松地进行模式化。
接着简单介绍了 promise 的 API,就不再详细讲述了:

  • then(onResolve, onReject)
  • catch(onReject)
  • resolve(callback)
  • reject(callback)
  • all(Array)
  • race(Array)

同步调用和异步调用同时存在导致的混乱

Promise只能进行异步调用方式。
理论上,在promise.then 执行的时候promise对象已经是确定状态,从程序上说对回调函数进行同步调用也是行得通的。
Promise也会以异步的方式调用该回调函数,这是在Promise设计上的规定方针。
当需求变得复杂后,多层嵌套和链式调用,也让代码看起来不那么优雅。

ES7下异步处理的终极解决方案

通过 async/await 解决异步方式有以下几个有优点:

  • 简约而干净
  • 同、异步混合错误处理
  • 条件判别
  • 轻松获取中间值
  • 错误堆栈信息
  • 调试便捷


async/await 基本规则:

  • async表示这是一个async函数,await只能用在这个函数里面。
  • await 表示在这里等待promise返回结果了,再继续执行。
  • await 后面跟着的应该是一个promise对象。
  • await等待的虽然是promise对象,但不必写.then(),直接可以得到返回值。

之后是下午甜点:

第八场:ES2017时代的后函数式编程

首先以一个 Demo 为例判断是否为函数式编程。

function f(h){
    return h + 1;
}
var x = 3;
f(x + 1);

理解函数式编程意味着:

  • 有能力阅读开源代码
  • 开拓新的思维方式
  • 编写整齐有序的代码

通过点击计数任务不同的写法来讲述函数式编程的特点。代码传送门:

什么是函数式编程

函数式编程是种编程范式,它将电脑运算视为函数的计算,关注纯逻辑与数学运算。

函数式编程特点

  • 声明式与命令式
  • 流式,更适合人的阅读

函数式编程基石 —— 纯函数

纯函数只有逻辑运算和数学运算,同一个输入总得到同一个输出。纯函数的优点是可缓存、可测试、可并行(web worker),可进行惰性计算。

  • 变量缓存
    var memoize = function(f) {
    var cache = {};
    return function() {
      var arg_str = JSON.stringify(arguments); 
      cache[arg_str] = cache[arg_str] || f.apply(f, arguments);
      return cache[arg_str];
    };
    };
  • 副作用
    • 往数据库插入记录
    • 发送一个 http 请求
    • 可变数据
    • 打印/log
    • 获取用户输入
    • DOM 查询
    • 访问系统状态等
      这些函数执行并不能总是返回相同的结果,可以通过延迟执行避免产生。

函数的变换和操作

  • 柯里化
    通过柯里化将低阶函数转换为高阶函数,可以形象地比喻成吃豆豆的过程。
  • Compose
    从右至左依次执行。
    let f = x => x + 1;
    let g = x => x * 2;
    g(f(1))
    compose(g, f)(1)
  • Functor
    functor 是实现了 map 函数并遵守一些特定规则的容器类。通过调用 Container.of 把东西装进容器中隔绝外部影响,通过 Map 来接触、操作窗口内的值,获得包含新值的容器。
    var Container = function(x) {
      this._value = x;
    }
    Container.of = function(x) {
      return new Container(x);
    }
    Container.of(3)
    // => Container(3)
    Container.prototype.map = function(f){
      return Container.of(f(this._value))
    }
    Container.of('flamethrowers').map(function(s) {
      return s.toUpperCase()
    }
    // => Container('FLAMETHROWERS')
  • Monad
    实现了 chain 的 Functor。
    chain( flatMap )
    使用Map执行后(可能会加容器/卷)剥离一次容器/卷,不会产生新的卷。

流式特点

上个函数输出是下个函数函数输入。
流式框架有 xtream 和 RxJS。

实战

  • Redux Middleware 源码
  • CycleJS 代码解读

最后附上参考资料

第九场:如何把自己构建成大型互联网公司需要的前端人才

老教授首先抛出一个经典问题,“如果你是一个大学毕业生,你会选择大型互联网公司还是创业公司?”。
这个问题从来没有标准的答案,并且现场的回答者就很坚定的选择小公司,而老教授的建议是选择大公司。

大公司有什么好?

  • 丰富的学习资源
  • 活跃的技术交流氛围
  • 专注做前端深入研究
    合格面试官需要具备完整前端知识体系,抓住重点辨别人才。
    关于前端校招的考察内容可以查看老教授的这篇文章《前端校招面试该考察什么?》

社招与校招的区别

校招面试流程

前端基础

  • HTML
    • 常用的 meta 头
    • 语义化
    • HTML5 新增功能
    • HTML 渲染解析知识
  • CSS
    • 可读规范的 CSS 代码
    • 盒模型
    • CSS3 特性:动画、弹性布局等
  • JS
    • 事件模型
    • 闭包和内存泄漏
    • 原型链
    • 渲染树、重排重绘、分层渲染等(进阶)
  • HTTP
    • 常见 HTTP 状态码
    • 不同请求类型的区别
    • 如何缓存
    • HTTP2
  • 调试
    • 如何抓包
    • 如何 debug 程序问题
    • 如何做移动端调试
    • 如何发现页面问题
  • 移动 Web 开发
    • 移动 Web 开发和 PC Web开发的区别
    • 响应式布局
    • 移动端的手势和事件
    • 怎么提高移动页面的渲染性能

以及一些综合知识考察,比如:用户从输入 url 到最终页面展示,这个过程中发生了什么?老板反馈页面打开白屏,而你手机是正常的,怎么办?页面卡顿,怎么优化?

校招前端专业知识是考察重点吗?

如果你连前端基础知识都没掌握好,我怎么相信你是热爱前端的学习者?

项目经历

一个字,怼!找出项目经历的关键词,然后由浅入深,一直问到答不上来为止。暗中观察团队协作意识、攻克难题决心、搜索资料能力等。

大学阶段该做什么积累?

  • 补齐学好前端基础
  • 跟进新技术,尝试新语言
  • 实践项目中吃透用到的技术项

怎么用大公司标准要求自己、提升自己?

  • 技术准备
    • 补齐基础知识
    • 单点深挖
      大公司推崇一专多长
      大学的时候以广度为主,拓展视野;
      工作之后以深度为主,单点深挖;
      当达到瓶颈后,再次向广度拓展,打通知识。
                        ————百度某总监
    • 以技术项目练兵
      从业务优化出发,以好玩有趣为主,挖掘技术项目。
    • 写文、分享
  • 思想准备
    • 沟通能力
      用沟通代替自作主张
      多做反馈,主动反馈
      有风险及时抛出
    • 正式资源不足
      “如果什么都准备好了,谁都能做,那要你干嘛?”
    • 问题到我为止
    • 培养高效工作方法

跳槽社招

  • 基础知识
    基础知识相比社招有更高的要求。

  • 项目经验
    项目经验需对比腾讯的高级前端工程师要求。

最后,乐观自信和技术能力一样重要!

到这里本次 AC 大会的现场实录就更新完了,一整天 9 场的技术分享加圆桌讨论,议题也是从项目搭建、优化、监控到编程思想、前沿科技以及职业发展涵盖各个方面,真的是干到不能再干的大会了。
一天很短,内容很长,希望对大家有所帮助,未来几天慢慢消化,接下来也可以多多交流。