京东PLUS会员项目前端性能优化实践

作者:Frans 京东PLUS会员项目是国内第一个电商付费会员项目,正式开通的会员数量已破千万。我团队从2016年接手这个项目的前端开发工作,一路见证了它的高速成长,也为此贡献了自己的力量。 这个项目有几个特点: 第一,需求多。移动端使用 H5 开发,曾有人问为什么不用原生或者 RN 开发? 我觉得吧,以这个项目的需求数量和迭代速度来看,连 H5 都难以 hold 的住,还是不要奢望原生和 RN 了。 第二,产品经理多。一般的项目对接一两个产品经理,这个项目我们需要对接一个异地的产品经理“团队”;一般的项目换产品经理一个一个的换,这个项目一批一批的换……我们已经送走好几届PLUS会员产品经理了。铁打的研发,流水的产品经理。 所以说,PLUS会员项目是业务方滴,也是项目经理滴,还是产品经理滴,但终归是俺们研发滴。每念及此,我的耳边总会响起叶倩文的那首老歌:“天地悠悠,过客匆匆,潮起又潮落…”。 书归正传。用户众多和需求迭代频繁,确保线上安全稳定始终是第一要务。所以在架构调整和性能优化方面我们一直都小心翼翼,以一些小修小补为主,只有到大规模改版的时候才会有大的升级改造。不过,平时我们对这些问题的思考和实践却不曾停止过,我们验证了一些行之有效的优化方案,在下一波改版中将会得到应用。 我虽然不完全认同“前端开发每十八个月难度翻一倍”的说法,但这一行发展迭代速度快却是不争的事实。若等到这些优化方案全都应用上再出来念叨,可能就显得不那么新鲜了。所以,我决定先把这些方案拿出来分享,和感兴趣的小伙伴一起讨论,进一步完善。 这些方案主要针对移动端,优化核心方向是提高首页的加载速度,特别是首屏和弱网络环境下的加载速度。从持久化缓存、削减代码量、优化接口请求、提升主观感受等方面下手,比较大的改动是应用 PWA 和升级架构。 PWA 离线缓存可以极大的提升用户体验,不过它对于首次加载速度并无提升作用,还得靠其他优化手段,这是一套组合拳。我们先从架构升级说起吧。 架构升级 项目计划迁移到 Gaea4.0 脚手架[1],这是我们团队基于 webpack 4 开发的一套通用 Vue 单页面应用脚手架,此前的系列版本已经过数十个项目的验证,还是比较稳定的。近期新推出4.0版相较之前版本有着不小的改进。 webpack 升级到了 4.0 Babel 升级到了 7.0 Vue-loader 升级到了 15 重构了上传插件,一键上传到测试服务器更快更稳定 针对我厂手机和电脑位于不同局域网无法互访的问题,集成了自主研发的 Carefree 解决方案[2],方便真机测试调试 集成了 NutUI 组件库[3],可按需加载需要的UI组件 集成了自主研发的基于swagger的数据mock工具SMOCK[4] 支持自动生成骨架屏[5] 支持 PWA … 迁移有几个主要目的: […]

体现工匠精神的Resource Hints

