开篇

现在Web富应用越来越多,越来越多网站朝单页面发展,所有功能模块都在一个页面中创建。作为一个合格的前端,所负责的模块一定是逻辑跟UI分离的,通常的做法就是页面代码编写成模板,然后往模板填充数据并输出到页面上。关于前端模板的介绍和使用我就不说了,不了解的可以先看看这篇文章(http://www.css88.com/archives/4564),这里讨论下使用模板引擎引入的另外一个问题(也不是Bug啦~) -- 页面模板代码放哪?

页面模板代码放哪

呼~~总算到正题了(- -||)。说回来,页面模板的代码到底要放哪呢?

  1. 放在 js 文件中;
  2. 放在页面不可见的地方,比如 标签内;

话说很久很久以前,我也是把模板写在js里面的,然后需要修改的时候就崩溃了~ 在一堆字符串里面找到想要改动的地方就像是在一坨黄色的屎里面找个金戒指(恶...)。过了不久学乖了,把模板像写html那样换行和缩进,就跟下面一样。more

var html = '\
    <div id="container">\
    <div>...</div>\
    <div>...</div>\
</div>'

然后代价是 -- 要给会混淆的引号转义以及每行末尾都要一个反斜杠! oh~天啊,我可是程序员啊,为什么要做这种重复无趣的工作!

于是很久很久以前的以后,我又学乖了一次,咱这次把模板写在html页面里面,放到一个特殊的script标签内,用到的时候根据id找到这个script,读取innerHTML拿来用。哇,简直是perfect!吼吼

/**
 * shot of getElementById
 * @param {String} id
 */
this.get = function(id{
    return document.getElementById(id);
}
var templateList = {};
/**
 * 获取页面的一个 html 模板
 * @param {String} tmplId 模板的 dom id
 */
this.getTemplate = function(tmplId){
    var tmpl = templateList[tmplId];
    if(!tmpl){
        var tmplNode = this.get(tmplId);
        tmpl = tmplNode.innerHTML;
        tmplNode.parentNode.removeChild(tmplNode);
        templateList[tmplId] = tmpl;//缓存起来,避免再次查找dom
    }
    if(!tmpl){
        throw new Error('no such template. [id="' + tmplId + '"]');
    }
    return tmpl;
}

模板的飞来横祸

从此,模板和页面过着幸福快乐的生活...然后直到有一天...

A: 为什么打开页面的那个菊花转那么久!

我:...

然后就如五雷轰顶般的醒悟,由于是单页面,模板都堆积到页面,大大增加了首页的大小,没什么逻辑的页面竟然有37KB(gzip前)。更因为js/css/images等都放到了多台cdn,读取速度快而且可以设置和利用浏览器cache。而html页面则只放在一台web server,而且因为版本迭代比较快,不能给html设置缓存策略(那样会导致用户那里不能及时更新)。

王子和公主就这样被硬生生拆散了~T_T

模板该放哪里

如果现在要我把模板都改成js变量,放到js文件里,我一定死给他看,哼~

然而,只是,可是,但是,加载速度还是得优化啊。既然开发的时候要方便,发布之后要速度,那发布前用脚本把模板抽取到js文件中不就结了? 顿时感觉柳暗花明又一村呀呼啦啦啦

抽取的步骤为:

  1. 在js文件中增加一个变量 templateList,值为 {/HtmlTemplates/} (注: 其实什么都行啦,这样只是为了可以正常运行以及不让编辑器报错...);
  2. 编写脚本(nodejs/python/shell/etc.),用正则把作为模板的script的id和innerHTML都匹配出来,拼装成一个json字符串,如:{ "templateId1": "value.....", "templateId2":"xxxx"} ;
  3. 读取该js文件,把 " {/HtmlTemplates/} "替换成生成的json字符串;
  4. 修改getTemplate方法,优先从templateList查找模板;

至于抽取用什么语言写都没所谓啦,仅仅是正则和文件操作,推荐用nodejs,真是太方便了。不过大部分机器都木有装,需要自己装。有些环境不能随便装新程序,那也可以用python写个,花半个钟现学现用就够了。附上个NodeJs版的。

var fs = require('fs');
var inputHtmlFile = './index.html';
var outputHtmlFile = './out/index.html';
var inputJsFile = './js/mb.templates.js'
var outputJsFile = './out/js/mb.templates.js';

var content = fs.readFileSync(inputHtmlFile).toString();
var regex = /<script\s*id="(\w+)"\s*type="text\/plain"\s*>([\s\S]*?)<\/script>/ig;

var result = {};
content = content.replace(regex, function(m, $1, $2){
    result[$1] = $2.replace(/\n|\r/g, '');
    return '';
});
fs.writeFileSync(outputHtmlFile, content);

content = fs.readFileSync(inputJsFile).toString();
var templateStr = JSON.stringify(result);
content = content.replace('{%HtmlTemplates%}', templateStr);
fs.writeFileSync(outputJsFile, content);

收尾

经过这么一搞,把模板代码抽出来之后,首页的大小立马从37KB降到1.7KB。虽然是个小技巧,也足以成大谋。那感觉,可是跟涨薪一样爽哇~~

Comments
Write a Comment
  • duwei reply

    小龙的文章真闷骚啊。<br>话说用得着嘛,你搞个iframe专门放模版页面不就解决了。

  • Azrael reply

    @duwei iframe还得去请求解析等等, js多方便啊

Tags

css3   魅力CSS   nodejs   loading   CSS   疯狂的菊花   html5   animation   compiler   编译脚本   png   WordPress   智能   旅行   优化   模板   历史记录   跨域   manifest   frame   canvas   动画   js   离线应用   codelet   transform   抽取   java   兼容问题   发布脚本   富文本   那一年在他乡   htaccess   iframe   帧动画   加载速度   intelligent   跨浏览器   DNS解析   插件   checkbox   单边   step-start   vary   复选框   自动更新   转换   文本溢出   盒子阴影   menu   blob   西安   滑动背景   box-shadow   内存占用   键盘事件   python   auto   text overflow   background   所见所得   android   rotate   字节数   合并   文本框   slide   字符串连接符   协议   伪类   兄弟选择符   网格   节点位置比较   空白   斜线拼接   自定义命令   溢出   clock   素描   无法更新   分隔符   字符编码   body   下载文件   精灵图   step   nodej   ubuntu   apache   css3选择器   创建文件   多级菜单   编辑状态   ajax   阴影   垂直   chrome   管道   时钟   firefox   背景   文件上传   createobjecturl   游记   下载   放射渐变   版本号   宽高   照片   localStorage   渐变背景   图片   图片拼接   属性值检测   自动生成   计算   返回键   oauth   合图   reset   调用   cavnas   漏洞   按钮   margin   线性渐变   xsrf   被黑   tab   checked   修复   border   消失   step-end   sprite   common-upload   菜单   兄弟选择器   字符串   svn   九寨沟   缩进   css遮罩   svg   添加系统服务   gzip   插入代码   动态   加速   模拟