前言
2006年至今,我们时常可以看到JavaScript的新闻,刚开始只是JavaScript引擎性能的提升,到后来发现很多是来自HTML5和Node创造的奇迹。如果只看表面,很容易让人感觉这又是一颗卫星。这种现象让人觉得不可信,所以出现了以下各种版本的误解。
❑ Node肯定是几个前端工程师在实验室里捣鼓出来的。
❑ 为了后端而后端,有意思吗?
❑ 怎么又发明了一门新语言?
❑ JavaScript承担的责任太重了。
❑ 直觉上,JavaScript不应该运行在后端。
❑ 前端工程师要逆袭了。
一方面,大家看到JavaScript在各个地方放出异彩,其他语言的开发者既羡慕它的成果,又担心它对当前所从事的语言造成冲击;另一方面,人们还是有JavaScript只能做前端脚本的定势思维。究其原因,还是因为人们缺乏历史观层次上的认知,所以会产生一些莫须有的惴惴不安。
1995年,JavaScript随网景公司发布的Netscape Navigator 2.0发布,它最早命名为LiveScript,随后更名为JavaScript。它出自如今的Mozilla公司的CTO——Brendan Eich之手,其产生来源于网景公司发布的Netscape Navigator浏览器需要一种脚本语言来协助浏览器做一些简单的动态操作。当时网景公司与Sun公司合作密切,不懂技术的管理层希望得到一个Java的脚本版语言,以期能像Java一样风靡。Brendan Eich原本进入网景公司是希望做Scheme语言的开发,但是却接到了一个不喜欢的任务,但迫于当时形势,不得不完成此事,于是JavaScript之父在10天的时间里仓促完成了JavaScript的设计,当时的项目代号是Mocha,名字叫LiveScript。
这门语言除了看起来像Java外,本质与Java语言相去甚远,管理层期望的Java Script其实借鉴了C、Scheme、Self、Java的设计。尽管仓促,但是这门语言还是借鉴了其他语言的不少优点,如函数式、原型链继承等。处于Java阴影下的这门语言获得了它最终的名字:JavaScript。至今,仍然还有许多人分不清Java与JavaScript的关系,就像分不清雷锋与雷峰塔一样。
虽然JavaScript的产生与Netscape Navigator浏览器的需求有关系,但它并非只是设计出来用于浏览器前端的。早在1994年,网景公司就公布了其Netscape Enterprise Server中的一种服务器端脚本实现,它的名字叫LiveWire,是最早的服务器端JavaScript,甚至早于浏览器中的JavaScript公布。对于这门图灵完备的语言,网景早就开始尝试将它用在后端。
随后,微软在第一次浏览器大战时,于1996年发布的IE 3.0中也包含了它的脚本语言:JScript。基于商标的原因,它叫JScript,但是与JavaScript兼容。在1997年年初,微软在它的服务器IIS 3.0中也包含了JScript,这就是我们在ASP中能使用的脚本语言。鉴于微软处处与网景针锋相对,出于保护自己的目的,网景公司推进了JavaScript的标准化进程,于1996年11月将JavaScript递交给ECMA国际标准组织,在1997年7月公布了第一个版本,是为ECMA-262号标准,又称ECMAScript。
可以看到,JavaScript一早就能运行在前后端,但风云变幻,在前后端各自的待遇却不尽相同。伴随着Java、PHP、.NET等服务器端技术的风靡,与前端浏览器中的JavaScript越来越重要相比,服务器端JavaScript逐渐式微。只剩下Rhino、SpiderMonkey用于工具。
然而,这个世界是变化的。第一次浏览器大战落幕后的JavaScript的世界有些平静,但依然在萌生一些变化。Google对Ajax的应用让JavaScript变得越来越重要。Firefox的发布掀起了对IE的反攻,迎来了第二次浏览器大战,竞争令JavaScript的性能不断提升,Chrome的加入令它高潮迭出。CommonJS规范的提出,不断在完善JavaScript。ECMAScript标准的不断推进,令语言更加精炼简洁,不停地去芜存菁。
浏览器端JavaScript在Web应用中盛行,甚至让人们忘掉了JavaScript可以在服务器端运行这码事。但是,服务器端JavaScript现在回来了,因为Node诞生了。Node的诞生离不开上述的历史契机,服务器端JavaScript在漫长的历史中长期停滞留下空白,但Node重新将这个领域激活。Ryan Dahl基于对高性能Web服务器的探索,无意间促成了服务器端JavaScript领域的焕然一新。Node凭借V8的高性能和异步I/O模型将JavaScript重新推向了一个高潮。现在,Node不仅满足JavaScript同时运行在前后端,而且性能还十分高效。与传统印象中的不同,它甚至可比于当前的高效脚本语言。
奇妙的反应还在继续,前后端要跨语言开发的现状已经开始改变,因为语言堆栈的不同,开发者的分工也进行了细分:前端工程师和后端工程师。专业技能因为分工而精进,但也将技能变为专利,似乎前端工程师不能进行后端开发,后端工程师搞不定前端开发,犹如树立的墙。但Node的出现令这种分工的界限又开始模糊了。同时一些后端工程师也关注到Node,他们甚至不关心前后端语言是否一致,而是赤裸裸地表示对Node高性能的垂涎,如实时、高并发等。
大量的前后端工程师加入了Node的开发阵营,GitHub上JavaScript是最活跃的开发语言,NPM社区第三方模块恐怖的增长速度和下载量都昭示着这个过程不可逆,在这里吼一声万能的NPM,总能找到你需要的解决方案。很多不断涌现的项目和创意都因为Node和前端开发能共用一种语言而独特。换言之,Node的本意是提供一个高性能的面向网络的执行平台,但无意间促成了JavaScript社区的繁荣,并进而形成强大的生态系统。
本书目的
目前,还没有一本书将Node自身结构介绍出来,大多停留在Node介绍或者框架、库的使用层面上,本书希望从不同的视角揭示Node自己内在的特点和结构。也许你已经用过Node进行相关的开发,在使用了Node带来的欣喜后,还能在阅读本书时,发出一句“哦,原来Node是这样的”,这就是本书的简单寄望。
对于Node初学者,目前市面上也已经有Node相关的入门书,它们可以快速地领你进入Node开发之旅。在了解了这些基本过程后,想了解更多Node知识的好奇心,会领你来阅读本书的。
阅读建议
本书并非完全按照顺序递进式介绍,如第2章是从代码组织结构看待Node,第3章是从运行结构看Node,第4章则是从编程结构看Node,第5章则是Node中内存结构的揭示,第6章谈及的是Node中的数据在I/O流中的结构或状态,第7章是Node在网络服务角度的介绍,第8章是Node在HTTP上的展现,第9章讨论了Node的单机集群结构,第10章是从单元测试和性能测试的角度去关注Node,第11章虽然已经脱离了Node编码的范畴,但是站在产品化的角度看待Node,也会颇有收获。
下面是各章的详细介绍。
第1章:这一章简要介绍了Node,从中可以了解Node的发展历程及其带来的影响和价值。
第2章:这一章介绍了Node的模块机制,从中可以了解到Node是如何实现CommonJS模块和包规范的。在这一章中,我们详细解释了模块在引用过程中的编译、加载规则。另外,我们还能读到更深度的关于Node自身源代码的组织架构。
第3章:这一章展示了在Node中我们将异步I/O作为主要设计理念的原因。另外,还会介绍到异步I/O的详细实现过程。
第4章:这一章主要介绍异步编程,其中有常见的异步编程问题介绍,也有详细的解决方案。在这一章中,我们可以接触到Promise、事件、高阶函数是如何进行流程控制的。
第5章:这一章主要介绍了Node中的内存控制,主要内容有垃圾回收、内存限制、查看内存、内存泄漏、大内存应用等细节。
第6章:这一章介绍了前端JavaScript里不能遇到的Buffer。由于Node中会涉及频繁的网络和磁盘I/O,处理字节流数据会是很常见的行为,这部分场景与纯粹的前端开发完全不同。
第7章:这一章介绍了Node支持的TCP、UDP、HTTP编程,还附赠了WebSocket与TLS、HTTPS的介绍。
第8章:这一章介绍了构建Web应用的过程中用到的大多数技术细节,如数据处理、路由、MVC、模板、RESTful等
第9章:这一章介绍了Node的多进程技术,以及如何借助多进程的方式来提升应用的可用性和性能。
第10章:这一章介绍了Node的单元测试和性能测试技巧。
第11章:“行百里者半九十”,完成产品开发的代码编写后,才完成了项目的第一步。这一章介绍了将Node产品化所需要注意到的细节,如项目工程化、代码部署、日志、性能、监控报警、稳定性、异构共存等。
附录A:详细介绍了Node的安装步骤。
附录B:讨论了Node的调试技巧。
附录C:探讨了团队实践或多人协作过程中需要关注的编码规范问题,它可以很好地规避一些低级的、明显的错误。
附录D:作为企业开发者,必须关注模块仓库的搭建管理。在这一章中,我们介绍了如何通过搭建私有NPM来解决企业隐私安全等方面的问题。