MidProxy开发之活动页面

为什么使用MidProxy

当前活动页面有特定的后端模板,而且后台系统中也有录入代码的入口,发布比较方便。但是这样却存在几个问题,

首先受制于模板限制,活动页面的前端可定制型几乎没有:由于模板在后端渲染,因此一旦活动页面的布局或者设计风格改变,前端开发人员的操作就不仅仅是在后台系统中粘贴代码并发布这么简单了;

其次,活动页面本质上是一个一次性消费的业务,对用户的体验要求比较高。目前的活动页面机制是“后端构建页面,前端异步渲染”,这样最直接的影响就是渲染时间不受控制,而且相对时间较长。在当前的活动页面加载过程中,前端通过jsonp异步加载两个接口(图片banner和列表数据),这两个接口的返回有时间差,给用户的体验就是首屏的闪烁。针对这样的优化,目前的活动页面开发规范无法解决。采用MidProxy则可由前端进行优化,选择首屏渲染的部分:如在首屏预先渲染好图片banner和10条列表数据,其余数据懒加载即可。

最后的最后,就是SEO。作为一个前端工程师,自然针对代码有某种特殊的偏执,可是打开我们活动页面的源码看看,我相信这足够成为前端开发界的反面教材:重复的body和html标签、乱嵌套的div、style和script标签随意插入...

如此种种,急需要针对活动页面进行分离,而且之所以率先分离活动页面,是由于其耦合度小,关联度低以及流量突发性强的特点非常适合目前的MidProxy架构。

MidProxy开发套件

MidProxy开发套件数据spon的插件,因此需要在安装spon的前提下使用。

如何安装spon,请看:http://docs.showjoy.net/2016/07/08/spon-info/

如何安装MidProxy开发套件,请看:http://docs.showjoy.net/2017/01/17/midproxykai-fa-gong-ju-spon-midproxy/

如何开发活动页面

活动页面开发仍然遵循Extends应用的规范,不过针对活动页面特有的首屏优化会有一些特殊的配置项,下面先从最简单的前端异步渲染说起:

异步渲染的活动页面

  • 模板
  • 路由
  • 缓存

由于前端异步渲染无需MidProxy代理请求,因此针对该情况无需配置接口。

模板

activity.tmpl模板

<link href="http://cdn1.showjoy.com/assets/f2e/activity/act-tmpl/0.0.3/tmpl-m/tmpl-m.min.css" rel="stylesheet" />  
        <div id="content">

                <a href="http://chat10.live800.com/live800/chatClient/chatbox.jsp?companyID=439479&configID=223765&jid=1490817627&enterurl">
                    <div class="chat-box"></div>
                </a>
                <a href="#"><div class="totop j_Top"></div></a>

                <div class="banner j_Banner">
                    <img src="{{banner}}" />
                </div>

                <div class="data-list j_Goods">
                    <ul>
                            {{each list as item}}
                            <li class="goods">
                                <a href="http://item.showjoy.com/sku/{{item.id}}.html">
                                    <div class="product">
                                        <div class="pro-pic">
                                            {{if item.inventory == 0}}
                                            <div class="sold-out"></div>
                                            {{/if}}
                                            <div class="del-tag"><span class="tag j_Tag">{{item.discount}}</span><span class="word">折</span></div>
                                            <img class=""  src="{{item.image}}.400x400.png"/>
                                        </div>
                                        <div class="pro-info">
                                            <div class="pro-name">{{item.Copywriter}}</div>
                                            <div class="pro-des">{{item.name}}</div>
                                            <div class="price-info">
                                                <div class="price"><div class="rmb">¥</div>{{item. price}}</div>
                                                <div class="original-price">市场价:¥{{item.originalPrice}}</div>
                                            </div>
                                        </div>
                                    </div>
                                </a>
                            </li>
                            {{/each}}
                        </ul>
                </div>

            </div>

                <script id="goods" type="text/html">
                    <ul>
                        <<each data as item>>
                        <li class="goods">
                            <a href="http://item.showjoy.com/sku/<<item.id>>.html">
                                <div class="product">
                                    <div class="pro-pic">
                                        <<if item.inventory == 0>>
                                        <div class="sold-out"></div>
                                        <</if>>
                                        <div class="del-tag"><span class="tag j_Tag"><<item.discount>></span><span class="word">折</span></div>
                                        <img class="lazyload j_Lazyload" data-original="<<item.image>>.400x400.png" src="http://cdn1.showjoy.com/images/46/465ff4a3a0ca4a1eb0797177f463e0fb.png"/>
                                    </div>
                                    <div class="pro-info">
                                        <div class="pro-name"><<item.Copywriter>></div>
                                        <div class="pro-des"><<item.name>></div>
                                        <div class="price-info">
                                            <div class="price"><div class="rmb">¥</div><<item. price>></div>
                                            <div class="original-price">市场价:¥<<item.originalPrice>></div>
                                        </div>
                                    </div>
                                </div>
                            </a>
                        </li>
                        <</each>>
                    </ul>
                </script>
    </div>
