Introduction to Scorpio system
Background introduction
- Baidu mobile is a hybrid app
- In the development stage, rapid development iteration, parallel development of mainline version
- Minutiae access party multi operation activity demand CMS demand
- Access party
- Operational activity requirements
- CMS demand
Mature teams should not stay in the stage of showing off skills and following the trend
problem
- High cost of Fe development, joint debugging and code deployment
- There are too many repetitions, which is not good for team and personal development
- One size fits all solution too many static resources embedded localstorage storage solutions
- Static resource infill
- Localstorage storage scheme
- JS library without own product
- Too many pages for unified management
Based on the current situation, lay out the future
There are too many SVN modules. To make a unified front-end solution, the public code can only be maintained separately through the SVN: externals attribute
Front end common SVN
Detach the front common from the SVN of template
common
├─demo # demo示例目录,不上线
├─docs # 文档目录,jsdoc生成,svn忽略
├─plugin # smarty插件和解决方案
├─static # 静态资源
│ ├─bdbox # js模块化库
│ ├─css
│ ├─img
│ └─js
├─test # 放fis的调试json文件,用于本地开发,不上线
│ └─page
│ └─xxx
├─widget # widget目录
└─nodejsLib # nodejs工具
The redundant code is separated, and the dependency between modules is clear, which is convenient for static resource management?
Thinking about using and not using the third party Library
- Whether team members can write native JS by themselves, and ensure quality and work efficiency
- Third party library selected, whether the community is active, and whether the team can cover bugs
- Expansibility, coupling degree between modules, pluggable modules
- Some modules need to be customized“
Zebto + customized amd library bdbox
- Zeptodom operations, events, AJAX (alone) remove less commonly used modules
- DOM operations, events, AJAX (separate)
- Remove infrequently used modules
- Bdbox mobile Baidu JS module library and zepto complement each other as the cornerstone of front-end static resource management
- Mobile Baidu JS module library
- Complementing zepto
- Be the cornerstone of front-end static resource management
Bdbox module library
18 categories, 50 + modules, covering all application scenarios of mobile Baidu
Management of modules
- Automatic package with fis-plus
- Generate static resource configuration file: common-map.json is different from fis-plus, including high-frequency source code
common-map.json
- Different from fis-plus, including high-frequency source code
- Transform the smart require / widget to support multiple calls of resources
- Support multiple resource calls
- Using JSDoc to produce bdbox documents
Module writing
/**
* 简单模板
* @memberOf Bdbox.utils
* @name template
* @param {String} html 模板String内容
* @param {Object} data 模板data对象
* @return {String} 返回处理后的模板
* @author wangyongqing01
* @version $Id: template.js 175996 2014-05-16 00:48:03Z wangyongqing01 $
* @example
* var t = Bdbox.utils.template('I am <%=name%>', {name:'Theo Wang'});
* // I am Theo Wang
* console.log(t);
*/
module.exports = function(html, data) {
for (var i in data) {
html = html.replace(new RegExp('<%=\\s*' + i + '\\s*%>', 'g'), data[i]);
}
return html;
};
The parent template is the solution, the child template focuses on business, and the parent-child inheritance relationship
Template splitting scheme
- Modify ODP router and template classes
- The parent template is divided by action and placed in TPL / layout
tpl/layout
- Sub templates are divided into specific pages and placed on TPL / page
tpl/page
- Contract the parent-child template path smart variable with PHP
{%extends file=$tplData.parentTplPath %}
{%block name="head"%}...{%/block%}
{%block name="body"%}...{%/block%}
{%html framework="common:bdbox" rendermode="inline|tag|combo"%}
Introduction to page rendering mode
- Inline means that all static resources are embedded in the page. The oldest one size fits all scheme, HTTP, has fewer requests and saves power
- That is, all static resources are embedded in the page, the oldest one size fits all solution
- Less HTTP requests, power saving
- Tag is to use the script and link tags, introduce the common way of JS and csspc in the outer chain, and use HTTP cache
- That is, using script and link tags to introduce JS and CSS of the outer chain
- Common ways of PC, using HTTP cache
- Combo combines multiple requests of the page into one to reduce HTTP requests. It can combine the advantages of CDN and HTTP cache
- Merge multiple requests from a page into one
- Reduce HTTP requests and combine the advantages of CDN and HTTP cache
Inline mode
Online environment, suitable for slow network
Tag mode
Offline environment, suitable for debugging
Combo mode
Online environment, suitable for 3G + network
Nginx combo service: box.bdimg.com
Intelligently switch rendering mode according to network speed
- The client knows the current network environment of the user, and the page public parameters contain this information
- Wise has IP speed measurement Library
<!DOCTYPE html>
{%if $network == 'fast' %}
{%html rendermode="combo"%}
{%else%}
{%html rendermode="inline" localstorage="true" lscookiepath="/xxx" %}
{%/if%}
{%head%}
.....
{%/head%}
....
Inline + localstorage storage
Solve the problem of slow network cache
Fine granularity / multi-dimensional, more storage, lower update frequency
Local storage and update scheme
- Fine grained code is layered according to the update frequency: basic, general and business business code updates will not distribute basic and general code
- Code is layered according to update frequency: basic, general and business
- Basic and general codes will not be distributed for business code update
- Using cookie to record version number to avoid second request
- Multi dimensional principle: cookies can be set according to the conditions of domain and path: different channels have different page paths, but the same effect of domain: access channel a, then access channel B, and the same code of channel B and channel a will not be distributed
- Principle: cookies can be set according to domain and path
- Condition: different channel pages have different path, but the domain is the same
- Effect: visit channel A and then channel B. the same code of channel B and channel a will not be distributed
- Package auto update version configuration files: localstorage.json and lsconfig.php
- Packing tool auto package version logic
localstorage.json
{
"jA": {
"hash": "2c79d70",
"files": [
"common:widget/localstorage/zepto-ajax.tpl"
],
"version": 1
},
"jZ": {
"hash": "5358395",
"files": [
"common:widget/localstorage/zepto.tpl"
],
"version": 1
}
}
Automatic generation of file version logic
<script data-lsid="jZ">
__inline('/static/js/zepto.js');
</script>
{%if ($_ls_nonsupport) || ($_parsedLSCookies.jZ.isUpdate ) %}
<script data-lsv="{%$_parsedLSCookies.jZ.version|escape:html%}" data-lsid="jZ">
var Zepto=xxx
</script>
{%else%}
<script>LS.exec("jZ","js");</script>
{%/if%}
Effectively avoid novice mistakes, free hands!
Cookie store version number effect
The version number is 36 base. If it exceeds 36, it starts from 1 to ensure that the length is always 1.
The expiration time of cookies is one week. There is no need to consider the overlapping of version numbers
Summary
- Intelligent selection of page rendering mode through client common parameters and wise speed IP library
- Use inline and localstorage for long network latency like 2G
- 3G + using CDN + combo rendering mode
- Tag rendering mode is used in the development to facilitate debugging
- Local storage fine-grained multi-dimensional and automated updates
When 4G becomes popular, as long as the slow judgment branch is removed, all can be replaced to the optimal scheme
JS template is compiled into bdbox module, which is convenient for management, cross domain pull and modular storage
Template selection: arttemplate
- Basically no conflict with smart syntax
- performance
- Expansion capability
- Compiler support
Template selection
Template compilation: before Compilation
{{include '../public/header'}}
<div id="main">
<h3>{{title}}</h3>
<ul>
{{each list}}
<li><a href="{{$value.url}}">{{$value.title}}</a></li>
{{/each}}
</ul>
</div>
{{include '../public/footer'}}
Template compilation: Bdbox module after compilation
define('baiduboxapp:tmpl/test/test2', function(require, exports, module, $) {
$.template('baiduboxapp:tmpl/test/test2', function($data, $filename) {
//忽略部分代码
include('../public/header');
$out += '\n\n<div id="main">\n <h3>';
$out += $escape(title);
$out += '</h3>\n <ul>\n ';
$each(list, function($value, $index) {
$out += '\n <li><a href="';
$out += $escape($value.url);
$out += '">';
$out += $escape($value.title);
$out += '</a></li>\n ';
});
$out += '\n </ul>\n</div>\n\n';
include('../public/footer');
$out += '\n';
return new String($out);
});
module.exports = function(id, data) {
var html = $.template("baiduboxapp:tmpl/test/test2", data);
$.byId(id).innerHTML = html;
}
});
After compilation: depends on auto generation
"baiduboxapp:tmpl/test/test2": {
"uri": "baiduboxapp/tmpl/test/test2.js",
"type": "js",
"deps": [
"baiduboxapp:tmpl/public/header",
"baiduboxapp:tmpl/public/footer"
]
}
{%require name="common:bdbox/template"%}
<div id="content"></div>
{%script%}
require('baiduboxapp:tmpl/test/test2');
var data = {
title:'加载模板演示',
time: +new Date(),
list: [...]
};
var html = Bdbox.template('baiduboxapp:tmpl/test/test2', data);
document.getElementById('content').innerHTML = html;
//or
Bdbox.tmpl.test.test2('content', data);
{%/script%}
Template output in rendering mode of rendermode = "tag"
JS template solution
- Compiling string template of JS into executable JS code fragment
- Compile to bdbox module
- Automatic maintenance of dependency
- Reduce JS template compilation time
- Can't see the existence of JS template!
After componentization, making pages is more like playing building block games
Componentized directory structure
# component 发现频道
discovery
├─header # 头部
│ header.css
│ header.js
│ header.tmpl
│
└─comment # 评论
comment.css
comment.js
comment.tmpl
Component-based
- A UI component consists of: tmpl, JS and CSS
- JS file is the core of component
- CSS / JS / tmpl dependency in components
Component example: discovery / foo
discovery/foo
Template foo.tmpl
{{include './public/header'}}
<div id="main">
<h3>{{title}}</h3>
<ul>
{{each list}}
<li><a href="{{$value.url}}">{{$value.title}}</a></li>
{{/each}}
</ul>
</div>
{{include './public/footer'}}
Component example: discovery / foo
discovery/foo
Interaction foo.js
function bindEvent(id){
$.byId(id).addEventListener(xxx);
//....
}
module.exports = function(id, data){
template(id, data);
bindEvent(id);
}
After compilation:
define('baiduboxapp:c_discovery/foo', function(require, exports, module, $){
var template=require("baiduboxapp:c_tmpl/discovery/foo");
function bindEvent(id){
$.byId(id).addEventListener(xxx);
}
module.exports = function(id, data){
template(id, data);
bindEvent(id);
}
});
Compile to generate dependency table
"baiduboxapp:c_css/discovery/foo": {
"uri": "baiduboxapp/components/css/discovery/foo.css",
},
"baiduboxapp:c_discovery/foo": {
"deps": [
"baiduboxapp:c_css/discovery/foo",
"baiduboxapp:c_tmpl/discovery/foo" ]
},
"baiduboxapp:c_tmpl/discovery/foo": {
"deps": [
"baiduboxapp:c_tmpl/discovery/public/header",
"baiduboxapp:c_tmpl/discovery/public/footer",
"baiduboxapp:c_css/discovery/foo" ]
},
"baiduboxapp:c_tmpl/discovery/public/footer": {
"deps": [ "baiduboxapp:c_tmpl/discovery/public/logo" ]
},
"baiduboxapp:c_tmpl/discovery/public/header": {
"deps": [ "baiduboxapp:c_tmpl/discovery/public/logo" ]
},
"baiduboxapp:c_tmpl/discovery/public/logo": {
"uri": "baiduboxapp/components/tmpl/discovery/public/logo.js",
}
Call a component
require('baiduboxapp:c_discovery/foo');
Bdbox.c_discovery.foo('content', data);
Actual output:
<!--先在head输出css-->
<link rel="stylesheet" type="text/css" href="baiduboxapp/components/css/discovery/foo.css" />
<!--在body依次输出模板依赖和js模块依赖-->
<script type="text/javascript" src="baiduboxapp/components/tmpl/discovery/public/logo.js"></script>
<script type="text/javascript" src="baiduboxapp/components/tmpl/discovery/public/header.js"></script>
<script type="text/javascript" src="baiduboxapp/components/tmpl/discovery/public/footer.js"></script>
<script type="text/javascript" src="baiduboxapp/components/tmpl/discovery/foo.js"></script>
<script type="text/javascript" src="baiduboxapp/components/discovery/foo.js"></script>
<div id="content"></div>
<script>
Bdbox.c_discovery.foo('content', data);
</script>
Combined with the previous solutions, webapp component development is more handy! Detailed documents
Use tools to simulate the interface, run through the process in advance, and reduce the joint commissioning time
- Baidu mobile is a hybrid app
- Added the role of client Rd, which needs to be cooperated with
- Develop interface / interface joint debugging / WebView page joint debugging
Using FIS to reduce the cost of joint debugging with PHPer
- Can support local interface data simulation
- The first one on ORP line can debug data
- Simulation data is put in TPL / test for others to reuse
tpl/test