作者:杨磊 背景 八卦图代表了古代算法数术的结晶,主要是为了提供一种预测人类行为的方法论,这种能提前预测的行为古往今来都备受人们追捧,既然预测这个行为那么受欢迎,互联网行业是不是也进行了这方面的技术储备呢?没错互联网行业也已经存在此功能了。 自从互联网兴起之后,网站也越来越漂亮,越来越大,性能就是大家一致追求的方向,大家也都想预测用户下一步行为。从浏览器厂商到各个开发者都想通过各种方式来提升用户的体验,所以提前知道用户的下一步行为,预先加载用户下一个页面的资源就是开发者要追求的下一个技术方向。之前大家都比较习惯使用 JS 来动态控制页面内容,殊不知我们还有一些更好的方案来替换这些方法。 我们这么搞? 简单粗暴的可以直接页签最下端引用加载; 高级一点:我可以在执行的 JS 代码来进行 load 加载; 更高级的替换方案是什么呢? 听小道消息说谷歌这么搞! 当你在谷歌浏览器输入域名一部分时会根据记录提示补全,如下图所示: 你知道吗?这个时候谷歌已经对你有意向访问的域名搞事情了。 因为此阶段,实际上谷歌已经大概知道你即将访问哪个页面,此时浏览器会根据捕获的页面 URL 进行提前操作,如提前解析 DNS,提前加载部分资源等事。具体能预先处理到何种程度,这个我还真的没有实际监控到太确切的数据,把它当成小道消息吧。 这种预先处理页面的方式,不只是开发的程序猿与攻城狮们,浏览器厂商也在想办法去推动这个行为的”合法化“,也就是进入 W3C 的标准,当然路途坎坷,但我们还是见到了一些效果,这个效果就是我们接下来要讲的Resource Hints。 Resource Hints 是什么? Resource Hints 实际上就是“合法化”的提供了使用浏览器原始语言来进行的一些提前预测行为的能力,W3C 也陆续增加了很多功能,主要包含如下: dns-prefetch preconnect prefetch prerender preload 根据 W3C 的记录,最早的草案是在2014年10月21日提出的,中途经过了几十个版本的迭代(好吧,我的确是一个版本一个版本的翻来看的),最新的草案是2018年1月15日发布的。W3C 也针对此进行了多次的优化,虽然现在的使用频率以及兼容性依然还不是特别的完美。 Resource Hints能做什么? 谈了这么多,那 Resource Hints 具体能干什么呢?我们来一个一个的说。 1、dns-prefetch 谈到这里,不得不先介绍一下 DNS 是一个什么东西。 DNS(Domain Name System) – […]

HTML5 Audio的兼容性问题和优化

作者:刘新金 引入 本人在双十一期间,做的一个移动端互动项目中,遇到一个在 App 、微信、h5页面环境切换选择音频播放的功能,在测试的时候出了不少兼容性问题,这里有很多值得探索的知识,今天我们就来看一下这个 HTML5-Audio。 Audio 标签用于定义声音,比如音乐或其他音频流,HTML5 的 Audio 标签在很大程度上取代了 Flash 来播放音乐。 一、默认样式 Audio 标签在浏览器中的默认样式如下图所示,需要注意的一个地方:需要配置 controls 属性(是否显示默认控制条,是 Audio 标签的控制属性),否则不展示样式效果。 二、Audio 支持的音频文件格式 1、OGG: OGG 是一种新的音频压缩格式,类似于 MP3 等的音乐格式。OGG 是完全免费、开放和没有专利限制的。OGG 文件格式可以不断地进行大小和音质的改良,而不影响旧有的编码器或播放器。 2、MP3: MP3 是一种音频压缩技术,其全称是 MovingPictureExpertsGroupAudioLayerIII(动态影像专家压缩标准音频层面3),简称为 MP3 。它被设计用来大幅度地降低音频数据量。将音乐以 1:10 甚至 1:12 压缩成容量较小的文件,而对于大多数用户来说重放的音质与最初的不压缩音频相比没有明显的下降。 3、WAV: WAV 是微软公司开发的一种声音文件格式,它用于保存 Windows 平台的音频信息资源,被 Windows 平台及其应用程序所广泛支持,标准格式化的 WAV 文件和 CD 格式一样,因此在声音文件质量和 CD 相差无几。 三、兼容性问题 我们来从下面几个角度看兼容性问题: 1、音频格式的兼容性 […]

一个表情引发的思考