<script src="http://cdn1.showjoy.com/assets/f2e/activity/act-tmpl/0.0.3/tmpl-m/tmpl-m.min.js"></script>  
    <script>
      $(function(){
        var shareData = {
          title: '初冬全新LOOK 从彩妆开始',
          desc: '初冬全新LOOK 从彩妆开始',
          link: 'http://market.m.showjoy.com/activity/ctopic/47942.html',
          imgUrl: 'http://cdn1.showjoy.com/images/e5/e5031fcace7243cfa3d82caace6bc3df.jpg'
        };
        $.JSBridge.registerHandler('wxShareInfo',function(){
          return shareData;
        });
        wx.ready(function() {
          wx.showOptionMenu();
          var shareData = {
            title: '初冬全新LOOK 从彩妆开始',
            desc: '初冬全新LOOK 从彩妆开始',
            link: 'http://market.m.showjoy.com/activity/ctopic/47942.html',
            imgUrl: 'http://cdn1.showjoy.com/images/e5/e5031fcace7243cfa3d82caace6bc3df.jpg'
          };
          wx.onMenuShareTimeline(shareData);
          wx.onMenuShareAppMessage(shareData);
        });
      })

    </script>

需要注意的是,由于MidProxy使用art-template模板渲染页面,因此为了避免前后端模板占位符的重复,设定前端的模板占位符为"<<、>>"。

缓存

package.json

{
  "type": "MidProxy",
  "name": "xxx",
  "info": "活动页面",
  "views": [],
  "cache": [
    {
      "k": "f2e:activity:56892coyg",
      "v": "56892coyg",
      "dirname": "mobile"
    }
  ],
"hotload": 1
}
路由
Extends.use('/activity/ctopic/56892coyg.html',{  
    page: {
      type: 'activity-shop',
      cacheKeys: ['f2e:activity:thxgiving'],
      title: '感恩节'
    },
    method: 'get'
  });

活动页面有两种类型:

  • activity-shop 达人店活动页
  • activity-showjoy 尚妆活动页

在示例中我们创建的是达人店活动页;

同时配置了cacheKeys数组,即模板缓存的key值;

最后,设置页面的title。

这样最简单的异步渲染的活动页面完成了。

不过,这样全部异步化渲染的方式用户体验不好,因此MidProxy提供了首页渲染优化机制。

Extends.use('/activity/ctopic/47935coyg.html',{  
    page: {
      type: 'activity-shop',
      cacheKeys: ['f2e:activity:47935coyg'],
      templateType: 1,
      firstPageOptimize: true,
      title: '懒人护肤术'
    },
    method: 'get',
    createProxies: function(){

      var proxy = MidProxy.create('a47935.*');
      // 准备MidProxy即将调用的接口,此处并未发起请求
      proxy
        // getConfig的参数为get请求的查询字符串,默认使用真是请求的查询字符串
        // 由于服务端采用OAuth2认证,请求须携带cookie
        .getBanner({
          moduleName: 'TOUTU',
          pageSize: 100,
          callback: 'jsonp2'
        })
        .getList({
          moduleName: 'BLOCKPRODUCT',
          pageSize: 100,
          callback: 'jsonp1'
        });

      // 返回值必须为为数组
      return [proxy];
    },
    handleRenderData: function(ret,app){
      var banner = ret[0][0],list = ret[0][1];
      banner = banner.replace('jsonp2(','').replace(')','');
      list = list.replace('jsonp1(','').replace(')','');
      return {
        banner: JSON.parse(banner)['TOUTU'][0]['banner'],
        list: JSON.parse(list)['BLOCKPRODUCT'].slice(0,4)
      };
    },
    isSetCookie: false
  });

其中,page参数多了两个属性:

  • templateType
  • firstPageOptimize

templateType为使用的模板类型,目前MidProxy只提供一种活动模板,默认是1
firstPageOptimize,即首屏优化。当设置为true时,必须提供 createProxies和handleRenderData两个处理函数(这两个函数的作用在MidProxy入门中已介绍)

