V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
推荐关注
Meteor
JSLint - a JavaScript code quality tool
jsFiddle
D3.js
WebStorm
推荐书目
JavaScript 权威指南第 5 版
Closure: The Definitive Guide
famanoder
V2EX  ›  JavaScript

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

  •  
  •   famanoder · 2017-02-12 23:53:58 +08:00 · 4286 次点击
    这是一个创建于 2628 天前的主题,其中的信息可能已经有所发展或是发生改变。

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

    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

    20 条回复    2017-02-14 11:37:20 +08:00
    PythonAnswer
        1
    PythonAnswer  
       2017-02-13 01:17:33 +08:00 via Android   ❤️ 1
    总体来说就是 js python 化 最后 js 一桶天下

    不过 php 是最好的
    a87150
        2
    a87150  
       2017-02-13 01:46:42 +08:00 via Android
    所以到底哪个框架最好?
    Geoion
        3
    Geoion  
       2017-02-13 04:23:16 +08:00 via Android
    用 jQuery 的人重感情。
    thetatxx
        4
    thetatxx  
       2017-02-13 07:11:27 +08:00
    6 个字..
    ttop5
        5
    ttop5  
       2017-02-13 07:33:13 +08:00 via Android
    6 个字, 233
    murmur
        6
    murmur  
       2017-02-13 08:02:13 +08:00
    ES6 再普及浏览器上跑的还不是 ES3 你用的 ES6 是无数 polyfill 和 babel 撑起来的

    IE 得 11 死完到 edge 差不多吧 现在 es5 还得 fill 呢
    ibufu
        7
    ibufu  
       2017-02-13 10:53:52 +08:00
    ng2 亡者归来
    Abigale
        8
    Abigale  
       2017-02-13 11:08:17 +08:00
    6 个字, 2333
    okampfer
        9
    okampfer  
       2017-02-13 11:14:29 +08:00
    到底什么时候才能彻底摘掉 IE 这颗前端大毒瘤。。。
    StargazerWikiv
        10
    StargazerWikiv  
       2017-02-13 12:01:26 +08:00
    6 个字是啥梗?
    thundernet8
        11
    thundernet8  
       2017-02-13 12:56:27 +08:00 via iPhone
    @StargazerWikiv 明明是 7 个字 多看多练多思考
    nanxiaobei
        12
    nanxiaobei  
       2017-02-13 13:01:59 +08:00
    非常 6+1 啊
    famanoder
        13
    famanoder  
    OP
       2017-02-13 21:09:02 +08:00
    @murmur 其实现在情况好很多了,由于 IE8 及以下 object.defineproperty 的硬伤,还有 sha1 认证过期的安全隐患, IE8 即将倒台,而 IE9+通过 babel 基本上没啥大问题了,所以 ES6 还是转码到了 ES5
    famanoder
        14
    famanoder  
    OP
       2017-02-13 21:10:59 +08:00
    @PythonAnswer 新的 ECMAScript 确实借鉴了很多后端语言优良的特性;
    反正我不会拍黄片
    famanoder
        15
    famanoder  
    OP
       2017-02-13 21:14:11 +08:00
    @okampfer 天猫不要 IE8 了,流行框架基本上都是基于 ES6 ,值得有足够的信心拥抱新标准
    famanoder
        16
    famanoder  
    OP
       2017-02-13 21:14:58 +08:00
    @a87150 为什么牛逼的人总是什么都会
    murmur
        17
    murmur  
       2017-02-13 23:00:52 +08:00
    @famanoder 实际上除了 angularjs vue 、 react 的 es5 语法都超优美
    murmur
        18
    murmur  
       2017-02-13 23:08:56 +08:00
    @famanoder 顺便,要不要拥抱新标准,从后端的角度来看,是有多少轮子用,这就是 php5.4 py2.7 java1.6 生生不息的原因,语言不优美 util 优美就可以,人家不提供轮子直接提供造好的跑车
    作为小厂,轮子有多好用永远是第一要素,语言之美?我不认为 es6 有啥吸引我的特性,你说那个叫 class ?下辈子吧。
    那种改变生产力的没有,你说 async ?解构?还是 array 和 object 那些附加函数,或者给 object 里放个[xx]??这跟 css3 不同, css3 有的没有那是真痛苦
    只有前端最牛逼, draft 的特性都敢上生产,换任何一个后端语言找不到, es3 就那个尿性,换了 es6 还那个尿性, c 、 java 、 c#好好抄一个不行么
    imswing
        19
    imswing  
       2017-02-14 11:05:26 +08:00
    @Geoion 这话从何而来 ...
    Geoion
        20
    Geoion  
       2017-02-14 11:37:20 +08:00
    @imswing 念旧,能用就好
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   1674 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 26ms · UTC 00:00 · PVG 08:00 · LAX 17:00 · JFK 20:00
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.