前端资源动态渲染模式介绍之概览篇

在手百我们使用了一种动态管理静态资源的方式,在开发中通常打包工具在打包构建的时候根据页面依赖将所有的js或者css打成一个app.js或者app.css,这样的打包方式我们称之为「静态打包」,因为只能在项目发布构建的过程中一次性将页面用到的js或者css打包成一个文件,上完线之后就不能在拆分。

这种「静态打包」的方式有个弊端:如果在多个view的页面,是不能够充分利用不同页面之间的公用代码(模块)。于是加强版就是在线统计一个网站(项目)模块依赖和公用的代码,然后设置一个阈值,利用统计的数据,分析出多个页面高频使用的公共代码,再下次上线的时候,将这部分代码打包在一起。这种方式百度内部也有类似的解决方案,但是这种方案也没有充分发挥出细粒度模块的作用,而且实现相对来说比较麻烦,需要长期数据统计支持。

今天我介绍下手百中我们实现的一种动态管理静态资源的方式,我将它称之为「前端资源动态渲染模式」,简称「渲染模式」。这种方式是基于手百现有业务出发的,解决了手百不同平台(安卓、ios、winphone)的代码差异,而且充分利用缓存、combo服务,做到可配方便调试的目的。

前端资源动态渲染模式特点

代码永远只写一份,不需要编写特殊逻辑

我们实现的渲染模式,对于代码开发者来说,不需要做特殊的逻辑编写,只需要按照正常编码要求来写代码,剩下的就交给打包工具和上线流程,对于初学者不需要任何的学习门槛,而且支持本地静态资源和外部静态资源混用。

能够根据不同平台,不同后端业务逻辑,动态打包不同代码

后端业务逻辑不通,则需要的js或者css文件不通,之前的做法是一个js里面包含了所有的代码逻辑,现在只需要如下代码:

{% if($isiOS) %}
    {%require name="life:ios/invoke.js"%}
{%else%}
    {%require name="life:android/invoke.js"%}
{% endif%}

这个是动态逻辑解析后的执行,所以编译阶段的静态打包是完全解决不了这个问题的。

结合combo服务或者localstorage做缓存优化

利用静态资源的combo服务和浏览器的localstorage存储,我们可以把渲染模式进一步优化,最简单的方式是combo渲染模式,动态分析完页面依赖之后,将url拼接成combo url一次输出

多种渲染模式,可以适用不同的应用业务场景

在不同的业务场景下,需要的代码组织形式不同,比如2G下,应该尽量少的http请求,这时候需要inline模式,将js和css分别放在<script><style> 标签内,而我们写代码不需要这样写,还是使用正常的{%require %} 语法

可结合用户设备特征,自动智能选择不同的渲染模式

对于不同的用户、设备和网络环境,能够自动识别出来最适合的渲染模式,例如对于2G用户,推荐使用http请求少的inline模式,对于3G、4G用户能够使用combo模式,对于支持localstorage的用户使用seed模式,这些修改只需要在父模板设置渲染模式即可:

{%if $network==='slow'%}
    {%html rendermode='inline'%}
{%elseif $isSuportLS%}
    {%html rendermode='seed'%}
{%else%}
    {%html rendermode='combo'%}
{%endif%}

技术要点

下面列下大概的技术要点:

  1. 利用项目发布阶段生成的静态资源依赖管理表,fis对应的是map.json,里面有每个静态资源的信息,可以利用打包工具,对这个表进行扩展,增加想要的信息,比如release之后的cdn url,发布上线后到路径,文件的MD5值
  2. 利用smarty扩展(本质是php的某个函数),将页面需要的静态资源收集起来
  3. 页面html输出的时候,需要将需要根据不同渲染模式,读取map.json内静态资源配置,比如combo需要读取去掉combo url的cdn url,拼接最终的url;tag模式需要单个的cdn url;seed需要读取MD5值;inline需要知道线上部署的路径,可以读取出来文件内容塞到<script><style>标签内

小结

本篇文章主要从总体对动态渲染模式做了介绍,基于smarty的语言扩展实现的动态解析依赖关系,充分利用网络环境、用户设备特性和server服务实现最优的性能优化和静态资源代码管理方式。如果是其他动态语言,可以参考本文的思想进行改造实验。接下来两篇文章重点介绍现在手百使用的两种渲染模式:combo和seed。

扩展阅读