开启首屏优化后,模板就需要相应的改动了:

开启首屏优化后的模板:

<link href="http://cdn1.showjoy.com/assets/f2e/activity/act-tmpl/0.0.3/tmpl-m/tmpl-m.min.css" rel="stylesheet" />  
        <div id="content">

                <a href="http://chat10.live800.com/live800/chatClient/chatbox.jsp?companyID=439479&configID=223765&jid=1490817627&enterurl">
                    <div class="chat-box"></div>
                </a>
                <a href="#"><div class="totop j_Top"></div></a>

                <div class="banner j_Banner">
                    <img src="{{banner}}" />
                </div>

                <div class="data-list j_Goods">
                    <ul>
                            {{each list as item}}
                            <li class="goods">
                                <a href="http://item.showjoy.com/sku/{{item.id}}.html">
                                    <div class="product">
                                        <div class="pro-pic">
                                            {{if item.inventory == 0}}
                                            <div class="sold-out"></div>
                                            {{/if}}
                                            <div class="del-tag"><span class="tag j_Tag">{{item.discount}}</span><span class="word">折</span></div>
                                            <img class=""  src="{{item.image}}.400x400.png"/>
                                        </div>
                                        <div class="pro-info">
                                            <div class="pro-name">{{item.Copywriter}}</div>
                                            <div class="pro-des">{{item.name}}</div>
                                            <div class="price-info">
                                                <div class="price"><div class="rmb">¥</div>{{item. price}}</div>
                                                <div class="original-price">市场价:¥{{item.originalPrice}}</div>
                                            </div>
                                        </div>
                                    </div>
                                </a>
                            </li>
                            {{/each}}
                        </ul>
                </div>

            </div>

                <script id="goods" type="text/html">
                    <ul>
                        <<each data as item>>
                        <li class="goods">
                            <a href="http://item.showjoy.com/sku/<<item.id>>.html">
                                <div class="product">
                                    <div class="pro-pic">
                                        <<if item.inventory == 0>>
                                        <div class="sold-out"></div>
                                        <</if>>
                                        <div class="del-tag"><span class="tag j_Tag"><<item.discount>></span><span class="word">折</span></div>
                                        <img class="lazyload j_Lazyload" data-original="<<item.image>>.400x400.png" src="http://cdn1.showjoy.com/images/46/465ff4a3a0ca4a1eb0797177f463e0fb.png"/>
                                    </div>
                                    <div class="pro-info">
                                        <div class="pro-name"><<item.Copywriter>></div>
                                        <div class="pro-des"><<item.name>></div>
                                        <div class="price-info">
                                            <div class="price"><div class="rmb">¥</div><<item. price>></div>
                                            <div class="original-price">市场价:¥<<item.originalPrice>></div>
                                        </div>
                                    </div>
                                </div>
                            </a>
                        </li>
                        <</each>>
                    </ul>
                </script>
    </div>
<script src="http://cdn1.showjoy.com/assets/f2e/activity/act-tmpl/0.0.3/tmpl-m/tmpl-m.min.js"></script>  
    <script>
      $(function(){
        var shareData = {
          title: '初冬全新LOOK 从彩妆开始',
          desc: '初冬全新LOOK 从彩妆开始',
          link: 'http://market.m.showjoy.com/activity/ctopic/47942.html',
          imgUrl: 'http://cdn1.showjoy.com/images/e5/e5031fcace7243cfa3d82caace6bc3df.jpg'
        };
        $.JSBridge.registerHandler('wxShareInfo',function(){
          return shareData;
        });
        wx.ready(function() {
          wx.showOptionMenu();
          var shareData = {
            title: '初冬全新LOOK 从彩妆开始',
            desc: '初冬全新LOOK 从彩妆开始',
            link: 'http://market.m.showjoy.com/activity/ctopic/47942.html',
            imgUrl: 'http://cdn1.showjoy.com/images/e5/e5031fcace7243cfa3d82caace6bc3df.jpg'
          };
          wx.onMenuShareTimeline(shareData);
          wx.onMenuShareAppMessage(shareData);
        });
      })

    </script>

区别在于首屏的数据(本例中4条列表数据)在MidProxy端渲染,其他列表数据则异步+图片懒加载。由于MidProxy和前端都是用art-template作为模板,因此针对前端的模板使用<<、>>作为占位符。

欲休

继续阅读此作者的更多文章

海创园尚妆