前端工程化:体系设计与实践
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.2 Node.js带给前端的改革

1.2.1 前端的两次新生

Brendan EichBrendan Eich是JavaScript语言的发明者。可能也没有想到JavaScript这门第1版只用了10天便完成设计的脚本语言在今天会如此流行。JavaScript目前不仅可以开发传统的Web站点,而且还跨足了手机App、小程序、物联网等开发领域。JavaScript经历过两次革命性的突破,这两次突破也带给了前端两次新生。

1.第一次新生:AJAX

AJAX技术起步于微软Outlook的XMLHTTP组件,微软将其作为ActiveX组件的一部分加入Internet Explorer 5。随后,其他浏览器厂商,包括Mozilla、Safari、Opera等,实现了一个同样功能的JavaScript对象——XMLHttpRequest。微软是AJAX技术的布道者,Google的进一步推广将其带到了普通民众眼前。人们惊叹于Google地图、Gmail等Web应用程序绝佳的用户体验。Jesse James GarrettJesse James Garrett: https://en.wikipedia.org/wiki/Jesse_James_Garrett。在2005年2月“Ajax: A New Approach to Web Applications”一文中正式提出了“AJAX”一词,并一直沿用至今。随后,W3C在2006年正式发布了XMLHttpRequest规范草案。

AJAX技术可以实现异步请求和局部刷新,彻底改变了传统Web站点的交互模式。Web不仅是供静态展示的网站,而且是一种由浏览器展现、资源寄存于Internet的应用程序。以此为契机,Web开发者开始在AJAX技术的基础之上探索和开发更加丰富的功能和优雅的用户体验。与此同时,用户对Web应用的需求也不断提高,这间接推动了Web技术的发展。

这是AJAX技术带给前端的第一次新生。

2.第二次新生:Node.js

2009年第1版Node.js(只支持Linux和Mac OS X系统)的发布是值得铭记的里程碑。Node.js的作者Ryan Dahl设计Node.js的灵感来自Flickr(一个提供网络图片服务的平台)上的一个上传进度条,浏览器为了能够获取上传文件的进度而不得不频繁地向服务器发起查询请求。与这种方式相比,如果服务器能够在文件上传完毕之后主动推送一条消息给浏览器的话,会节省很多浏览器和网络资源消耗。这种理念便是Node.js实现异步操作的核心Event Loop(事件驱动)的雏形,如图1-2所示。

图1-2

2011年,Node.js发布了支持Windows系统的版本,Node.js在Web开发界进一步流行起来。在此之前的十几年内,JavaScript一直被认为只能在浏览器里耍点小把戏。即便AJAX技术彻底改变了网站的交互模式,JavaScript也仍然未脱离浏览器这个“宿主”。Node.js带来的改革不仅仅是让JavaScript进入了服务器端开发领域,更重要的意义是丰富了JavaScript的生态。JavaScript能做的事情越来越多,业内泛起了JavaScript学习潮,这在一定程度上加速了ECMAScript规范的迭代。

这是Node.js带给前端的第二次新生。

小贴士:随着用户对Web应用的期待越来越高,承载Web应用的浏览器也“被迫”加速了发展,尤其是JavaScript引擎。在AJAX技术问世之前,JavaScript引擎只要能够稳定运行几十行JavaScript代码即可,但是如今Web应用的JavaScript代码已经远远超过这个量级,动辄几百上千行。2008年,Google推出了全新的浏览器Chrome,搭载代号为V8的JavaScript引擎。V8引擎采用实时编译(JIT)技术将JavaScript代码编译为机器码执行,大大提高了JavaScript代码的运行效率。Node.js便是使用V8引擎执行JavaScript代码的。

1.2.2 Node.js带来的改革

Node.js并非一个JavaScript框架,而是一个集成了Google V8 JavaScript引擎、事件驱动和底层I/O API,并且可使用JavaScript语言开发服务器端应用的运行环境。与PHP不同的是,Node.js可以直接提供网络服务,不需要借助Apache、Nginx等专业的服务器软件。虽然并不建议在生产环境下直接将Node.js服务暴露给用户,但是Node.js这种特性可以让我们更方便地开发各种工具,比如将在后续章节中讲解的前端工程化方案中本地服务器的搭建。

1.服务器端开发

Node.js作为服务器端平台已经逐步被国内外公司和团队接纳。2015年10月,著名的开源博客系统WordPress发布了使用Node.js重写的4.3版本。许多企业(国内的,比如阿里巴巴、美团等;国外的,比如IBM、LinkedIn、GoDaddy等)对Node.js也均有不同程度的使用。虽然Node.js尚未威胁到PHP、Java等传统Web服务器端语言的地位,但Node.js的事件驱动和异步I/O机制,以及其易学习、易部署和对前端工程师天然的语言共通性,让其成为实时应用、微服务以及前端工程化等应用场景的最佳技术选型之一。

