[全文]如何正确学习Node.js
《狼书(卷1):更了不起的Node.js》Node.js》 已出版,和本文内容类似,但更深入。
《狼书(卷2):Node.js Web应用开发》 《狼书(卷3):Node.js高级技术》,预计10月之前出版。
预览地址 https://i5ting.github.io/How-to-learn-node-correctly/
Live 简介
你好,我是 i5ting ,江湖人称「狼叔」,目前是阿里巴巴技术专家,斯达克学院( StuQ )明星讲师, Node.js 技术布道者。曾就职于去哪儿、新浪、网秦,做过前端、后端、数据分析,是一名全栈技术的实践者。
现在,越来越多的科技公司和开发者开始使用 Node.js 开发各种应用。Node.js除了能够辅助大前端开发外,还可以编写Web应用,封装Api,组装RPC服务等,甚至是开发VSCode编辑器一样的PC客户端。和其它技术相比, Node.js 简单易学,性能好、部署容易,能够轻松处理高并发场景下的大量服务器请求。Node.js 周边的生态也非常强大,NPM(Node包管理)上有超过60万个模块,日下载量超过3亿次。但编写 Node.js 代码对新人和其它语言背景的开发者来说,不是一件容易的事,在入门之前需要弄懂不少复杂的概念。
我身边也有很多人问我:如何学习 Node.js ?作为一名 Node.js 布道者,我做过很多 Node.js 普及和推广的工作,对它的基本概念和核心模块都很熟悉; 此外,我还在撰写一本名为《更了不起的 Node.js》的书,已经写了 2 年,积累了很丰富的资料,本次 Live 也将为你提供对 Node.js 更全面的解读。
本次 Live 主要包括以下内容,目录
Part 0 :Node.js简介
a)Node.js简介 b)什么是Node.js? c)基本原理
Part 1前言:学习 Node.js 的三个境界
Part 2准备:如何学习Node.js
Part 3延伸:大前端变化那么快,如何才能做到每日精进?
Part 4实践:从招聘角度来看, Node.js 开发需要具备哪些技能?
Part 5答疑:回答大家的问题
本次Live主要是科普,适用于新用户和对Node比较迷茫的朋友,希望大家多多理解和支持。
a)Node.js简介 b)什么是Node.js? c)基本原理
Node.js 诞生于 2009 年,由 Joyent 的员工 Ryan Dahl 开发而成,之后 Joyent 公司一直扮演着 Node.js 孵化者的角色。由于诸多原因,Ryan 在2012年离开社区,随后在2015年由于 Node 贡献者对 es6 新特性集成问题的分歧,导致分裂出iojs,并由 iojs 发布1.0、2.0和3.0版本。由于 iojs 的分裂最终促成了2015年Node基金会的成立,并顺利发布了4.0版本。Node.js基金会的创始成员包括 Google、Joyent、IBM、Paypal、微软、Fidelity 和 Linux基金会,创始成员将共同掌管过去由 Joyent 一家企业掌控的 Node.js 开源项目。此后,Node.js基金会发展非常好,稳定地发布5、6、7、8等版本,截止发稿最新版本已经是8.6,长期支持版本是6.11。
Node.js 不是一门语言也不是框架,它只是基于 Google V8 引擎的 JavaScript 运行时环境,同时结合 Libuv 扩展了 JavaScript 功能,使之支持 io、fs 等只有语言才有的特性,使得 JavaScript 能够同时具有 DOM 操作(浏览器)和 I/O、文件读写、操作数据库(服务器端)等能力,是目前最简单的全栈式语言。
早在2007年,Jeff Atwood 就提出了著名的 Atwood定律
任何能够用 JavaScript 实现的应用系统,最终都必将用 JavaScript 实现
目前 Node.js 在大部分领域都占有一席之地,尤其是 I/O 密集型的,比如 Web 开发,微服务,前端构建等。不少大型网站都是使用 Node.js 作为后台开发语言的,用的最多的就是使用Node.js做前端渲染和架构优化,比如 淘宝 双十一、去哪儿网 的 PC 端核心业务等。另外,有不少知名的前端库也是使用 Node.js 开发的,比如,Webpack 是一个强大的打包器,React/Vue 是成熟的前端组件化框架。
Node.js通常被用来开发低延迟的网络应用,也就是那些需要在服务器端环境和前端实时收集和交换数据的应用(API、即时聊天、微服务)。阿里巴巴、腾讯、Qunar、百度、PayPal、道琼斯、沃尔玛和 LinkedIn 都采用了 Node.js 框架搭建应用。
另外, Node.js 编写的包管理器 npm 已成为开源包管理领域最好的生态,截止到2017年10月份,有超过47万模块,每周下载量超过32亿次,每个月有超过700万开发者使用npm。
当然了,Node.js 也有一些缺点。Node.js 经常被人们吐槽的一点就是:回调太多难于控制(俗称回调地狱)和 CPU 密集任务处理地不是很好。但是,目前异步流程技术已经取得了非常不错的进步,从Callback、Promise 到 Async函数,可以轻松地满足所有开发需求。至于 CPU 密集任务处理并非不可解,方案有很多,比如通过系统底层语言 Rust 来扩展 Node.js,但这样会比较麻烦。笔者坚信在合适的场景使用合适的东西,尤其是在微服务架构下,一切都是服务,可以做到语言无关。如果大家想使用 JavaScript 做 CPU 密集任务,推荐 Node.js 的兄弟项目 fibjs,基于纤程(fiber,可以简单理解为更轻量级的线程),效率非常高,兼容npm,同时没有异步回调烦恼。
按照 Node.js官方网站主页 的说法:
Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine. Node.js uses an event-driven, non-blocking I/O model that makes it lightweight and efficient. Node.js' package ecosystem, npm, is the largest ecosystem of open source libraries in the world.
从这段介绍来看,解读要点如下
npm 作为包管理器,目前 npm 是开源库里包管理最大的生态,功能强大,截止到2017年12月,模块数量超过 60 万+大多数人都认为 Node.js 只能写网站后台或者前端工具,这其实是不全面的,Node.js的目标是让并发编程更简单,主要应用在以网络编程为主的 I/O 密集型应用。它是开源的,跨平台,并且高效(尤其是I/O处理),包括IBM、Microsoft、Yahoo、SAP、PayPal、沃尔玛及GoDaddy都是 Node.js 的用户。
下面是一张 Node.js 早期的架构图,来自 Node.js 之父 Ryan Dahl 的演讲稿,在今天依然不过时,它简要的介绍了 Node.js 是基于 Chrome V8引擎构建的,由事件循环(Event Loop)分发 I/O 任务,最终工作线程(Work Thread)将任务丢到线程池(Thread Pool)里去执行,而事件循环只要等待执行结果就可以了。
核心概念
Chrome 浏览器中被使用。Chrome V8 引擎可以独立运行,也可以用来嵌入到 C/C++ 应用程序中执行。libuv 提供)libuv 提供)梳理一下
我们再换一个维度看一下
核心
libuv 由事件循环和线程池组成,负责所有 I/O 任务的分发与执行在解决并发问题上,异步是最好的解决方案,可以拿排队和叫号机来理解
Node.js 其实就是帮我们构建类似的机制。我们在写代码的时候,实际上就是取号的过程,由 Event Loop 来接受处理,而真正执行操作的是具体的线程池里的 I/O 任务。之所以说 Node.js 是单线程,就是因为在接受任务的时候是单线程的,它无需进程/线程切换上下文的成本,非常高效,但它在执行具体任务的时候是多线程的。
Node.js 公开宣称的目标是 “旨在提供一种简单的构建可伸缩网络程序的方法”,毫无疑问,它确实做到了。这种做法将并发编程模型简化了,Event Loop和具体线程池等细节被 Node.js 封装了,继而将异步调用 Api 写法暴露给开发者。真是福祸相依,一方面简化了并发编程,另一方面在写法上埋下了祸根,这种做法的好处是能让更多人轻而易举地写出高性能的程序!
在Node.js Bindings层做的事儿就是将 Chrome V8 等暴露的 C/C++ 接口转成JavaScript Api,并且结合这些 Api 编写了 Node.js 标准库,所有这些 Api 统称为 Node.js SDK,后面模块章节会有更详细的讨论。
微软在2016年宣布在MIT许可协议下开放 Chakra 引擎,并以 ChakraCore 为名在 Github 上开放了源代码,ChakraCore 是一个完整的 JavaScript 虚拟机,它拥有着和 Chakra 几乎相同的功能与特性。微软向 Node.js 主分支提交代码合并请求,让 Node.js 用上 ChakraCore引擎,即 nodejs/node-chakracore 项目。实际上微软是通过创建名为 V8 shim 的库的赋予了 ChakraCore 处理谷歌 Chrome V8 引擎指令的能力,其原理示意图如下
目前,Node.js 同时支持这2种 JavaScript 引擎,二者性能和特性上各有千秋,ChakraCore 在特性上感觉更潮一些,曾经是第一个支持 Async函数 的引擎,但目前 Node.js 还是以 Chrome V8 引擎为主, ChakraCore 版本需要单独安装,大家了解一下就好。
我总结的编程3种境界
大家可以自测一下,自己在哪个水平?如果是第三个阶段,那么本场Live可能不太适合你。哈哈哈
Node不是语言,不是框架,只是基于V8运行时环境。结合libuv能够通过js语法获得更好的等价于c/c++的性能。
它很简单,异步是解决并发的最佳实践。本节主要讲如何学习Node.js,是本次Live非常核心的内容,大家要注意听。
1)js语法必须会
犀牛书,《JavaScript权威指南》,没事就多翻翻,看多少遍都不为过。
2)个人学习和技术选型都要循序渐进
可以看出我的思路,先能写,然后再追求更好的写法,比如面向对象。等团队水平到一定程度了,并且稳定的时候,可以考虑更加极致的函数式写法。
团队是这样选型的,个人学习也这样,最好是循序渐进,步子迈大了不好。
3)各种高级的JavaScript友好语言
JavaScript友好语言指的是能够使用其他语法实现,但最终编译成js的语言。自从Node.js出现后,这种黑科技层出不穷。比如比较有名的coffee、typescript、babel(es)等。
CoffeeScript虽然也是JavaScript友好语言,但其语法借鉴ruby,崇尚极简,对于类型和OO机制上还是偏弱,而且这么多年也没发展起来,仍然是比较小众的活着。未来比例会越来越少的。
显然TypeScript会越来越好,TypeScript 的强大之处是要用过才知道的。
当下前端发展速度极快,以指数级的曲线增长。以前可能1年都不一定有一项新技术,现在可能每个月都有。大前端,Node全栈,架构演进等等都在快速变化。可以说,前端越复杂,有越多的不确定性,TypeScript的机会就越大。
4)再论面向对象
面向对象想用好也不容易的,而且js里有各种实现,真是让人眼花缭乱。
对于es6高级特性,我是比较保守的,一般node长期支持版本lts支持的我都让用,一些更新的特性我一般不让使用。根本lts版本保持一致就好。
我的团队现在是采用es6的面向对象写法开发,后面会一点一点转到typescript上的。熟练oo转到ts是非常容易的。
3m安装法
node版本发布非常快,而且多版本共存可能性较大,推荐使用nvm来安装node
$ curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.6/install.sh | bash
$ echo 'export NVM_DIR="$HOME/.nvm"' >> ~/.zshrc
$ echo '[ -s "$NVM_DIR/nvm.sh" ] && . "$NVM_DIR/nvm.sh" # This loads nvm' >> ~/.zshrc
$ source ~/.zshrc
$ nvm install 0.10
$ nvm install 4
$ nvm install 6
$ nvm install 8
https://registry.npmjs.com 是node官方的源(registry),服务器在国外,下载速度较慢,推荐安装nrm来切换源,国内的cnpm和taobao的源都非常快,当然,如果你想自建源也是支持的。
$ npm install --global nrm --registry=https://registry.npm.taobao.org
$ nrm use cnpm
nrm切换完源之后,你安装npm模块的速度会更快。
$ npm install --global yarn
npm基本命令
| 名称 | 描述 | 简写 |
|---|---|---|
| npm install xxx | 安装xxx模块,并且记录到package.json里,字段对应的dependency,是产品环境必须依赖的模块 | npm i xxx |
| npm install --no-save xxx | 安装xxx模块,但不记录到package.json里 | npm i --no-save xxx |
| npm install --save-dev xxx | 安装xxx模块,并且记录到package.json里,字段对应的dev-dependency,是开发环境必须依赖的模块,比如测试类的(mocha、chai、sinon、zombie、supertest等)都在 | npm i -D xxx |
| npm install --global xxx | 全局安装xxx模块,但不记录到package.json里,如果模块里package.json有bin配置,会自动链接,作为cli命令 | npm i -g xxx |
注意: npm 5 之前采用默认 --no-save 策略,需要加 --save 或 -S 参数将其记录到 package.json 里。
配合iterm2分屏 + spectacle全屏,几乎无敌
安装4个必备软件
brew install git 最流行的SCM源码版本控制软件
brew install wget 下载、扒站神器
brew install ack 搜索代码神器
brew install autojump 终端下多目录跳转神器
3)vim
我虽然不算vim党,但也深爱着。janus是一个非常好用的vim集成开发环境。比如ctrl-p、nerdtree等插件都集成了,对我这种懒人足够了。
关于Node.js的IDE和编辑器有很多选择,对比如下
| 名称 | 是否收费 | 断点调试 | 功能 |
|---|---|---|---|
| Webstorm | 收费 | 支持 | 是IDE,在代码提示、重构等方面功能非常强大,支持的各种语言、框架、模板也非常多,支持断点调试,好处是特别智能,缺点也是特别智能 |
| Sublime/TextMate | 收费 | 不支持 | 编辑器里非常好用的,textmate主要针对mac用户,sublime是跨平台的,相信很多前端开发都熟悉 |
| Vim/Emacs | 免费 | 不支持 | 命令行下的编辑器,非常强大,难度也稍大,但更为酷炫,而且对于服务器部署开发来说是值得一学的 |
| VSCode/Atom | 免费 | 支持 | Atom比较早,功能强大,缺点稍卡顿,VSCode是微软出的,速度快,对于Node.js 调试,重构,代码提示等方面支持都非常好 |
Visual Studio Code是一个运行于 Mac、Windows和 Linux 之上的,针对于编写现代 Web 和云应用的跨平台源代码编辑器。它功能强大,便于调试,加上它本身也是基于 Node.js 模块 electron 构建的,尤其要推荐大家使用。
Visual Studio Code(以下简称vsc)
值得一学,我推荐VSCode编辑器!
更多调试方法,参见https://github.com/i5ting/node-debug-tutorial
《Node.js in action》一书里说,Node.js 所针对的应用程序有一个专门的简称:DIRT。它表示数据密集型实时(data-intensive real-time)程序。因为 Node.js 自身在 I/O 上非常轻量,它善于将数据从一个管道混排或代理到另一个管道上,这能在处理大量请求时持有很多开放的连接,并且只占用一小部分内存。它的设计目标是保证响应能力,跟浏览器一样。
这话不假,但在今天来看,DIRT 还是范围小了。其实 DIRT 本质上说的 I/O 处理的都算,但随着大前端的发展,Node.js 已经不再只是 I/O 处理相关,而是更加的“Node”!
Node.js 使用场景主要分为4大类
nw.js/electron 、移动端 cordova、HTML5、react-native、weex,硬件 ruff.io 等Vue \ Angular 辅助开发,以及工程化演进过程(使用Gulp /Webpack 构建 Web 开发工具)npm上各种工具模块,包括各种前端预编译、构建工具 Grunt / Gulp、脚手架,命令行工具,各种奇技淫巧等下面列出具体的 Node.js 的使用场景,以模块维度划分
| 分类 | 描述 | 相关模块 |
|---|---|---|
| 网站 | 类似于 cnodejs.org 这样传统的网站 |
Express / Koa |
| Api | 同时提供给移动端,PC,H5 等前端使用的 HTTP Api 接口 |
Restify / HApi |
| Api代理 | 为前端提供的,主要对后端Api接口进行再处理,以便更多的适应前端开发 | Express / Koa |
| IM即时聊天 | 实时应用,很多是基于 WebSocket协议的 |
Socket.io / sockjs |
| 反向代理 | 提供类似于 nginx 反向代理功能,但对前端更友好 |
anyproxy / node-http-proxy / hiproxy |
| 前端构建工具 | 辅助前端开发,尤其是各种预编译,构建相关的工具,能够极大的提高前端开发效率 | Grunt / Gulp / Bower / Webpack / Fis3 / YKit |
| 命令行工具 | 使用命令行是非常酷的方式,前端开发自定义了很多相关工具,无论是shell命令,node脚本,还是各种脚手架等,几乎每个公司\小组都会自己的命令行工具集 | Cordova / Shell.js |
| 操作系统 | 有实现,但估计不太会有人用 | `NodeOS |
暂无开放 Issues,或尚未同步最近议题。