记录一些要点,以便于常记起时有据可循!
1 、静态资源与主站分离
上了规模的站点将静态资源分离出来是非常有必要的,好处也是很大的:
( 1 )、 CDN 加速,大胆开启强缓存,降低 DNS 解析和请求的时间;
( 2 )、静态资源的 http 请求和一些在服务器上的 commbo ,会耗费大量服务器资源,分离后会大大减少主站服务器压力;
( 3 )、减少 http 请求头携带的内容,除非后端在 cookies 的作用域做了明确的限制,要不然静态资源的 http 请求头也会携带大量与其无关的内容;
( 4 )、统一管理静态资源的存储与调用,能有效的防止各个站点之间对一些资源的交叉使用造成资源叠加冗余浪费服务器空间,以便于共享缓存;
2 、关于印链
目前我负责的项目是一个对接印刷厂的 ERP 系统(印链);
印链 2.0 以前还不够成熟,业务逻辑也相对简单,总体代码量较小,当时的 js 只是页面上直接 src 的几个文件,由于浏览器的同步加载模式,为了防止 js 的加载执行会阻塞页面的渲染以及可能出现的 DOM 节点 undefined 操作,所以一股脑把 js 放最底部加载就行了;印链 2.0 以后,步子放开了,代码量大增,这时就感觉之前这种加载方式越来越不顺心了,同时各个业务模块之间的代码交叉混杂的情况也越来越多,很不便于维护,为了赶在老大发现问题之前,避免挨骂,就在空余时间准备对全站的 js 使用 Seajs 进行模块化改造;
到了 2.0 阶段,项目已经是大势已成,要对全站的 js 改造的话,风险非常大,同时后端是.NET 将 js 文件的引用路径写进了配置文件,要想每个页面各自一个对应的 js 文件,是很不靠谱的做法,我要做很大改动,后端改动也很大;为了将后端的改动降到最低,同时每个页面能够按需加载 js 并且对之前的代码进行平滑的模块化切分,想来想去,引入了一个 main.js 作为全站的入口主模块,来分发各个页面所需的模块;这样后端永远只需配置两个 js 文件的引用路径( Jquery 和 main.js ); main.js 非常简单,就是一个全站各个页面、或按业务板块分的配置 json ,指明哪个版块需要哪些 js 模块(合并后的),然后就是一个异步加载模块和一个预加载模块; main.js 大致如下:
var clearAllCacheReg=/(,cache:')\w+(')/;//$1w567$2
var staticFilesConf={
path:'/path/to/path/',
maps:{
login:{//登陆
name:'login',cache:'yl.20170104'
},
baseSettings:{//基础资料
name:'baseSettings',cache:'yl.20170113'
}
// ......
// ......
}
}
var YL=function() {
function load() {
var args=arguments;
var head = document.getElementsByTagName('head')[0];
var js = document.createElement('script');
js.type='text/javascript';
js.src=args[0];
head.appendChild(js);
if (document.all) {
js.onreadystatechange = function () {
if (js.readyState == 'loaded' || js.readyState == 'complete') args[1]&&args[1](0);
}
} else {
js.onload = function () {
args[1]&&args[1](0);
}
}
js.onerror=function(){
args[1]&&args[1](1);
}
}
function execJSblock(scriptsStr) {
var script=document.createElement('script');
script.type='text/javascript';
if (document.all) {
script.text=scriptsStr;
}else {
script.appendChild(document.createTextNode(scriptsStr));
}
document.body.appendChild(script);
}
function getHost(){
return $('script:last').length?
$('script:last').attr('src').replace(/(.*?\/\/.+?)\/.*/i,'$1'):
/^(?:file:|test\.|web\.|localhost)|(\w+\.cn)$/i.test(location.host)?
'http://web.xxxxx.cn':
'http://cdn.xxxxx.cn';
}
function preloadModules(maps,ignores){
ignores=[].slice.call(ignores.toString());
$.each(maps,function(i,o){
if ($.inArray(o.name,ignores)==-1) new Image().src=getHost()+staticFilesConf.path+o.name+'.js?'+o.cache;
});
return YL;
}
return {
load:load,
exec:execJSblock,
getStaticFileHost:getHost,
preloadModules:preloadModules,
use:function(fn){
fn&&fn.call(YL,$('body').attr('id'));
}
}
}();
YL
.preloadModules(staticFilesConf.maps,['xxx','xxx'])
.use(function (type) {
var f=staticFilesConf.maps[type],
src=this.getStaticFileHost()+staticFilesConf.path+f.name+'.js?'+f.cache;
if (/msie\s7/.test(navigator.userAgent.toLowerCase())) this.load(this.getStaticFileHost()+'/js/json2.js');
this.load(src,function(err){
if (err) {
YL.load(src,function(err){
if (err) throw src+'---- SCRIPT LOAD FAILED !';
});
};
});
});
为了防止不同页面可能存在的相同节点的操作造成事件多重绑定之类的不可预知问题,采用 new Image().src 的方式来预加载,即只加载不执行,后面直接取缓存;关于缓存的问题,服务器 Nginx 那的缓存我们无法控制就不考虑了,现在采用的是替换式更新,所以用文件内容 hash 替换文件名的方式也暂不考虑了,所以去缓存操作,后端只需给 main.js 加上 query 戳就可以了,那么各个版块的缓存就只需在上面的 maps 里改就行了;结果就是后端可控的 js 就只剩 main.js 了,其他的全在前端控制;
天有不测风云,印链 3.0 开始,换了个更有行业经验的老马(人不老)做产品经理,对整个产品做了变革式的重构,业务版块更多,业务逻辑更复杂,目前已完成他完美战略蓝图的一半据说,前端代码量已超之前两倍;新版继续沿用了 main.js (事实证明 2.0 的改造是有效的),还是 Jquery 作为基础库,放弃了 Seajs 的模块化方式,新代码开始使用 ES6 的模块化方式,用 Webpack 的多入口模式构建;接下来准备在新的大板块中使用 Vue2 来逐步替换 Jquery ,毕竟将之前的代码全改装为 Vue 版的,一下子不太可能,时间也不允许,可能是我有强迫症吧,不太喜欢一份代码里既有 Jquery 又有 Vue ,话说我开始担心了: ES6 普及后 Jquery 未来的路在哪里? 3.0 开始由于准备工作不够充分,初期在 IE7891011 这一家子上栽了个大跟头,直到 ErrorInspector.js (留下了,还在改进中http://famanoder.com/bokes/5867eea54aee37201fb4d1cc)出来不久,情况出现了好转,客户端内核终于换成 webkit 了,是的,厉害的队友总能让人快速的有所长进!现在 main.js 里可以加上 ErrorInspector 了:
ErrorInspector.Config={
url:'http://error.famanoder.com/ErrorInspector/common',
$:{
timeout:60000
},
IgnoreMsgPattern:/script\.error/ig,
IgnoreBrowserError:true
}
3 、关于自学的前端
臭不要脸的说一下,有初学者问我怎么学前端,我只是“敷衍”的说了 6 个字:多看多练多思考;因为我也还处于这条路的探索之中,不敢误导初学者、或者让大神们笑话;最近遇到了瓶颈期,前端没什么进步, Nodejs 学了个半吊子,被 Koa2 吸引却没有太多的尝试,看到社区大家分享的很多重大问题都有些力不从心,没事还担心 Vue 、 React 它们牛逼哄哄的会不会替代 Jquery (看来我依然深爱着 Jquery )。。。如今, Angular2 携 TypeScript 、 AOT 又王者归来了,今年有的是东西去琢磨了;我不喜欢这么多框架,我只是想探索下它们牛逼的地方;谁说爱上一部没有结局的前端剧本,唯一结局就是无止境的追;谁说不管爱上什么剧本,也要不断追求得一个安稳;(好像歌词哈。。。)
好吧,我又得思考一个问题了:百花齐放的前端,留给我的余香会是什么呢?
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.