2.同构JavaScript

Node.js在使用JavaScript语言开发Web服务器端平台的同时,还提高了同构JavaScript开发的可行性。

同构(isomorphism)一词是数学领域的专业术语,指的是数学对象之间属性或者操作关系的一类映射。数学中研究同构的主要目的是为了把数学知识应用于更多不同的领域,同理,在JavaScript开发领域研究同构的主要目的也是为了将这门编程语言应用于不同的开发领域。同构JavaScript的概念最早由Airbnb工程师Spike Brehm提出,简单讲就是令JavaScript编写的代码既可以在浏览器端工作,也可以在服务器端工作,如图1-3所示。这意味着服务器端和浏览器端都可以承载网页的渲染工作。

图1-3

传统网站的渲染流程是由浏览器主动发起请求,然后服务器端生成HTML文档后发送响应给浏览器,浏览器接到响应后将HTML文档渲染为可视网页。这是自浏览器发明以来就沿用至今的渲染流程。这种工作模式的优点是节省客户端资源,在客户终端设备以及浏览器性能普遍比较落后的情况下能够保证良好的渲染效果,并且服务器端渲染的网页更利于SEO(Search Engine Optimization,搜索引擎优化)。而其缺点是每访问一个页面都要发起请求,每个请求都需要服务器进行路由匹配、数据库查询、生成HTML文档后再发送响应给浏览器,这个过程会消耗服务器的大量计算资源,如图1-4所示。

图1-4

随着个人终端设备和浏览器性能的不断提升,Web开发者尝试将渲染以及路由工作交给客户端,服务器端RESTFul API只提供渲染HTML所需的JSON数据。这种形态的Web应用被称为SPA(Single Page Application,单页应用)。SPA有以下优点。

 

·减轻了服务器的资源消耗。

·与HTML文档比起来,JSON数据的体积小很多,减少了网络请求的时间消耗。

·页面路由控制更快速灵活。

·可以离线使用。

 

同时SPA也带来了新问题。首先,浏览器需要等待JavaScript文件加载完成之后才可以渲染后续的HTML文档内容,用户在等待的过程中页面是空白的,这就是我们在进行Web产品性能评估时经常谈到的“白屏时间”;其次,由于客户端和服务器端编程语言不同,可能会存在一些诸如数据格式的差异,甚至路由逻辑冲突,比如vue-router history模式的路由,这些问题增加了维护难度;最后,SPA不利于常规的SEO(搜索引擎优化)爬虫(之所以说常规是因为Google已经针对SPA进行了SEO优化,但是目前国内的搜索引擎对SPA的支持并不理想)。

与传统的服务器端渲染模式和客户端渲染的单页应用相比,同构JavaScript拥有更好的性能、可维护性以及对SEO更好的支持。同构JavaScript的理念类似于Java秉承的“Write once, run anywhere”, JavaScript除命名以外终于又跟Java扯上了关系。Node.js是实现同构JavaScript开发的关键。一方面,JavaScript在浏览器环境下可以执行渲染工作;另一方面,Node.js运行环境下同样可以使用JavaScript创建HTML字符串。在这个前提下,JavaScript开发生态中浮现了一大批支持同构开发的框架和库,比如Facebook推出的React.js和国内的Vue.js。

3.前端工具

除了服务器端开发外,Node.js对前端最大的贡献是丰富了前端工具生态。在Node.js出现以前,没有Grunt、Gulp、webpack等便捷且强大的工具,压缩合并JavaScript、CSS代码对于前端工程师来说是一项非常艰难的任务。前端工程师不得不使用不熟悉的语言、工具来处理静态文件的压缩合并。而这些工具往往并不是为了处理静态文件的,比如Apache Ant。使用Ant处理静态文件可以说是杀鸡用了牛刀,而且这把牛刀用来杀鸡还并不好使。除此之外,也可以使用shell脚本完成这项工作,但对于并不擅长编写shell脚本的前端工程师来说学习成本和时间成本太高,往往要麻烦团队中的服务器端工程师代写。不论哪种选择,都会对项目的开发进度产生影响。

Node.js的出现彻底解决了这些问题。目前耳熟能详的前端工具,比如Grunt、Gulp、webpack,无一不是由Node.js承载的。结合JavaScript的灵活性与Node.js提供的API,前端工程师可以编写各种工具满足项目的开发需求。本书所介绍的前端工程化解决方案中的各个功能模块全部是由JavaScript语言实现的。