Node.js开发指南 我们从Node.js的版本号大飞跃谈起
沉沙 2018-07-19 来源 : 阅读 493 评论 0

摘要:Node.js是为异步而生的,它自己把复杂的事儿做了(高并发,低延时),交给用户的只是有点难用的Callback写法。也正是坦诚的将异步回调暴露出来,才有更好的流程控制方面的演进。也正是这些演进,让Node.js从DIRT(数据敏感实时应用)扩展到更多的应用场景,今天的Node.js已经不只是能写后端的JavaScript,已经涵盖了所有涉及到开发的各个方面,而Node全栈更是热门种的热门。

版本帝?

Chrome浏览器已经蹦到57版本了,是名副其实的版本帝,作为兄弟的Node.js也一样,1.0之前等了6年,而从1.0到8.0,只用了2年时间,这世界到底怎么了?

我们就数一下

· 从v0.1到0.12用了6年

· 2015-01-14发布了v1.0.0版本(io.js)

· 2.x(io.js)

· 3.x(io.js)

· 2015年09月Node.js基金会已发布Node.js V4.0版 与io.js合并后的第一个版本

· 2015年10月Node.jsv4.2.0将是首个lts长期支持版本

· 2016年底发布到4.2.4 && 5.4.0

· 2016年3月20日v4.4.0 LTS(长期支持版本)和v5.9.0 Stable(稳定版本)

· 2016 年底 v6.0 支持95%以上的es6特性 , v7.0通过flag支持async函数,99%的es6特性

· 2017年2月发布v7.6版本,可以不通过flag使用async函数

 

整体来说趋于稳定

· 成立了Node.js基金会,能够让Node.js在未来有更好的开源社区支持

· 发布了LTS版本,意味着api稳定

· 快速发版本,很多人吐槽这个,其实换个角度看,这也是社区活跃的一个体现,但如果大家真的看CHANGELOG,其实都是小改进,而且是边边角角的改进,也就是说Node.js的core(核心)已经非常稳定了,可以大规模使用

已无性能优势?

Node.js在2009年横空出世,可以说是纯异步获得高性能的功劳。所有语言几乎没有能够和它相比的,比如Java、PHP、Ruby都被啪啪的打脸。但是山一程,水一程,福祸相依,因为性能太出众,导致很多语言、编程模型上有更多探索,比如go语言产生、php里的swolo和vm改进等,大家似乎都以不支持异步为耻辱。后来的故事大家都知道了,性能都提到非常高,c10问题已经没人再考虑,只是大家实现早晚而产生的性能差距而已。

编程语言的性能趋于一样的极限,所以剩下的选择,只有喜好

那么在这种情况下,Node.js还有优势么?

· 实现成本:Node.js除了异步流程控制稍复杂外,其他的都非常简单,比如写法,你可以面向过程、面向对象、函数式,根据自己的解决选择就好了。不要因为它现在变化快,就觉得自己跟不上潮流。尤其是后端程序员转Node.js几乎是2周以内的成本,某些语言光熟悉语法习惯也不止2周吧?

· 调优成本:Node.js即使不优化,它的性能也非常好,如果优化,也比其他语言更简单

· 学习成本:是否必须用,如果是必须要用,那就少学一样是一样,人生有限,不能都花在写hello world上。我想问,大前端离得开js么?

误读:Node.js已无性能优势,它现在最强大的是基于npm的生态

上面是成本上的比较,其实大家把关注点都转移到基于npm的生态上,截止2017年2月,在npm上有超过45万个模块,秒杀无数。npm是所有的开源的包管理里最强大的,我们说更了不起的Node.js,其实npm居功甚伟,后面会有独立的章节进行阐述。

来自www.modulecounts.com的各个包管理模块梳理的比较

 

npm生态是Node的优势不假,可是说“Node.js没有性能优势”真的对么?这其实就是误读,Node.js的性能依然很好呀,而且它有npm极其强大的生态,可谓性能与生态双剑合璧,你说你死不死?

异步和回调地狱?

天生异步,败也异步,成也异步

正因为异步导致了api设计方式只能采用error-first风格的回调,于是大家硬生生的把callback写成了callback hell。于是各种黑粉就冒出来,无非是一些浅尝辄止之辈。但也正因为回调地狱是最差实践,所以大家才不得不求变,于是thunk、promise等纷沓而至。虽然Promise/A+不完美,但对于解决回调地狱是足够的了。而且随着ES6等规范实现,引入generator、co等,让异步越来越近于同步。当async函数落地的时候,Node已经站在了同C#、Python一样的高度上,大家还有什么理由黑呢?


