[现代Web] [论文] 服务器端JavaScript框架研究

引言

       “Any application that can be writtenin JavaScript, will eventually be written in JavaScript.(任何可以用JavaScript编写的应用最终都会由JavaScript来编写)”2007年,一个叫做Jeff Atwood [1]的美国程序员在他的博客中写下了这样一句话,这也被人们称为Atwood’s Law。实际上在当时,Javascript的主要运行环境是浏览器,浏览器作为JS代码的解析器,为JS提供了操作DOM对象和window对象的接口。

        两年之后,Node.js,一个能够在服务器端运行JavaScript的开放源码、跨平台的运行环境诞生了,它是服务器端JS的代码解析器,也是JS的一种运行环境,为JS提供操作文件、创建http服务、创建TCP/UDP服务等接口,所以Node.js可以完成其他后台语言能完成的一切工作。随著Node.js的发展,我们意识到Atwood’s Law的远见性──JavaScript的确越来越强大了。

 

第一章    概述

        Node.js 诞生自2009年,作为一个新兴的开发工具,历史远不如 Python、Ruby、PHP 等“老大哥”,但是它却是有史以来发展最快的开发工具,没有之一。在短短的几年间,我们看到了Node.js从最初一个小小的演示项目到如今拥有规模庞大的使用开发者,这是其他任何开发工具所不能企及的。

1    发展历程

1.1    诞生初期

       Node.js于2009年写成,其原始作者是Ryan Dahl。Node.js结合了Google的V8引擎、事件驱动模型和底层I/O接口[3],其设计灵感源自Flickr的一款上传进度栏:在上传过程中,浏览器并不清楚有多少文件已经发送到服务器,除非向服务器发送额外的请求进行查询,如何让服务器同时高效地处理两件事情呢?那么如果所有事情都是非阻塞的呢?如果我们从来就没有等待过任何I/O操作的完成呢?

        Dahl原本的工作是用C/C++写高性能Web服务,对于高性能,异步IO、事件驱动是基本原则,但是用C/C++写就太痛苦了。最终,Ryan选择了JavaScript [4]。选定了开发语言,还要有运行时引擎,V8作为开源的JavaScript引擎,可以很方便地进行改造并直接使用。

        2009年11月8日,Dahl在欧洲JSConf大会上展示了Node.js项目,并受到了广泛关注。在演讲中,Dahl针对Apache HTTP Server和顺序编程方式提出了批评,认为Apache处理大量并发连接(10,000甚至更多)的可能性有限,而且顺序编程方式在多连接情况下会造成阻塞,或者消耗更多资源;而Node.js提供了基于事件驱动和非阻塞的接口,可用于编写高并发状态下的程序,且JavaScript的匿名函数、闭包、回调函数等特性就是为事件驱动而设计的。

        2010年1月,Node.js的核心用户Isaac Z. Schlueter开发出奠定了Node.js如今地位的重要工具——npm。作为一个软件包管理系统,npm使程序员能够更方便地发布和分享Node.js类库及源代码,而且简化了类库安装、升级与卸载的过程。

        Node.js最初只支持Linux和Mac OS X操作系统,2011年6月,微软和Joyent公司合作,把Node.js移植到了Windows系统上面,并在7月发布了第一个正式支持Windows系统的版本。

1.2    成长分裂期

       随后,Connect、Express、Socket.IO等框架的出现吸引了一大波爱好者加入到 Node.js 的开发者阵营中来。 CoffeeScript的出现更是让不少Ruby和Python开发者找到了学习的理由。期间一大波以Node.js作为运行环境的CLI工具涌现,其中不乏有用于加速前端开发的优秀工具,如less,、UglifyJS,、browserify、grunt等等,Node.js的发展势如破竹。[2]

       另一方面,2012年1月,Dahl离开了Node.js项目,由于对Joyent的管理感到不满,Node.js核心开发者Fedor Indutny在2014年12月制作了分支版本,并起名为“io.js”。与Node.js相对的是,io.js采用开放管理模式进行管理,并计划始终采用最新版的V8引擎。

1.3    飞速发展期

       为了在用户、厂商和开发者之间获取平衡,Node.js基金会于2015年初成立。基金会得到了IBM、Intel、微软、Joyent等公司的支持。6月,Node.js和io.js开发者社区共同决定合并到Node.js基金会之下。同年9月,Node 4.0发布,Node.js和io.js正式合并。到了2016年,io.js宣布不再发布新版本,并建议开发者换回Node.js。

       随著ES2015的发展和最终定稿,一大批利用ES2015特性开发的新模块出现,如原express核心团队所开发的koa。Node.js始终紧跟着时代和标准的发展,在经历了成长、分裂和合并之后进入到飞速发展阶段,社区用户数量激增、npm也成为全球最大的开源库管理系统。


2    Node.js特点

       Node.js官网首页上的简介是这样三句话:Node.js是基于Chrome V8引擎建立的一个JavaScript运行时平台。它采用事件驱动和非阻塞I/O模型使其轻量且高效。其自带的包管理系统npm是世界上最大的开源库管理系统。下面简要介绍Node.js的两个特点:

2.1    非阻塞I/O与事件驱动

       传统Web服务器采用多线程模型,为每一个业务逻辑提供一个系统线程,通过系统线程切换弥补同步式I/O调用的时间开销。[5] 而Node.js采用单线程模型,对于所有I/O都采用异步请求方式,避免了频繁的上下文切换。

图1 Node.js非阻塞I/O与事件循环

        如图1所示[6],Nodejs中的异步I/O操作是通过libuv这个库来实现的,包含了window和linux下面的异步I/O实现[7]。当涉及到I/O操作的时候,Node会开一个独立的线程来进行异步I/O操作,操作结束以后将结果压入事件队列。随后,它通过一个事件循环来逐个取出事件队列中的结果进行处理,处理过程基本上就是去调用该消息对应的回调函数,最后将最终结果返回给主程序。

2.2    模块、包与npm

模块

        每个文件都是它自己的模块,要导入模块使用全局变量的require函数;Node模块允许从被引用文件中选择要暴露给程序的函数和变量,如果模块返回的函数或变量不止一个,那它可以通过设定exports对象的属性来指明它们[8]。其中有两点值得注意:

        第一,require是Node中少数几个同步I/O操作之一,因为经常用到模块,并且一般都是在文件顶端引入,所以把require做成同步的有助于保持代码的整洁、有序,还能增强可读性。但在程序中I/O密集的地方尽量不要用require,所有同步调用都会阻塞Node,直到调用完成才能做其他事情,所以通常都只在程序最初加载时才使用require和其他同步操作。

        第二,不允许重写exports对象,因为在程序里导出的是module.exports,exports只是对module.exports的一个全局引用,最初被定义为一个可以添加属性的空对象,如果把exports设定为别的,就打破了module.exports和exports之间的引用关系。

        在Node.js中,可以通过包来对一组具有相互依赖关系的模块进行统一管理,Node模块打包代码是为了重用,但它们不会改变全局作用域。一个包其实就是一个目录,目录下有一个用于对包进行描述的JSON格式的package.json文件,其中定义了包的名称、版本、依赖和其他信息。

npm

        npm是随同Node.js一起安装的包管理工具,能解决Node.js代码部署上的很多问题,常见的使用场景有以下几种:[9]

        (1)   允许用户从npm服务器下载别人编写的第三方包到本地使用。

        (2)   允许用户从npm服务器下载并安装别人编写的命令行程序到本地使用。

        (3)   允许用户将自己编写

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值