前言:同步一篇2017年1月写在QQ空间的随笔。2017年,我还是实习生。回头看,已经好几年了。很有意思。与其他方向相比,web会更简单,但涉及的东西会更多。现在的web程序员应该具备三剑客的基本功,nodejs、php、mysql、http系列协议、网络、浏览器。原理,apache/nginx,包括几十个javascript库和上百个框架,也许你需要一个shell和linux常用命令,如果你涉猎过这些,没关系,面试官会问各种源码,原理,机制做你有。但是,所需的技能在很大程度上取决于公司。具体来说,应该有几种情况。在参与小系统或者内部系统的开发时,前端程序员其实就是web程序员,需要自己建表写服务。端逻辑,前端逻辑,写页面样式,交互,俗称全栈,如果有后端匹配你,说不定还能省去写后端代码。在参与一个中型系统的开发时,前端程序员要做的就是写交互,页面和样式都要重构。前端只需要处理用户操作,然后与后台接口即可。对于转发层,因为前端有同源策略,对于一般的系统来说,整个系统一个团队负责。不管前后端代码怎么分离,解决同源问题还是有办法的,但是有时候一个大系统的后台不是一个团队负责。这时候前端看到的是一个黑盒子。我们只是把前端的数据按照后端给的接口传输到我们的后端,也就是中间层(中间层可以是nodejs或者php做的),然后在访问其他后台背景,而且后面可能有几十个背景串在一起。同源问题解决了,但是中间层不是只解决同源问题的。现在很多公司的系统都是拆成服务的,比如建一个登录子系统,然后大量的平台去那里验证登录状态。中间层也是业务接入。因此,参与开发的不同系统需要不同的技能。但是,作为一个web程序员,核心应该是javascript。javascript这门语言套路很深,和很多传统语言有很大的不同。不管是鼻祖c语言还是各种面向对象的语言,我认为function函数中分配的变量在函数执行后仍然可以访问。这一点很不一样。javascript的知识点不是很多。核心的大概有词法作用域、原型链、this问题、bind/call/apply系列函数、闭包、变量提升、正则化、函数是一等公民、变量对象、执行上下文、参数、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握手机制和过程,实现https流量转发的connect方法,以及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后浏览器会发生什么?这个面试题基本上是前端面试中的必答题。可见,浏览器的原理也是需要了解的。Proxy/webserver也是一个比较重要的部分,因为大多数外部系统出于安全、性能等问题都会有proxy。Squid和nginx是比较重要的代理服务器。缓存以提高性能。Nginx这个神器,功能太多了。你接触到的都是反向代理。nginx的代码和架构享有盛誉。看代码是了解软件的最好方式。作为一个前端,其实可能没有必要深入研究nginx的代码,但是多看一些工作原理和代码设计架构,可能对自己的水平和nginx的工作原理是有好处的。tnginx是淘宝基于nginx开发的服务器。研究思路和经验发表在他们的网站上。有兴趣的可以看看,了解下nginx的基本工作原理。nodejs和nginx都用了一个神奇的技术,就是事件驱动模型+单线程,来应对网络高并发无压力。不同于传统的在有分歧的情况下打开进程和线程。进程线程的切换开销很大,同步互斥问题也很复杂。事件通过注册一个事件来驱动。当事件发生时,将回调抛出到事件队列中排队等待执行,单线程不断轮询事件队列并执行回调。其实js也是一样的。但是这种模式不适合cpu密集型应用,因为单线程,伤不起。Nginx有很多功能。可以作为代理服务器,也可以作为web服务器(比如配置https服务器)、邮件服务器、缓存服务器等。要使用nginx,需要先了解nginx.conf的使用方法。至于参数调优,开发自己的模块,这些都是高级话题。说到服务器谁不敢说老前辈apache,apache一般作为web服务器,管理静态页面并与后端cgi程序通信,将前端请求分配给cgi程序处理,一般使用php,apache一般都是基于一种方式pre-spawnprocesses/threads,这样当有前端请求来的时候,就不用急着创建进程/线程了。当一个请求来的时候,从线程池中取出一个进程/线程,那么高并发就会爆炸。使用apache一般都熟悉httpd.conf文件,里面包括配置虚拟主机、ip和需要监控的端口、各个目录的权限控制、文件权限控制、url重写、日志记录、静态文件的缓存管理等等配置HTTP头、压缩、加载相应模块等,与nginx类似,只是语法不同。后端,作为前端,有时候你需要知道后端的知识,因为你不知道什么时候需要写后端,学习后端也不会让你看起来当时很迷茫。后端一般用nodejs,也有人用PHP和python。很多人说对于前端来说,学习nodejs可能不难,但是也没有那么简单,至少不会比php简单,因为对于lamp下的网站来说,前端向apache发送请求,然后Apache抛出请求到php,php自己处理,最多连接一个数据库,比较简单,但是nodejs不一样,因为nodejs是web服务器和应用服务器的结合体,直接用nodejs监听一个端口就可以了,这是一个server不需要像apache和nginx那样配置,然后你的前端请求到达nodejs后,nodejs会执行相应的回调。需要自己做的事情很多,而express等nodejs的框架基本没有任何功能,需要安装很多中间件来帮你完成工作。不像php框架,一切都为你做好,就像在php中上传文件一样,你可以使用$_FILES来获取文件的内容和信息。在nodejs中,首先需要百度一下,然后找一个无望的。只有把你折磨死的中间件才能完成这个功能。比如前端传过来的查询字符串,在PHP中可以直接根据key值得到对应的值。在nodejs甚至express中,你得到的只是一个字符串。然后你自己解析,或者你用中间件解析。在早期的Express版本中,前端post一个两级嵌套的对象过去。在Express中,二级对象直接变成数组,几乎不可怕。对我来说,原因是早期的中间件功能不够强大,所以对于这种框架,除非你牛逼自己写中间件,否则你就等着那些大佬给你写中间件。只能说nodejs的学习成本不低。现在nodejs和相关的框架发展的很好,是比较流行的技术。因为nodejs的语法是基于js的,所以也比较适合前端程序员学习,但是我们在nodejs中,有时候我们需要做的事情可能比在php中要多。这几乎是nodejs给我们的最原始的东西了,让我们可以为所欲为。不像python,一行代码就能解决的事情不要用两句话。nodejs相关的知识点很多。毕竟功能比较强大。常用的大概有进程相关、文件系统相关、网络请求处理、字符串处理等。nodejs的运行原理和架构也是需要学习的,因为只有这样才能用好nodejs。如果你使用express,你可以看看它的源代码。源码不多,因为它依赖大量的中间件来工作。其中路由的源码是比较核心的,路由也是express中非常重要的一个功能。这里的路由并不是前端的请求最终是如何分发到具体的业务代码中的,是指每个前端请求在express中是如何处理的。expressrouting思路看起来不是很难,但是很有趣。类似于nginx请求处理的过程。对于每一个传入的请求,依次传递给各个函数或者模块进行处理,然后决定传递给下一个还是结束请求,这和nginx中的流程是一样的,有点像责任链设计模式中的模式。最后,express中的很多包源码值得学习,npm官网的很多源码包也很值得学习,对提高js功力有很大帮助。数据库,前端很少接触数据库,基本就是设计一些简单的表,然后进行增删改查,需要会一些sql,对于数据库来说,其实是基于一个client,server模型,我们的cgi程序连接远程数据库,也就是进程之间的通信,有时只是在不同主机之间。连接数据库,基本参数是数据库进程所在主机ip,端口(默认3306),数据库名,用户名,密码。数据库也是一个复杂的东西,比如sql分析和优化,连接管理,数据缓存和管理。安全也是网络程序员非常重要的知识部分。与前端相关的可能包括xss、csrf、点击劫持,与后端相关的可能包括sql注入、http头注入、session劫持、文件上传等。xss主要是在提交显示的时候需要对内容进行转义。csrf主要是通过csrfCode来确认一个请求是否是用户自愿发送的。遭遇点击劫持的并不多。一种方法是将iframe嵌入第三方网站界面,然后隐藏自己的界面,劫持用户输入和点击。这个可以通过http头来禁止自己的网页被其他网页嵌入,或者在前端代码中进行判断跳转。后端的安全主要是需要对用户的输入进行过滤。会话劫持可以通过修改php配置文件来解决。文件上传不受影响。前端安全最重要的应该是同源策略。现在增加了很多新特性来防止各种安全问题,包括一些http头来定义返回的html文档中的资源访问限制,以及iframe标签中的文档。访问控制。还有一个众所周知的a标签的target='_blank'的安全问题。设计模式也是一个重要的部分。开始写代码,先随便写,先实现功能。渐渐地,你需要开始思考如何把代码写好,如何写得更好,如何组织得更好。有的时候,一些设计模式确实会优雅的解决一些问题,代码复用性和可维护性对自己和他人来说都很重要。提高写代码的方法,不仅需要阅读和学习,还需要不断的琢磨和思考,还要不断地阅读别人的代码和一些写得好的源代码。因为现在的前端已经不是以前的那几个交互了,现在的前端已经越来越复杂了,所以写出可持续的代码非常重要。函数库、框架和软件用于提高工作和学习效率。web程序员常用的软件大概有fiddler神器、wireshark神器、whistle以及浏览器f12的各种tabs。随着浏览器的原生支持,很多函数,一些库函数可能会逐渐变得不需要,现在各大公司也逐渐放弃了ie,不再支持8以下的版本,很多兼容性问题也会逐渐消失。剩下的那一堆打包压缩工具就没什么好说的了。其实,工作中最重要的技能就是学习能力和解决问题的能力。学习能力必不可少。学习一个新东西,先阅读它的文档并使用它,然后阅读它的源代码,因为只有这样你才能真正理解它。理解nodejs的精髓是很有必要的,即使无法完全理解nodejs的源码,但总的脉搏还是要揣摩的。至少我认为使用起来会安全舒适。当你有了一定的知识后,如何解决问题也是很重要的一环。控球能力好的人,未必就高人一等。做一个需求,有时候可能只是改一个小东西,但是改哪里,改了会不会影响之前的功能?所以,你要改一点东西,首先得看一堆别人的代码,而这一堆代码不一定在同一个地方,甚至不一定在同一个系统,但这种问题总是需要解决,但这种困难就像阅读英文文档一样,一开始会很痛苦,但慢慢地,你会习惯这种情况,潜移默化地提高自己的能力。另一个要求是开发一个全新的功能。这个时候你不需要看别人的代码,所以你可以想着这个时候怎么组织和写自己的代码,这样看起来很舒服,维护和扩展也很容易,无形中提高自己。工作的疲劳和压力,不仅仅是工作内容本身造成的,更重要的是你需要时刻思考。很多事情只有细细思索,慢慢来,才能做成。嗯,做对了,这会消耗你很多的脑力,所以做技术是很费脑的,有时候不一定代表你有多聪明,但是你要保持大脑的高效和清晰。最后想说的是,其实做技术还是需要找到自己的兴趣和方向,抓住重点来学习。现在技术更新太快,枝繁叶茂,难免有些尴尬,但还是要按照自己的计划慢慢走。学习,不用太心急!学习更多必要的知识,因为只有这些不会改变。比如es6的类,其实只是一种语法糖,背后是原型链的前期知识。现在的开源社区很活跃,其实你可以在上面找到很多好的代码和很棒的人,但是我觉得你应该向他们学习,而不是给自己带来不好的心理压力。苏轼说的对。早年读书不多,晚年有省事之功。你在学习的时候,很多你觉得没用的东西,其实他在一定程度上提高了你。
