前言:同步一篇2017年1月在QQ空间写的随笔,2017年,我还在实习,现在回首,已经好几年过去,现在看起来,还挺有意思的。
web相对于其他方向来说,会简单点,但是涉及的东西会多点,如今的web程序员,所需的基本技能应该有三剑客,nodejs,php,mysql,http系列协议,网络,浏览器基本原理,apache/nginx,其中包括几十个javascript库和几百个框架,没准还需要个shell和linux常用命令,如果这些都涉猎过了,没事,面试人家还会问各种源码,原理,机制有没有。不过需要的技能其实很大程度上依赖于公司,具体来说应该有这么几种情况 ,参与小系统或者内部系统的开发时,前端程序员其实就是个web程序员,需要自己建表,写服务端逻辑,前端逻辑,写页面样式,交互,俗称全栈,如果有个后台和你搭配,或许你可以免去写后端的代码。参与中型系统开发时,前端程序员需要做的是写交互,页面和样式有重构,前端只需要处理用户操作然后和后台搞好接口就行,参加大型系统开发时,前端程序员还需要写中间转发层,因为前端有个同源策略,对于一般的系统,整个系统都是由一个团队负责的,前后端的代码再怎么分离,也还是有办法解决同源问题,但是大型系统的后台有时候并不是由一个团队负责的,这时候,前端看到的就是一个黑盒子,我们只是根据后台给的接口,把前端的数据传到我们的后台,也就是中间层(中间层可以是nodejs或者php来做),然后在后台去访问别的后台,而且后面可能有好几十个后台串起来,这时候就没有什么前端和后台了,或许叫客户端和服务端更加好,利用中间层,我们解决了同源问题,但是中间层不仅仅是为了解决同源问题。现在很多公司的系统都拆成服务化,比如做一个登录的子系统,然后一大波平台都统一去那校验登录态。中间层也是为了业务的接入。所以,参与开发的系统不同,所需要的技能也不一样。
但是,作为web程序员,最核心的应该还是javascript,javascript这门语言,套路很深,而且和很多传统的语言差别很大,无论是鼻祖c语言,还是各种面向对象的语言,我觉得函数里分配的变量在函数执行完还能被访问,这个点就很不一样,javascript的知识点不算是很多,核心的大概有词法作用域,原型链,this问题,bind/call/apply系列函数,闭包,变量提升,正则,函数是一等公民,变量对象,执行上下文,arguments,setTimeout系列函数等,因为有垃圾回收器,内存管理这个大难题我们就不需要过于担心了,但是javascript的知识只是前端的其中一部分,接下来的还有BOM和DOM的知识还有API非常多,虽然常用的都不会很难,但是一不小心还是会踩坑,高级点的还有v8的一些知识,包括javascript编译和执行的过程原理,js引擎是单线程,浏览器是多线程,事件驱动模型,事件队列,页面加载和渲染原理,浏览器的工作原理。
网络协议也是很重要的一部分,应用层现在说的基本都是http1.1,https和http2,http2的前身spyd已经在chrome里部署,http2目测也要来临了,不过现在讨论比较多的还是https,毕竟安全也是很重要的, http1.1主要需要搞一下rfc文档和http权威指南就功力大增了。http协议的核心知识应该有缓存机制,常见的请求方法,cookie机制,持久连接和管道化机制,常见的http响应码,请求头,响应头的意义。还包括一些安全的,协议升级协商,解决跨域的头部。https协议的知识包括ssl握手机制和过程,connect方法实现https流量的转发,https服务器的搭建。http2加了很多高大上的特性,提供了很多新的功能和对http1.1的性能进行了优化。tcp/ip,dns协议也是前端需要学习的知识,浏览器对域名进行解析或预解析时需要使用dns协议。需要了解浏览器解析域名的机制,比如浏览器里有对域名的解析进行缓存,这会导致使用dns服务器进行负载均衡时达不到效果,host文件里也有域名的映射,利用host文件可以配置不同的域名指向127.0.0.1来进行同源策略的学习,然后dns服务器自然也有缓存或者域名对应的ip,最后还需要了解dns服务器进行域名解析的机制,这些在计算机网络里都会说到。tcp/ip协议里,前端的知识里似乎没有太多涉及到ip协议的,tcp却是很重要的一部分,tcp协议是ssl和http协议的基础,后者都是需要在建立tcp连接的基础上进行工作的,理解tcp协议对前端的优化有很大帮助。
浏览器基本工作原理是前端比较重要的一块,webkit内部这本书讲了很多这方面的知识,而且也很全面, 浏览器工作原理包括域名解析和缓存,tcp连接的管理,cookie管理,同源策略机制,缓存管理,页面代码的分析,布局计算,渲染,js引擎和渲染引擎的互斥工作,dom树和cssom树的构建,dns预解析,页面预渲染,tcp预连接,其实js引擎是单线程和浏览器是多线程这个知识也比较重要,这个对理解为什么大量的cpu密集型的计算会导致浏览器挂掉。为什么js引擎正在执行代码时,点击了按钮,点击事件的回调还可以被会加到事件队列里。还有setTimeout(0)的原理有很大的帮助。浏览器什么时候会进行布局计算和重绘影响我们如何写代码,以免引起性能问题。输入url时,浏览器发生了什么,这个面试题基本是前端面试必问。可见浏览器的原理也是需要了解的。
代理/web服务器也是比较重要的一部分,因为大部分的对外系统,因为安全,性能等问题,都是有代理的,squid和nginx是比较重要的代理服务器,squid是缓存代理,是对静态资源进行缓存以提高性能,nginx是神器,功能太多,接触到的都是做反向代理的,nginx的代码和架构都是享有美誉的,看代码是理解软件的最好方式,作为一个前端,其实去深入研究nginx代码或许暂时没有必要,但是大概看一些工作原理和代码的设计架构,对自己的水平和对nginx的工作原理都是有好处的,tnginx是淘宝基于nginx开发的一个服务器,他们把研究的思路和心得都发布到他们的网站上,有兴趣的可以去瞅瞅,理解了nginx的基本工作原理,nodejs和nginx都是用了一种神技,就是事件驱动模型+单线程,应对网络高并发无压力,和传统的一言不合就开进程和线程不同,进程线程的切换花销很大,而且同步互斥问题很复杂,事件驱动是通过注册事件,事件发生时把回调扔到事件队列里去排队执行,单线程就去不断轮询事件队列,执行回调,其实js也是这样。但这种模式不适合cpu密集型的应用,因为单线程,伤不起。nginx的功能很多,可以做代理服务器,也可以做web服务器(比如配置一个https服务器),邮件服务器,缓存服务器等等,使用nginx主要是需要学会使用nginx.conf。至于参数调优,开发自己的模块,这都是高级话题。说到服务器,谁敢不说老前辈apache,apache一般作为web服务器使用,管理静态页面和和后端的cgi程序通信,把前端的请求分配给cgi程序处理,一般使用的是php,apache一般是以一种预先派生进程/线程的方式工作,这样前端的请求来的时候,就不需要急忙地创建进程/线程,来一个请求,从线程池里拿出一个进程/线程,所以高并发会爆,使用apache一般也是熟悉httpd.conf文件,里面包括配置虚拟主机,需要监听的ip和端口,每个目录的权限控制,文件权限控制,url重写,打log,对静态文件进行缓存管理,配置一些http头,压缩,加载相应的模块等,和nginx类似但是语法不太一样。
后端,作为一个前端,有时候也需要知道后端的知识,因为你不知道什么时候你需要去写后端,学习点后端不至于到时候一脸懵逼,后端现在一般是使用nodejs和php,python也有人用,很多人说对于前端来说,学习nodejs可能不是很难,但其实也不是这么简单,至少不会比php简单,因为对于lamp下的网站,前端发请求到apache,然后apache把请求扔给php,php处理,最多连个数据库,比较简单,但是nodejs就不一样了,因为nodejs是集web服务器和应用服务器与一身的,你用nodejs可以直接监听一个端口,这就是一个服务器,不需要像apache和nginx那样配置什么,然后你前端的请求到nodejs后,nodejs会执行相应的回调,这里有很多东西需要自己去做,而且nodejs的框架如express基本没什么功能,需要安装一大堆中间件去帮你干活。不像php那些框架,什么都帮你做好了,像在php里上传一个文件,用$_FILES就可以拿到文件的内容和信息,在nodejs里你首先要百度一波,然后找一个希望没把你折磨死的中间件,才能完成这个功能,再比如前端传的查询字符串,在php里可以直接根据键值拿到相应的值,在nodejs甚至express里,你得到的只是一个字符串,然后你自己去解析,或者你用中间件去解析,在express的早期版本里,前端post一个嵌套了两层的对象过去,在express里第二层的对象直接变成数组了,差点没吓死我,原因就是早期的中间件功能还不够牛逼,所以对于这种框架,除非你牛逼,自己写中间件,要不然你就是等着那些大牛写中间件给你用的处境,这只是说一下nodejs的学习成本并不低,现在nodejs和相关的框架已经进化得很好,是比较热门的一个技术,因为nodejs的语法是基于js的,所以也比较适合前端程序员学习,只是我们在nodejs里,有时候我们可能需要比在php里做的更多。这差不多就是nodejs给我们最原始的玩意,让我们自己随心所欲去做我们想做的事情。不像python,能用一句代码解决的事情,就不要用两句。nodejs的相关知识点很多,毕竟功能比较强大,常用的大概包括进程相关的,文件系统相关的,处理网络请求相关的,字符串处理相关的。nodejs的运行原理和架构也需要去学习,因为这样才能用好用对nodejs。如果使用express的话可以去瞅瞅他的源码,源码不是很多,因为他是靠大量的中间件来工作的,其中路由的源码是比较核心的,路由也是express里很重要的功能,这里的路由不是前端请求最后怎么分发到具体的业务代码里,指的是对于每一个前端请求,在express里是怎么被处理的。express的路由思想看起来不是很难,不过很有意思,类似于nginx的请求被处理的过程,对于每一个进来的请求,被串行地传到一个个函数或者模块里进行处理,然后决定要传给下一个还是结束这个请求,nginx里也是这么一个过程,有点像设计模式里的责任链模式。最后express里的很多package源码非常值得研究,在npm官网的里很多源码包也值得研究,对js的功力提升有很多的帮助。
数据库,前端其实很少会接触到数据库,基本上就是设计一些简单的表,然后进行增删改查,需要了解一些sql, 对于数据库,其实也是基于一个客户端,服务器模型,我们的cgi程序去连接远端的数据库,也就是进程间的通信,只是有时候是不同的主机间的,连接数据库,基本的参数是数据库进程所在的主机ip,端口(默认是3306),数据库名,用户名,密码。数据库也是一个复杂的玩意,比如sql的解析和优化,连接管理,对数据的缓存和管理。
安全也是web程序员很重要的一部分知识,和前端相关的大概有xss,csrf,点击劫持,和后端相关的大概有sql注入,http头注入,会话劫持,文件上传。xss主要是提交和显示的时候需要对内容进行转义,csrf主要是利用csrfCode来确认某个请求是否是用户自愿发出的,点击劫持遇到不是很多,有一个方法是引用iframe嵌入第三方网站的界面,然后隐藏自己的界面进行劫持用户的输入和点击。这种可以使用http头禁止自己的网页被嵌到别的网页里,或者在前端代码里进行判断跳转,后端的安全主要是需要对用户的输入进行过滤,会话劫持可以修改php配置文件解决,文件上传没有接触过。前端安全中最重要的应该属于同源策略了,现在增加了很多新特性来防止各种安全问题,包括一些http头来定义返回的html文档里资源访问的限制,和对iframe标签里的文档进行权限控制。还有一个是之前比较出名的a标签的target='_blank'的安全问题。
设计模式也是一个重要的部分,写代码一开始是先随便写,实现功能第一,渐渐地,就需要开始考虑怎样写好代码,怎么写比较好,怎么组织比较好,有时候,有些设计模式的确会很优雅地解决一些问题,代码的重用和可维护性对于自己和别人都是很重要的。提高写代码的方法,不仅需要看书学习,也需要不断琢磨,思考,还需要不断地看别人的代码和一些写得比较好的源码。因为如今的前端不再是以前的几个交互,现在的前端已经变得越来越复杂,所以写可持续发展的代码变得很重要。
函数库,框架和软件是用来提高工作和学习效率的,web程序员的常用软件大概有fiddler神器,wireshark神器,whistle还有浏览器f12出来的各种tab,随着浏览器原生地支持很多功能,有些库的功能可能会渐渐变得没必要,现在各大公司已经渐渐放弃作死的ie,不再支持8以下的版本,很多兼容性问题渐渐也会消失。剩下的一堆打包压缩工具就没啥好说的了。
工作其实最主要的技能是学习能力和解决问题能力,学习能力是必不可少的,学习一个新东西时,首先看他的文档先使用它,然后再看他的源码,因为这样才能真正了解他的本质,这是有必要的,即使像nodejs的源码,虽然不可能完全看懂,但是大致的脉搏还是需要摸清一下的,至少我觉得这样用起来才会安心,舒服。当拥有一定的知识后,遇到问题怎么解决,这也是一个重要的部分,控球好的人不一定就会过人,做一个需求,有时候可能只是改一点点东西,但是在哪改,改完会不会对之前的功能有影响。所以改一点点东西的需求,首先你要去看别人的一堆代码,而这堆代码还不一定是在同一个地方,甚至不在一个系统里, 但是这种问题始终需要解决,但这种困难就像看英文文档一样,一开始是会很痛苦,但是慢慢地,你就会习惯这种情况,并且潜移默化中提升了自己的能力。还有一种需求是开发一个完全新的功能,这时候你不需要看别人的代码了,所以这时候你就可以考虑,琢磨你该如何组织和编写自己的代码,使得看起来很舒服,维护和扩展也很容易,这无形中又提高了自己,工作的劳累和压力其实不仅仅来源于工作本身的内容,更来源于你无时无刻都需要思考,很多事情,只有细细考虑,慢慢琢磨才能做好,做对,这会大量消耗你的脑力,所以做技术费脑,有时候并不一定是说你要多聪明,而是你要一直保持你大脑的效率和清晰。
最后想说的是,其实做技术还是需要找到自己的兴趣和方向,抓住重点去 学习,现在技术更新太快,枝繁叶茂,难免会有点方,但是还是需要按照自己的计划慢慢去学,不需要太急躁!多去学一些本质的知识,因为只有这些是不会变的,比如es6的class,其实只是一种语法糖,他的背后也还是以前的原型链知识。现在的开源社区非常活跃,你在上面其实会发现很多很好的代码和很厉害的人,但是我觉得应该学习他们,而不是给自己不好的心理压力。苏轼说的对,早年读书无甚解,晚年省事有奇功,学习的时候,很多东西你觉得没用的,其实在一定程度上他已经提高了你。