@mircode
2016-07-12T11:31:08.000000Z
字数 3861
阅读 953
her
Her一方面集成了FIS的前端工程化能力,能够有效的解决前端开发中自动化工具、性能优化、模块化框架、开发规范、代码部署、开发流程等问题。同时又在此基础上实现了Pagelet和类Bigpipe输出渲染控制,从而有效的提升了页面加载和渲染性能,所以说Her是一个页面高性能的渲染方案。
这种架构图中,我们可以看到Her相当于FIS来说,增加了对页面渲染做了优化。对于首屏幕界面,Her实现了
npm install her -g # or sudo npm install her -g
home # 模块名
|- lib (前后端运行时代码目录,即 her-runtime)
|- page (页面模板目录)
|- static (静态资源目录)
|- widget (模块化资源目录)
|- fis-conf.js (构建工具配置文件)
her release -cw
her server init # 下载 smarty rewrite 模块等
her server start --type php
Her中,分别使用{html},{head},{title},{body}来替换HTML中的,html,head,title,body标签。
Her中,通过是用pagelet标签,对页面进行细粒度的分块。分块收集HTML 片段及其依赖的CSS、JS资源,对页面模块进行细粒度编码,分解资源依赖和数据获取等。
页面会首先把{Pagelet}区块输出成一个空的div占位,同时会输出code标签,内容就是对应Pagelet的html片段,接下来再通过Bigpipe.onPageletArrive的方式输出这个Pagelet。
<html>
<head><link href="{框架样式}" /></head>
<body>
{pagelet}
HTML内容
<script runat="server">
//区块的功能
</script>
{/pagelet}
{pagelet}HTML内容{/pagelet}
{pagelet}HTML内容{/pagelet}
</body>
</html>
运行时代码会成为
<html>
<head><link href="{框架样式}" /></head>
<body>
<div id="__elm_0_1"></div>
<div id="__elm_0_2"></div>
<div id="__elm_0_3"></div>
<script src="{框架Js}"></script>
<code id="__cnt_0_1" style="display:none"><!-- HTML片段 --></code>
<script>
Bigpipe.onPageletArrive({
"id":"__elm_0_1",//Pagelet ID
"container_id":"__cnt_0_1",//片段内容ID
"css":[],//依赖样式
"js":[],//依赖脚本
"callback":{"load":["__cb_0_1"]}//回调函数名
});
</script>
</body>
</html>
支持四种渲染方式server|lazy|none|default
server,直接输出 html 内容到页面,同时将 beforedisplay 依赖加入 root context,其他同 default
lazy,只输出 pagelet 占位标签,不输出其他数据,需要手动通过 Bigpipe.fetch() 异步加载,通过 BigPipe.lazyPagelets 可以获取lazy pagelets
none,不输出,直接跳过 pagelet,可通过条件判断控制是否输出 pagelet
通过渲染方式的设置,我们可以方便实现核心(首屏)模块优先输出、非核心模块延迟输出,模块开关等。
{script}标签用来标注并收集页面中的代码片段。在输出时,Her 会将收集的代码封装成函数并且自动控制调用时机。
{script} 标签支持 pagelet-on 属性,用来控制脚本执行的时机。默认为 "load" ,即 pagelet 的HTML加载后执行。
同时该标签,还支持传入参数
{$name="我是含有引号( ' )的用户名"}
<script runat="server" pagelet-on="beforeload" var-userName=$name>
var xxx = require(xxx);
xxx.XXX();
alert(userName);
</script>
运行时代码会成为
<script>
BigPipe.hooks["系统管理的ID"] = function(require, pagelet){
var userName = "我是含有引号( \' )的用户名";
var xxx = require(xxx);
xxx.XXX();
alert(userName);
};
</script>
{require} 标签用来标注一个资源依赖。可以用于CSS和Js资源, resourcePath 为资源路径。
{require name="common:js/jquery.js"}
{require name="common:css/color.css"}
{define} 标签用来定义一个可重用模板片段,该片段可以通过 {widget} 标签调用。
{*common:widget/title/title.tpl*}
{define userName="默认用户名"}
<!-- 一个可以重用的用户名显示组件 -->
<dl>
<dt>姓名</dt>
<dd>{$userName|escape}</dd>
</dl>
{/define}
{*调用方式如下:*}
{widget name="common:widget/title/title.tpl" userName="张三"}
{widget} 标签用来调用用 {define} 定义的可重用的模板片段。
BigPipe.fetch(pagelets[, url, cache]) 函数
用于局部刷新页面,pagelets为需要刷新的区块的id数组,url为请求区块的url地址。
BigPipe.fetch(["sidebar","container"], "index?nav=1", true);
三个接口方法
requier方法,用于加载依赖的,被 require的模块将在引用代码执行前被加载。(AMD规范,同步加载)
defer和async方法,用于动态加载模块。支持加载JS和CSS,加载完毕后执行callback方法回调。(CMD规范,异步加载)
注意
require.defer 与 require.async 唯一的区别在于: require.defer 会将模块的加载推迟到页面 onload 之后,以防止对首屏速度的影响。一般来说不建议使用,请用 require.defer 替代。
通过注释中的 @require moduleName moduleName 来标明这个文件的依赖css文件名,支持绝对和相对路径。
例如:
/**
* slogan也使用了 section的样式
* @require ../section/section.css
*/
Her同时支持CSS背景图片定位的能力,对于开发者,只需要根据开发目录写图片的相对路径即可。
#forkme_banner {
background: url('blacktocat.png') #0090ff no-repeat 95% 50%;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='macbook.png')
}
编译后
#forkme_banner {
background: url('/static/home/widget/slogan/blacktocat.png') #0090ff no-repeat 95% 50%;
filter: progid:DXImageTransform.Microsoft.AlphaImageLoader(src='/static/home/widget/slogan/macbook.png')
}
}