为了账号安全,请及时绑定邮箱和手机立即绑定

前端瓶颈期,反思一些问题

记录一些要点,以便于常记起时有据可循!

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又王者归来了,今年有的是东西去琢磨了;我不喜欢这么多框架,我只是想探索下它们牛逼的地方;谁说爱上一部没有结局的前端剧本,唯一结局就是无止境的追;谁说不管爱上什么剧本,也要不断追求得一个安稳;(好像歌词哈。。。)

好吧,我又得思考一个问题了:百花齐放的前端,留给我的余香会是什么呢?

原文来自:花满楼http://famanoder.com/bokes

点击查看更多内容
11人点赞

若觉得本文不错,就分享一下吧!

评论

作者其他优质文章

正在加载中
感谢您的支持,我会继续努力的~
扫码打赏,你说多少就多少
赞赏金额会直接到老师账户
支付方式
打开微信扫一扫,即可进行扫码打赏哦
今天注册有机会得

100积分直接送

付费专栏免费学

大额优惠券免费领

立即参与 放弃机会
意见反馈 帮助中心 APP下载
官方微信

举报

0/150
提交
取消