应用场景

MEAN是一个Javascript平台的现代Web开发框架总称,它是MongoDB + Express +AngularJS + NodeJS 四个框架的第一个字母组合。它与传统LAMP一样是一种全套开发工具的简称。在2014和2015年喜欢讲这个,并且还有MEAN.js等框架,但今天已经过时,Node.js有了更多的应用场景。

《Node.js in action》一书里说,Node所针对的应用程序有一个专门的简称:DIRT。它表示数据密集型实时(data-intensive real-time)程序。因为Node自身在I/O上非常轻量,它善于将数据从一个管道混排或代理到另一个管道上,这能在处理大量请求时持有很多开放的连接,并且只占用一小部分内存。它的设计目标是保证响应能力,跟浏览器一样。

这话不假,但在今天来看,DIRT还是范围小了。其实DIRT本质上说的I/O处理的都算,但随着大前端的发展,Node.js已经不再只是I/O处理相关,而是更加的“Node”!

这里给出Node.js的若干使用场景

· 网站(如express/koa等)

· im即时聊天(socket.io)

· api(移动端,pc,h5)

· HTTP Proxy(淘宝、Qunar、腾讯、百度都有)

· 前端构建工具(grunt/gulp/bower/webpack/fis3…)

· 写操作系统(NodeOS)

· 跨平台打包工具(PC端的electron、nw.js,比如钉钉PC客户端、微信小程序IDE、微信客户端,移动的cordova,即老的Phonegap,还有更加有名的一站式开发框架ionicframework)

· 命令行工具(比如cordova、shell.js)

· 反向代理(比如anyproxy,node-http-proxy)

· 编辑器Atom、VSCode等

可以说目前大家能够看到的、用到的软件都有Node.js身影,当下最流行的软件写法也大都是基于Node.js的,比如PC客户端luin/medis采用electron打包,写法采用React+Redux。我自己一直的实践的【Node全栈】,也正是基于这种趋势而形成的。在未来,Node.js的应用场景会更加的广泛。更多参见sindresorhus/awesome-nodejs。

Web框架

演进时间线大致如下:

· 2010年tj写的Express

· 2011年Derby.js开始开发,8月5日,WalmartLabs的一位成员Eran Hammer提交了Hapi的第一次commit。Hapi原本是Postmile的一部分,并且最开始是基于Express构建的。后来它发展成自己自己的框架,

· 2012年1月21日,专注于rest api的restify发布1.0版本,同构的meteor开始投入开发,最像rails的sails也开始了开发

· 2013年tj开始玩generator,编写co这个generator执行器,并开始了Koa。2013 年下半年李成银开始ThinkJS,参考ThinkPHP

· 2014年,4月9日,express发布4.0,进入4.x时代持续到今天,MEAN.js开始随着MEAN架构的提出开始开发,意图大一统,另外total.js开始,最像PHP’s Laravel 或 Python’s Django 或 ASP.NET MVC的框架

· 2015年8月22日, 下一代Web框架Koa发布1.0,可以在node 0.12下面,通过co + generator实现同步逻辑,那时候co还是基于thunkfy的,2015.10.30 ThinkJS发布了Es2015+ 特性开发的v 2.0版本

· 2016 年 09 月,蚂蚁金服的eggjs,在 JSConf China 2016 上亮相并宣布开源

· 2017年2月,下一代Web框架Koa发布2.0


对于框架选型

· 业务场景、特点,不必为了什么而什么,避免本末倒置

· 自身团队能力、喜好,有时候技术选型决定团队氛围的,需要平衡激进与稳定

· 出现问题的时候,有人能Cover的住,Node.js虽然8年历史,但模块完善程度良莠不齐,如果不慎踩到一个坑里,需要团队在无外力的情况能够搞定,否则会影响进度

个人学习求新,企业架构求稳,无非喜好与场景而已

我猜大家能够想到的场景,大约如下

· 前端工具,比如gulp、grunt、webpack等

· 服务器,做类似于Java、PHP的事儿

如果只是做这些,和Java、PHP等就没啥区别了。如果再冠上更了不起的Node.js,就有点名不符实了。所以这里我稍加整理,看看和大家想的是否一样

技术栈演进