作者:石文帅 简介:字符集的由来是什么?各种字符编码又有什么关系?乱码是如何出现的?带着这些问题,我们一起倾听字符的故事。 前几天测试给提了个 bug ,“在长度限定的文本区域,输入表情时会展示乱码”。不由的产生了一些想法:这些表情是什么东西?为什么会出现乱码? JS 是使用哪种编码方式?便查阅了相关文献,最终找到了答案,今天就详细说一说编码的故事。 一、比特、字符、字节 在聊编码之前,有几个基础的概念需要先明确一下: 比特位:比特位即 Bit ,是计算机最小的存储单位。以 0 或 1 来表示比特位的值。也是网络信息传输的基本单位。 字节:8 个比特位表示一个字节。 字符:字符是可使用多种不同字符方案或代码页来表示的抽象实体。 我们知道,在计算机内部,所有的信息最终都表示为一个二进制的序列。每一个二进制位(bit)有 0 和 1 两种状态,因此八个二进制位就可以组合出 256 种状态,这被称为一个字节( byte )。也就是说,一个字节一共可以用来表示 256 种不同的状态或者符号。如果我们制作一张对应表格,对于每一个 8 位二进制序列,都对应唯一的一个符号。每一个状态对应一个符号,就是 256 个符号,从 0000000 到 11111111 。 二、东方的故事 上个世纪 60 年代,美国制定了一套字符编码,对英语字符与二进制位之间的关系,做了统一规定。这被称为 ASCII 码,一直沿用至今。 后来我们天朝也会用电脑了,但是汉字没办法表示,所以勤劳智慧的中国人民融合了 ASCII 中的数字、标点、字母,还把数字符号、罗马希腊字母与 7000 多个简体汉字整合进去,产生了 GB2312 , GB2312 是对 ASCII 的中文拓展。后来又发现中华文化实在是博大精深,汉字太多,原来的编码不太够用,因此再做拓展,此拓展方案叫做 […]

利用交叉观察器解锁懒加载新姿势

作者:宋成林 懒加载,一个在我们前端性能优化中高频出现的词汇,无论是懒加载图片还是懒加载模块,无非都是希望用户可以在滚动指定视区再去加载相应的资源, 从而达到节省用户流量、提升首次加载时间、减轻服务器的压力的目的。 “懒加载”不是一个新的概念,对于经验丰富的你们来说,一定积累了很多实现方法,但为什本文还要提出来呢?因为我们开发过程中,常用的实现方式都是通过监听页面的 scroll 事件来实现的,这种方法在使用过程中,scroll 事件会被高频触发,强制浏览器重排和重绘,从而不断增加浏览器的压力,导致浏览器性能的损失,有时可能出现卡顿或是闪烁的现象,即使使用了节流与去抖等方法,但还是会产生高昂的计算开销。那是否有更好的方法来解决呢,本文会讲解一种新实现方式,在此之前,先让我们回顾一下常用的实现姿势吧! 常用姿势 姿势一:getBoundingClientRect() 方法 通过 Element.getBoundingClientRect() 方法可以返回元素的大小及其相对于视口的位置。 rectObject = object.getBoundingClientRect() ;返回值 rectObject 对象包含了一组用于描述边框的只读属性—— left 、top 、right 和 bottom ,单位为像素。除了 width 和 height 外的属性都是相对于视口的左上角位置而言的。 如下图: 随着页面滚动,我们可以获取懒加载元素相对于视口的顶点位置 rectObject.top 的像素值,当这个值小于可视区高 window.innerHeight ,表示已经进入可视区,开始加载数据,如果要提前加载,可以设置一个 threshold 阈值。 姿势二: 首先我们获取元素 Element.offsetTop ,获取可视区高度 window.innerHeigh 。 随着页面滚动,实时获取滚动条的高度 scrollTop ,如果元素 Element.offsetTop – 滚动条的高度 scrollTop 小于可视区高度 window.innerHeight 的时候,开始加载数据。 这两种实现方式都是通过监听页面的 scroll […]

© 2019 JDC. All Rights Reserved.