你开始使用渐进启动了么?是不是已经使用过React和Angular中 tree-shaking 和 code-splitting 两个工具?有没有用过Brotli、Zofli和HPACK这几种压缩技术,或者OCSP协议(在线证书状态协议)?知不知道资源提醒,客户端提醒和CSS containment一类的技术?了解IPv6,HTTP/2和Service Worker这些协议吗?
回想那些年,大家往往在 完成了产品之后 才会去考虑性能。常常把与性能相关的事情拖到项目的最后来做,所做的也不过是对服务器上的 config
文件进行一些微调、串联、优化以及部分特别小的调整。而现在,技术已经有了翻天覆地的变化。
一个项目的性能是非常重要的,除了要在技术层面上注意,更要在项目的设计之初就开始考虑,这样才可以使性能的各种隐形需求完美的整合到项目中,随着项目一起推进。性能最好具有可量化、可监测以及可改动的特性。网络越来越复杂,对网络的监控也变得越来越难,因为监测的过程会受到包括设备、浏览器、协议、网络类型以及其他技术(CDN,ISP,缓存,代理服务器,防火墙,负载均衡器和服务器对性能的影响都很大)的很大影响。
下文是一份 2017年的前端性能优化清单 ,阐述了作为前端开发人员,为了确保反馈速度以及浏览器兼容性我们需要考虑的问题。
(你也可以下载 checklist PDF 或者 check in Apple Pages 。优化万岁!)
微优化是保持性能最好的办法,但是又不能有太过明确的优化目标,因为过于明确的目标会影响在项目中做的每一个决定。以下是一些不同的模型,请按照自己舒服的顺序阅读。
根据一个 心理学研究 ,你的网站最少在速度上比别人快20%,才能让用户感觉到你的网站比别人的更快。这个速度说的不是整个页面的加载时间,而是开始加载渲染的时间, 首次有效渲染时间 (例如页面需要加载主要内容的时间),或者 交互时间 (指的是页面或者应用中主要的页面加载完成,并主备好与用户进行交互的时间)。
在Moto G(一个中端三星设备)和Nexus 4(比较主流的设备)上衡量开始渲染时间(用 WebPagetest )以及首页有效渲染时间(用 Lighthouse ),最好是在一个 开放的实验室 中,使用规范的3G,4G和Wi-Fi链接。
Lighthouse,一个Google开发的新的性能审查工具
你可以通过你的分析报告看看你的用户处在哪个阶段,选取其中前90%的用户体验来做测试。接着收集数据,建一个 表格 ,筛去20%的数据并预设一个目标(如: 性能预算 )。现在你可以将上述两个值进行对比检测。如果你始终维持着你的目标并且通过一点一点改变脚本去加快交互时间,那么上述方法就是合理可行的。
由Brad Frost创建的性能分析
和你的同事分享这份清单。首先要确保团队中的每个人都熟悉这份清单。项目中每一个决定都会影响性能,如果前端工程师们都在积极的参与项目概念,UX以及视觉设计的决定,这将会给整个项目带来巨大收益。地图设计的决定违背了性能理念,所以他在这份清单内的顺序有待考虑。
RAIL性能模型 会为你提供一个优秀的目标,既尽最大的努力在用户初始操作后的100毫秒内提供反馈。为了达到这个目标,页面需要放弃权限,并将权限在50毫秒内交回给主线程。对于像动画一样的高压点,最好的方法就是什么都不做,因为你永远无法达到最小绝对值。
同理,动画的每一帧都需要在16毫秒内完成,这样才能保证每秒60帧(一秒/60=16.6毫秒),如果可以的话最好能在10毫秒内完成。因为浏览器需要一定的时间去在屏幕上渲染新的帧,而且你的代码需要在16.6毫秒内完成执行。要注意,上述目标应用于衡量项目的运行性能,而非加载性能。
纵使这个目标实现起来非常困难,你的最终目标也应该是让开始渲染时间低于1秒且速度指数低于1000(在网速快的地方)。对于首次有效渲染时间,上限最好是1250毫秒。对于移动端,3G下移动设备首次渲染时间低于3秒都是可以接受的。稍微高一点也没关系,但千万别高太多。
不要过多的关注当下最流行的工具,坚持选择适合自己开发环境的工具,例如Grunt、Gulp、Webpack、PostCSS,或者组合起来的工具。只要这个工具运行的速度够快,而且没有给你的维护带来太大问题,这就够了。
在构建前端结构的时候,应始终将 渐进增强 作为你的指导原则。首先设计并且构建核心体验,随后再完善那些为高性能浏览器设计的高级特性的相关体验,创建弹性体验。如果你的网页可以在使用低速网络、老旧显示器的很慢的电脑上运行飞快,那么在光纤高配电脑上它只会运行的更快。
最好使用那些支持服务器端渲染的框架。在使用某个框架钱,先记录服务器和客户端的引导时间,记得要在移动设备上测试,最终才能使用某个框架(因为面对的是性能问题,如果在使用某个框架后,再做修改是非常困难的)。如果你使用JavaScript框架,要保证你的选择是被 广泛使用 并且 经过考验 的。不同框架对性能有着不同程度的影响,同时对应着不同的优化策略,所以最好可以清楚的了解你要用的框架的每个方面。在写网页应用时可以先看看 PRPL pattern 和 application shell architecture 。
本图描述了PRPL pattern
上图是application shell,是一个小型的、由HTML,CSS和JavaScript构成的用户界面
根据你整体组织结构的优先顺序和策略,你可以考虑使用Google的 AMP 或Facebook的 Instant Articles 。要知道没有这些你也可以达到不错的性能,但是AMP可以提供一个性能不错的免费的内容分发网络框架(CDN),Instant Articles可以在Facebook上促进你的性能。你也可以建立 progressive web AMP 。
根据你的动态数据量,可以将一部分内容外包给 静态网站生成工具 ,将它置于CDN上,从中生成一个静态版本,从而避免那些数据库的请求。也可以选择基于CDN的 静态主机平台 ,通过交互组件丰富你的页面( JAMStack )。
注意CDN是否可以很好的处理(或分流)动态内容。没必要单纯的将你的CDN限制为静态。反复检查CDN是否执行了内容的压缩和转化,检查智能HTTP/2传输和缓存服务器(ESI),注意哪些静态或动态的部分处在CDN的边缘(最接近用户的服务器)。
首先应该弄清楚你想解决的问题是什么。检查一遍你所有的文件(JavaScript,图片,字体,第三方script文件以及页面中重要的模块,例如轮播,复杂信息图标和多媒体内容),并将他们分类。
列一个表格。明确浏览器上应该有的基础核心内容,哪些部分属于为高性能浏览器设计的升级体验,哪些是附加内容(那些不必要或者可以被延时加载的部分,例如字体,不必要的样式,轮播组件,播放器,社交网站入口,很大的图片)。更详细的细节请参考文章 ”Improving Smashing Magazine’s Performance‘’ 。
使用 符合标准的技术 向过时的浏览器提供核心体验,向老式浏览器提供增强体验, 同时对所加载的内容要有严格的把控。即首要加载核心体验部分,将增强部分放在 DomContentLoaded
,把额外内容发在 load
事件中。
以前我们可以通过浏览器的版本推断出设备的性能,但现在我们已经无法推测了。因为现在市场上很多廉价的安卓手机都不考虑内存限制和CPU性能,直接使用高版本的Chrome浏览器。一定要注意,在我们没有其他选择的时候,我们选择的技术同时可能成为我们的限制。
在一些应用中,可以在渲染页面前先初始化应用。最好先 显示框架 ,而不是一个进度条或指示器。使用可以加速初始渲染时间的模块或技术(例如 tree-shaking 和 code-splitting ),因为大部分性能问题来自于应用引导程序的初始分析时间。还可以在服务器上 提前编译 ,从而减轻部分 客户端的渲染过程 ,从而快速输出结果。最后,考虑使用 Optimize.js 来加快初始加载速度,它的原理是包装优先级高的调用函数(虽然现在已经没什么必要了)。
渐进启动指的是使用服务器端渲染,从而快速得到首次有效渲染,这个渲染过程也包括小部分的JavaScript文件,目的是使交互时间尽可能的接近首次有效渲染时间。
到底采用客户端渲染还是服务器端渲染?不论哪种做法,我们的目标都是建立 渐进启动 :使用服务器端渲染可以得到很短的首次有效渲染时间,这个渲染过程也包括小部分的JavaScript文件,目的是使交互时间尽可能的接近首次有效渲染时间。接下来,尽可能的增加一些应用的非必要功能。不幸的是,正如 Paul Lewis所说 ,框架基本上对开发者是没有优先级的概念的,因此渐进启动在很多库和框架上是很难实施的。如果你有时间的话,还是考虑使用策略去优化你的性能吧。
仔细检查一下例如 expires
, cache-control
, max-age
以及其他HTTP缓存头是否被正确的使用。一般来说,资源不论在短时间(如果它会被频繁改动)还是不确定的时间内(如果它是静态的)都是可缓存的——你大可在需要的时候在URL中成改版本。
如果可能,使用为指纹静态资源设计的Cache-control:immutable,从而避免二次验证(2016年12月,只有 FireFox在 https://
处理中支持 )。你可以使用,Heroku的primer on HTTP caching headers,Jake Archibald的 ”Caching Best Practices” ,还有IIya Grigorik的 HTTP caching primer 作为指导。
当用户请求页面时,浏览器会抓取HTML同时生成DOM,然后抓取CSS并建立CSS对象模型,最后通过匹配DOM和CSS对象生成渲染树。在需要处理的JavaScript文件被解决之前,浏览器不会开始对页面进行渲染。作为开发者,我们要明确的告诉浏览器不要等待,直接开始渲染。具体方法是使用HTML中的 defer
和 async
两个属性。
事实上, defer
更好一些(因为对于IE9及以下用户 对于IE9及以下用户 ,很有可能会中断脚本)。同时,减少第三方库和脚本的使用,尤其是社交网站的分享按键和 <iframe>
嵌入(比如地图)。你可以使用 静态的社交网站分享按键 (例如 SSBG 的)和 指向交互地图的静态链接 去代替他们。
尽可能的使用带有 srcset
, sizes
还有 <picture>
元素的 响应式图片 。你也可以利用 <picture>
元素的 WebP格式 ,用JPEG格式作为替补(参见Andreas Bovens的 code snippet )或是使用内容协商(使用接受头)。Sketch原本就支持WebP,WebP图片可以直接 被Photoshop的WebP plugin导出 。当然也有很多 其他方法 。
响应图片断点生成器 可自动处理图片
你也可以使用 客户端提示 ,现在 浏览器也可以做到 。在用来生成响应图片的源文件过少时,使用响应图片断点生成器或类似 Cloudinary 的服务自动的优化图片。在很多案例中,单独使用 sreset
和 sizes
都带来了很大的收益。在本网站上,我们给文件添加 -opt
后缀——例如 brotli-compression-opt.png
;这样团队的每一个人就知道这些带着后最的图片是被优化过的。
当你在编写登陆界面的时候,发现页面上的图片加载的特别快,这时你需要确认一下JPEG格式文件是否已经通过 mozJPEG (它可以操作扫描等级从而提高渲染时间)优化和压缩,PNG格式对应 Pingo ,GIF需要用到 Lossy GIF ,SVG要使用 SVGOMG 。对图片不重要的部分进行模糊处理(使用高斯模糊过滤器处理他们),从而减少文件大小,最后你可能还要去彩色化使图片变成黑白,从而减少更多的容量。对于背景图片,使用Photoshop保持0到10%的质量输出是绝对可以接受的。
如果你还觉得不够,那你可以通过 多重背景图片技术 来提高图片的感知性能。
你用来修饰网页字体的服务很有可能毫无用处,包括字形和额外的特性。如果你在使用开源的字体,尝试用字体库中某一个小的子集或是 自己归类 一个小的子集从而压缩文件大小(例如通过一些特殊的注音符号引用Latin)。 WOFF2 support 是个非常不错的选择,如果浏览器不支持,那你可以将WOFF和OTF作为备用。你也可以从Zach Leatherman的 “Comprehensive Guide to Font-Loading Strategies” 一文中选择一个合适的策略,然后使用服务器来缓存字体。如果想要快速入门,Pixel Ambacht的 教程与案例 会让你的字体变得尽然有序。
Zach Leatherman的“Comprehensive Guide to Font-Loading Strategies”提供了一打可以让字体传输变得更好的选项
如果你用的是第三方服务器主机,没办法自己在服务器上对字体进行操作,一定看看 Web Font Loader 。 FOUT is better than FOIT 中提到,在备选情况下立即渲染文本,并且异步加载字体——你也可以使用 loadCSS 实现这个。你可能也会 避免本地OS上安装字体 。
为了确保浏览器尽可能快的渲染你的页面,先收集页面首次可见部分的CSS文件(也叫决定性CSS或上半版CSS)进行渲染,然后将它加入页面的部分,从而避免重复操作。因为慢启动阶段对交换包大小的限制,你 关键CSS文件 的大小也被限制在14KB左右。如果高于这个值,浏览器需要重复一些步骤来获取更多的样式。关键CSS是允许你这样做的。可能对每个模板都需要这个操作。如果可能,考虑一下用Fiament Group用的 条件内敛方法 。
通过HTTP/2,关键CSS可以单独存为CSS文件,通过服务器传输,而且可以避免HTML膨胀。服务器传输缺乏连续支持,并且存在一些超高速缓存的问题( Hooman Beheshti演示 的前144页)。事实上,这样会导致网络缓冲区膨胀。因为TCP的慢启动,服务器传输在 稳定的连接下会更有效率 。所以你可能需要建立 带有缓存的HTTP/2服务器传输机制 。但请记住,新的 cache-digest
规则 会否定手动建立的需要缓存的服务器的请求。
Tree-shaking是通过保留那些在项目过程中真正需要的代码从而清理你的构建过程的一种方式。你可以用 Webpack 2 来提出那些没用的住配置文件,用 UnCSS 或 Helium 从CSS中取出不需要的样式。同理,也可以考虑学习一下如何编写 高效的CSS选择器 ,以及如何 避免膨胀和高费的样式 。
Code-splitting 是另一个Webpack特性,它可以根据按需加载的块将你的代码分开。只要你在代码中定义了分离点,Webpack便会处理好相关的输出文件。它基本上能保证你初始下载的内容很小,而且在需求被添加时按需请求代码。
Rollup 所展示的结果要比Browserify配置文件所显示的好得多。所以当我们想使用类似工具的时候,或许应该看看 Rollupify ,它将ECMAScript2015模块变成了一个更大的CommonJS模块——因为小模块没准有出乎意料的 高性能成本 ,这源自于你对打包工具模块系统的选择。
使用类似 CSS containment 的方法对高消耗组建进行隔离,从而限制浏览器样式的范围,可以作用在为无canvas的浏览工作的布局和装饰工作中,或是用在第三方工具上。要确保页面滚动和出现动画效果时没有延迟,别忘了之前提到过的每秒60帧的原则。如果没办法做到,那就尽可能保证每秒帧数的大致范围在15到60帧。使用CSS中的will-change通知浏览器哪些元素和属性发生了变化。
也记得要衡量 渲染执行中的性能 (可以用 DevTools )。可以参照Udacity上Paul Lewis的免费课程—— 浏览器渲染优化 ,作为入门。还有一篇Sergey Chikuyonok的文章讲了 如何正确的用GPU动画 。
使用页面框架,对高消耗组建延迟加载(字体,JS文件,循环播放,视频和内嵌框架)。使用 资源提示 来节省在 dns-prefetch
(指的是在后台执行DNS检索), preconnect
(指要求浏览器在后台进行握手链接(DNS,TCP,TLS)), prerender
(指要求浏览器在后台对特定页面进行渲染), preload
(指的是提前取出暂不执行的源文件)。根据你浏览器的支持情况,尽量使用 preconnect
来代替 dns-prefetch
,而且在使用 prefetch
和 prerender
要特别小心——后者( prerender
)只有在你非常确信用户下一步操作的情况下再去使用(比如购买流程中)。
Google开始向着 更安全网页 的方向努力,并且将所有Chrome上的HTTP网页定义为“不安全”时,你或许应该考虑是继续使用HTTP/1.1,还是将目光转向 HTTP/2环境 。虽然初期投入比较大,但是使用HTTP/是大趋势,而且在熟练掌握之后,你可以使用service worker和服务器推送技术让行 性能再提升 一大截。
现在,Google计划把所有HTTP页面标记为不安全,并且将HTTP安全指示器设置为与Chrome用来拦截HTTPS的红色三角相同的图标。
使用HTTP/2的环境的缺点在于你要转移到HTTPS上,并且根据你HTTP/1.1用户的数量(主要指使用过时操作系统和过时浏览器的用户),你需要适应 不同的建构过程 ,才能发送不同的建构。注意:不论是迁移还是新的构建过程都可能非常棘手而且耗时很多。
重申,使用 HTTP/2协议之前 ,你需要彻底排查目前为止你所使用协议的情况。你需要在打包组建和同时加载很多小组间之间找到平衡。
一方面,你可能想要避免将很多资源链式链接,与其将你全部的界面分割成许多小模块,不如将他们压缩使之成为建构过程的一部分,之后给它们赋予可检索的信息并加载它们。这样的话,对一个文件将不再需要重新下载整个样式清单或JavaScript文件。
另一方面, 封装 是很有必要的,因为一次向浏览器发送太多JavaScript文件会出问题。首先, 压缩会造成损坏 。得益于dictionary reuse,压缩大文件不会对文件造成损害,压缩小文件则不然。确实有方法可以解决这个问题,但这不是本文讨论的范畴。其次,浏览器还 没有优化到 可以对类似工作流进行优化。例如,Chrome会引发 进程间通信 (IPCs),这些通信的数量与资源的数量成正比,而这成百上千个资源将会消耗大量的浏览器的执行时间。
Chrome的Jake Archibald建议,为了用HTTP/2达到最好的效果,考虑一下逐步加载CSS文件
当然你可以考虑 逐步加载CSS文件 。很显然,你这样做对HTTP/1.1的用户非常不利,所以你可能需要根据不同的浏览器建立多个版本来应对你的调度过程,这样就会使过程略微复杂。你也可以避免 HTTP/2连接的合并 ,同时受益于HTTP/2来使用域名碎片,但是实现起来有些困难。
我们到底应该做什么呢?如果你粗略的用过HTTP/2,似乎成功的发送过10个左右的包(在老是浏览器上运行的也不错)。那你就能着手开始试验并且为你的网站找到平衡点。
所有的浏览器都支持HTTP/2并且使用TLS,这是有你可能想要避免安全警告,并删除页面上没用的元素。好好检查你的 安全头部是否设置正确 , 排除已知的缺陷 并 检查证书 。
如果还没有迁移到HTTP, 你那可以先看看 HTTPS准则 (The HTTPS-Only Standard)。确保所有外部插件和监视脚本都能被HTTPS正确加载,确保没有跨站脚本出现, HTTP脚本传输的安全头 和 内容安全头 也都设置正确。
不同服务器和CDN对HTTP/2的兼容性不同,你可以使用 TLS够快吗? 一文来查看你有什么选择。
Is TLS Fast Yet?让你能看看你的服务器和CDN在使用HTTP/2的时候你能使用的工具
2015年,Google介绍了 Brotli ,一个新的开源无损数据格式,它已经被Chrome,Firefox和Opera很好的 兼容 了。具体使用时,Brotli所显示出的 效率要远高于 Gzip和Deflate。它根据不同的配置可能压缩的时候会比较慢,但是压缩速度慢最后会让压缩效率提高。而且解压起来非常快。因为这个算法来自Google,所以浏览器只在用户通过HTTPS访问网页的时候使用它,这个事情就不奇怪了。Brotli的隐患是它没办法在目前大部分服务器上预设,而且如果没有NGINX或者Ubuntu,部署起来还是有难度的。但其实你是 可以在不支持它的CDN上使用Brotli (通过service worker)。
你可以看看 Zopfli压缩算法 作为备选,它将数据编码为Deflate,Gzip和Zlib格式。任何规范的Gzip压缩资源都受益于Zopfli改进了Deflate编码,因为文件会比Zlib压缩的最大文件小3%-8%。问题在于文件会消耗大概80倍的时间去压缩。这就是为什么在不怎么会变得资源上使用Zopfli是不错的选择,这样的文件一般都压缩一次,下载多次。
让服务器使用 OCSP装订 ,可以提升你TLS握手的速度。线证书状态协议(OCSP)是作为证书废置列表协议的代替品被创造出来的。两个协议都可以用来检测SSL证书是否被取消。然而,OCSP不需要浏览器花时间下载和扫描证书信息的列表,所以它可以减少握手时间。
因为我们已经 没什么IPv4的地址可用 了,而且移动网络大都开始使用IPv6( 美国已经有50%的入口采用IPv6 ),将你的DNS升级到IPv6为以后作打算是个不错的选择。要确保通网络可以支持双栈协议——它需要允许IPv6和IPv4同时运行。毕竟IPv6不只是做为后备计划的。而且 研究显示 ,伴随邻居发现(NDP)和路由优化,使用IPv6的网站要比普通网站快10%到15%。
如果你在使用HTTP/2,看看你的服务器有没有执行 HPACK 对HTTP的响应头进行压缩,来减少不必要的消耗。因为HTTP/2服务器相对较新,所以有些像HPACK这样的规格目前还没有被支持。我们可以用 H2spec 来检查 HPACK是否在工作 。
H2spec的截图
没有经过优化的网络可以比用户机器的本地缓存跑得更快。如果你的网站在HTTPS上运行,你可以参考 “实用主义者的service workers手册” ,然后把静态资源存在service worker的缓存中,把离线预设(甚至离线页面)存在用户机器方便检索,这样比多次进行网络连接更有效。你还可以参考Jake的 离线使用手册 和免费的Udactiy课程 “离线网络应用” 。如果浏览器支持,那就再好不过了,预设就能在任何地方代替网络了。
如果你近期完成了HTTP到HTTPS的迁移,你可以利用类似 Report-URI.io 一类的对主动和被动的混合内容警告都进行监听。也可以利用 混合内容扫描器 来对你使用HTTPS的网页进行扫描。
选一个调试工具来对每一个按钮进行检查。确保自己明白如何分析渲染性能和控制台输出、明白如何调试JavaScript以及编辑CSS样式。Umar Hansa最近有一个关于使用DevTools调试和测试的分享,主要包括一些不常用的技巧和技术。
仅仅使用Chrome和Firefox测试是不够的。还应该看看你的网页在代理浏览器和过时浏览器上运行的怎么样。比如UC浏览器和Opera Min, 它们在 亚洲市场的份额 很高(高达35%)。在推广时,利用目标客户所在国家的 平均网速 来进行测试,避免日后出现大的误差。同样的,不仅要在节流网络以及模拟的高数据处理设备上进行测试,还要在真实设备上测试。
在进行快速、无限制的测试时,最好使用一个个人的 WebPageTest 实例。建立一个能自动预警的性能预算监听。建立自己的用户时间标记从而测量并监测具体商用的数据。使用 SpeedCurve 对性能的变化进行监控,同时利用 New Relic 获取WebPageTest没法提供的数据。 SpeedTracker , Lighthouse 和 Calibre 都是不错的选择。
这份清单综合性很强,几乎介绍了所有的可用的优化方式。那么,如果你只有一个小时进行优化,你应该干什么呢?让我们从中总结 10个最有用的 来。别忘了在你开始优化前和结束优化后,记录你的结果,包括开始渲染时间以及在3G,有限连接下的速度。
<head>
中(你可以使用14KB)。 dns-lookup
, preconnect
, prefetch
, preload
和 prerender
添加资源提示,从而加快传输速度。 文中提到的一些优化可能超出了你工作的范围,有的可能超出了你的预算,有的甚至对你正在使用的有些过时的代码判了死刑。但没关系,本文只是一个普通大纲(希望能做到综合性强),你应该根据自己的工作环境列一份适合自己的清单。最重要的,在开始优化之前,先对项目中存在的问题有一个明确的了解。最后,祝大家2017年优化顺利!
----------------------------------我们需要的小伙伴------------------------------------
工作职责:
-Web前端的功能设计、开发和优化,开发可重用模块
-实现与视觉稿、交互稿一致的跨平台、浏览器、客户端,兼容性好的移动端页面和PC页面
-前沿技术研究和新技术调研,
职位要求:
-精通JavaScript/HTML5/CSS3等相关前端开发技术,熟悉页面架构和布局,有良好的程序设计和架构能力;
-精通vue或react; 熟悉并熟练使用es6语法,熟悉node.js;
-掌握前端调试、性能优化、工程化等开发等相关技术;
-具有至少一年以上移动端网页开发经验;
-对web技术钻研有强烈兴趣,有良好的学习能力和强烈的进取心,能主动跟进新技术发展动态优先 ;
-学习能力强,强烈的责任心,具有较强的沟通能力及团队合作精神 ;
-有较强的产品理解,能从技术角度推动产品优化;
-思维缜密、思路清晰,较好的逻辑分析能力;
-了解一门后台语言(php或java)者优先;
有意向的同学,请发送简历到 xuheng@baidu.com :)