自从ES 2015(俗称ES 6)在Node.js 落地之后,整个Node.js开发都发生了翻天覆地的变化。自从0.10开始,Node.js就逐渐的加入了ES 6特性,比如0.12就可以使用generator,才导致寻求异步流程控制的tj写出了co这个著名的模块,继而诞生了Koa框架。但是在4.0之前,一直都是要通过flag才能开启generator支持,故而Koa 1.0迟迟未发布,在Node 4.0发布才发布的Koa 1.0。

2015年,成熟的传统,而2016年,变革开始

核心变更:es语法支持

· 使用Node.js 4.x或5.x里的es6特性,如果想玩更高级的,可以使用babel编译支持es7特性,或者typescript

· 合理使用standard 或者 xo 代码风格约定

· 适当的引入ES 6语法,只要Node.js SDK支持的,都可以使用

· 需要大家重视OO(面向对象)写法的学习和使用,虽然ES 6的OO机制不健全,但这是大方向,以后会一直增强。OO对于大型软件开发更好。这其实也是我看好typescript的原因。

  

预处理器

前端预处理可分3种

· 模板引擎

· css预处理器

· js友好语言

这些都离不开Node.js的支持,对于前端工程师来说,使用Node.js来实现这些是最方便不过的。

  

跨平台

跨平台指的是PC端、移动端、Web/H5

 

构建工具

说起构建工具,大概会想到make、ant、rake、gradle等,其实Node.js里有更多实现


构建工具都不会特别复杂,所以Node.js世界里有非常多的实现,还有人写过node版本的make呢,玩的很嗨

HTTP Proxy

· 请求代理

· SSR && PWA

· Api Proxy

1)请求代理

对于http请求复杂定制的时候,你是需要让Node.js来帮你的,比如为了兼容一个历史遗留需求,在访问某个CSS的时候必须提供HEADER才可以,如果放到静态server或cdn上是做不到的。

2)SSR && PWA

SSR是服务器端渲染,PWA是渐进式Web应用,都是今年最火的技术。如果大家用过,一定对Node.js不陌生。比如React、Vuejs都是Node.js实现的ssr。至于pwa的service-worker也是Node.js实现的。那么为啥不用其他语言实现呢?不是其他语言不能实现,而是使用Node.js简单、方便、学习成本低,轻松获得高性能,如果用其他语言,我至少还得装环境

3)Api Proxy

产品需要应变,后端不好变,一变就要设计到数据库、存储等,可能引发事故。而在前端相对更容易,前端只负责组装服务,而非真正对数据库进行变动,所以只要服务api粒度合适,在前端来处理是更好的。

Api的问题

· 一个页面的Api非常多

· 跨域,Api转发

· Api返回的数据对前端不友好,后端讨厌(应付)前端,几种api都懒得根据ui/ue去定制,能偷懒就偷懒

· 需求决定Api,Api不一定给的及时

所以,在前端渲染之余,加一层Api Proxy是非常必要的。淘宝早起曾公开过一张架构图,在今天看来,依然不过时

 

· 左侧半边,浏览器和Node.js Server通信可以有多种协议,HTML、RESTfull、BigPipe、Comet、Socket等,已经足够我们完成任何想做的事儿了

· 右侧半边,是Node.js实现的WebServer,Node服务分了2个部分

· 常规的Http服务,即大块部分二

· ModelProxy指的是根据Server端的服务,组成并转化成自身的Model层。磨蹭用于为Http服务提供更好的接口

这里的Model Proxy其实就是我们所说的Api Proxy,这张图里只是说了结果,把聚合的服务转成模型,继而为HTTP服务提供Api。

下面我们再深化一下Api Proxy的概念

 

这里的Node Proxy做了2件事儿,Api和渲染辅助。

· 前端的异步ajax请求,可以直接访问Api

· 如果是直接渲染或者bigpipe等协议的,需要在服务器端组装api,然后再返回给浏览器。

所以Api后面还有一个服务组装,在微服务架构流行的今天,这种服务组装放到Node Proxy里的好处尤其明显。既可以提高前端开发效率,又可以让后端更加专注于服务开发。甚至如果前端团队足够大,可以在前端建一个Api小组,专门做服务集成的事儿。

说完了Proxy,我们再看看利益问题。Node.js向后端延伸,必然会触动后端开发的利益。那么Proxy层的事儿,前后端矛盾的交界处,后端不想变,前端又求变,那么长此以往,Api接口会变得越来越恶心。后端是愿意把Api的事儿叫前端的,对后端来说,只要你不动我的数据库和服务就可以。

但是Node.js能不能做这部分呢?答案是能的 ,这个是和Java、PHP类似的,一般是和数据库连接到一起,处理带有业务逻辑的。目前国内大部分都是以Java、PHP等为主,所以要想吃到这部分并不容易。

· 小公司,创业公司,新孵化的项目更倾向于Node.js,简单,快速,高效

· 微服务架构下的某些服务,使用Node.js开发,是比较合理的

国内这部分一直没有做的很好,所以Node.js在大公司还没有很好的被应用,安全问题、生态问题、历史遗留问题等,还有很多人对Node.js的误解

· 单线程很脆弱,这是事实,但单线程不等于不能多核并发,而且你还有集群呢

· 运维,其实很简单,比其他语言之简单,日志采集、监控也非常简单

· 模块稳定性,对于Mongodb、MySQL、Redis等还是相当不错,但其他的数据库支持可能没那么好。

· 安全问题,

这些对于提供Api服务来说已经足够了。

  

更好的写法

Async函数与Promise

· Async函数是趋势,Chrome 52. v8 5.1已经支持Async函数(https://github.com/nodejs/CTC/issues/7)了,Node.js 7.0+支持还会远么?

· Async和Generator函数里都支持promise,所以promise是必须会的。

· Generator和yield异常强大,不过不会成为主流,所以学会基本用法和promise就好了,没必要所有的都必须会。

· co作为Generator执行器是不错的,它更好的是当做Promise 包装器,通过Generator支持yieldable,最后返回Promise,是不是有点无耻?

我整理了一张图,更直观一些。

 

· 红色代表Promise,是使用最多的,无论async还是generator都可用

· 蓝色是Generator,过度货

· 绿色是Async函数,趋势

结论:Promise是必须会的,那你为什么不顺势而为呢?

推荐:使用Async函数 + Promise组合,如下图所示。

 

实践

合理的结合Promise和Async函数是可以非常高效的,但也要因场景而异

· Promise更容易做promisefyAll(比如使用bluebird)

· Async函数无法批量操作

那么,在常见的Web应用里,我们总结的实践是,dao层使用Promise比较好,而service层,使用Async/Await更好。

dao层使用Promise:

· crud

· 单一模型的方法多

· 库自身支持Promise

这种用promisefyAll基本几行代码就够了,一般单一模型的操作,不会特别复杂,应变的需求基本不大。

而service层一般是多个Model组合操作,多模型操作就可以拆分成多个小的操作,然后使用Await来组合,看起来会更加清晰,另外对需求应变也是非常容易的。

ES.next

Node.js + ES.next = ♥

Flow && TypeScript

Type Systems Will Make You a Better JavaScript Developer

ES6模块

现在ES6自带了模块标准, 也是JS第一次支持module(之前的CommonJS、AMD、CMD都不算), 但目前的所有Node.js版本都没有支持,目前只能用用Traceur、BabelJS, 或者TypeScript把ES6代码转化为兼容ES5版本的js代码,ES6模块新特性非常吸引人,下面简要说明。

ES6 模块的目标是创建一个同时兼容CommonJS和AMD的格式,语法更加紧凑,通过编译时加载,使得编译时就能确定模块的依赖关系,效率要比 CommonJS 模块的加载方式高。而对于异步加载和配置模块加载方面,则借鉴AMD规范,其效率、灵活程度都远远好于CommonJS写法。

· 语法更紧凑

· 结构更适于静态编译(比如静态类型检查,优化等)

· 对于循环引用支持更好

ES6 模块标准只有2部分,它的用法更简单,你根本不需要关注实现细节:

· 声明式语法:模块导入import、导出export,没有require了

· 程式化加载API:可以配置模块是如何加载,以及按需加载。

多模块管理器:Lerna

A tool for managing JavaScript projects with multiple packages.

https://lernajs.io/

在设计框架的时候,经常做的事儿是进行模块拆分,继而提供插件或集成机制,这样是非常好的做法。但问题也随之而来,当你的模块模块非常多时,你该如何管理你的模块呢?

· 法1:每个模块都建立独立的仓库

· 法2:所有模块都放到1个仓库里

法1虽然看起来干净,但模块多时,依赖安装,不同版本兼容等,会导致模块间依赖混乱,出现非常多的重复依赖,极其容易造成版本问题。这时法2就显得更加有效,对于测试,代码管理,发布等,都可以做到更好的支持。

Lerna就是基于这种初衷而产生的专门用于管理Node.js多模块的工具,当然,前提是你有很多模块需要管理。

你可以通过npm全局模块来安装Lerna,官方推荐直接使用Lerna 2.x版本

更好的NPM替代品:Yarn

Yarn是开源JavaScript包管理器,由于npm在扩展内部使用时遇到了大小、性能和安全等问题,Facebook携手来自Exponent、Google和Tilde的工程师,在大型JavaScript框架上打造和测试了Yarn,以便其尽可能适用于多人开发。Yarn承诺比各大流行npm包的安装更可靠,且速度更快。根据你所选的工作包的不同,Yarn可以将安装时间从数分钟减少至几秒钟。Yarn还兼容npm注册表,但包安装方法有所区别。其使用了lockfiles和一个决定性安装算法,能够为参与一个项目的所有用户维持相同的节点模块(node_modules)目录结构,有助于减少难以追踪的bug和在多台机器上复制。

Yarn还致力于让安装更快速可靠,支持缓存下载的每一个包和并行操作,允许在没有互联网连接的情况下安装(如果此前有安装过的话)。此外,Yarn承诺同时兼容npm和Bower工作流,让你限制安装模块的授权许可。

2016年10月份, Yarn在横空出世不到一周的时间里,github上的star数已经过万,可以看出大厂及社区的活跃度,以及解决问题的诚意,大概无出其右了!

替换的原因

· 在Facebook的大规模 npm 都工作的不太好

· npm拖慢了公司的ci工作流

· 对一个检查所有的模块也是相当低效的

· npm被设计为是不确定性的,而Facebook工程师需要为他们的DevOps工作流提供一直和可依赖的系统

与hack npm限制的做法相反,Facebook编写了Yarn

· Yarn 的本地缓存文件做的更好

· Yarn 可以并行它的一些操作,这加速了对新模块的安装处理

· Yarn 使用lockfiles,并用确定的算法来创建一个所有跨机器上都一样的文件

· 出于安全考虑,在安装进程里,Yarn 不允许编写包的开发者去执行其他代码

Yarn, which promises to even give developers that don’t work at Facebook’s scale a major performance boost, still uses the npm registry and is essentially a drop-in replacement for the npm client.

很多人说和ruby的gem机制类似,都生成lockfile。确实是一个很不错的改进,在速度上有很大改进,配置cnpm等国内源来用,还是相当爽的。

友好语言

· 过气的Coffeescript,不多说

· Babel – also an ES6 to ES5 transpiler that’s growing in popularity possibly because it also supports React’s JSX syntax. As of today it supports the most ES6 features at a somewhat respectable 73%.

· TypeScript – a typed superset of JavaScript that not only compiles ES6 to ES5 (or even ES3) but also supports optional variable typing. TypeScript only supports 53% of ES6 features.

总结

坦诚的力量是无穷的

Node.js是为异步而生的,它自己把复杂的事儿做了(高并发,低延时),交给用户的只是有点难用的Callback写法。也正是坦诚的将异步回调暴露出来,才有更好的流程控制方面的演进。也正是这些演进,让Node.js从DIRT(数据敏感实时应用)扩展到更多的应用场景,今天的Node.js已经不只是能写后端的JavaScript,已经涵盖了所有涉及到开发的各个方面,而Node全栈更是热门种的热门。

直面问题才能有更好的解决方式,Node.js你值得拥有!

 

本文由职坐标整理发布,学习更多的Node.js相关知识,请关注职坐标WEB前端Node.js频道!

本文由 @沉沙 发布于职坐标。未经许可,禁止转载。
喜欢 | 0 不喜欢 | 0
看完这篇文章有何感觉?已经有0人表态,0%的人喜欢 快给朋友分享吧~
评论(0)
后参与评论

您输入的评论内容中包含违禁敏感词

我知道了

助您圆梦职场 匹配合适岗位
验证码手机号,获得海同独家IT培训资料
选择就业方向:
人工智能物联网
大数据开发/分析
人工智能Python
Java全栈开发
WEB前端+H5

请输入正确的手机号码

请输入正确的验证码

获取验证码

您今天的短信下发次数太多了,明天再试试吧!

提交

我们会在第一时间安排职业规划师联系您!

您也可以联系我们的职业规划师咨询:

小职老师的微信号:z_zhizuobiao
小职老师的微信号:z_zhizuobiao

版权所有 职坐标-一站式IT培训就业服务领导者 沪ICP备13042190号-4
上海海同信息科技有限公司 Copyright ©2015 www.zhizuobiao.com,All Rights Reserved.
 沪公网安备 31011502005948号    

©2015 www.zhizuobiao.com All Rights Reserved

208小时内训课程