Node.js

Node.js 的安装与版本管理

我选择使用 nvm 进行 Node.js 的安装与版本管理,里面同时也就包含了 npm 的安装与版本管理。

可以参照 nvm 的 github 官网 进行命令行安装,但是我在 mac 上更偏向于使用 homebrew 进行统一的包安装管理。

# 查看下是否有这个 nvm 包
$ brew info nvm
1
2

其中输出的这块消息比较重要:

You should create NVM's working directory if it doesn't exist:

  mkdir ~/.nvm

Add the following to ~/.zshrc or your desired shell
configuration file:

  export NVM_DIR="$HOME/.nvm"
  . "/usr/local/opt/nvm/nvm.sh"
1
2
3
4
5
6
7
8
9

接下来就是安装与配置环境了:

# 安装 nvm
$ brew install nvm

# 配置环境变量
$ mkdir ~/.nvm
# 或者 vim ~/.zshrc,取决于你正在使用的 shell
$ vim ~/.bashrc

# 追加如下内容
# 要注意由于这里是用 brew 安装的
# 所以配置与 github 上的不太相同
export NVM_DIR="$HOME/.nvm"
. "/usr/local/opt/nvm/nvm.sh"
1
2
3
4
5
6
7
8
9
10
11
12
13

异步

非阻塞 I/O

  • I/O,一个系统的输入和输出
  • 阻塞 I/O 和非阻塞 I/O 的区别就在于系统接收输入再到输出期间,能不能接收其他输入

计算程序运行的耗时:console.time([<String>])console.timeEnd([<String>]) 套装

console.time('Program A');
// ... 一段程序的执行
console.timeEnd('Program A');
1
2
3

异步编程

异步流程控制:

  • npm: async.js
  • thunk: 不是一个包,也不是一个框架,是一种编程范式

RPC 调用

Remote Procedure Call,远程过程间调用

RPC 调用时用于服务器之间的调用通信,可以类比于浏览器与服务器之间的 ajax。

区别:

  1. 不一定使用 DNS 作为寻址服务,因为 rpc 一般在「鹅厂里面」是内网之间通信,如果还使用 DNS 的话,就不合适了,因为没必要;
    • ajax 使用 DNS 将域名换成 ip,然后进行通信;
    • rpc 使用特有服务进行寻址(例如腾讯使用的是 L5,阿里使用的是 vip(virtual ip)),也就是拿一个 id 一样的东西去「寻址服务器」换 ip,然后再进行通信;
  2. 应用层协议一般不使用 HTTP,而是使用二进制协议,以获得更好的性能优势;
    • 二进制协议:更小的数据包体积、更快的编解码速率
  3. 基于 TCP 或者 UDP 协议;
    • TCP 通信方式有:单工通信、半双工通信、全双工通信

同构直出

其实实质就是服务端将一份渲染好的 html 发到浏览器,其中这份 html 里面包含了浏览器端能够渲染的脚本代码,是经过 webpack 打包的静态资源,而且全局中还注入了初始化数据,对,没错,这些数据就是挂在了 window 对象下。

当发到浏览器端时,用户能够立即看见页面,这时候,静态资源 js 文件还在下载,然后运行,也就是在浏览器端重新渲染一次核心页面部分,当然渲染后的结果是一样的,用户不会察觉到有什么变化,但实际上这时候就可以用在浏览器端渲染的脚本做一些动态数据交互。

其实一开始我在想,既然都做了服务端直出了,为什么还需要再写一份浏览器端渲染的代码?就算的确是为了动态数据交互,那也可以用直出方式的。

后面总结了下原因:

  • 选择直出的原因无非有二:
    1. SEO
    2. 首屏呈现更快(一般大多为了在移动端上压榨首屏呈现时间)

但是要知道,要做 SEO 的网站并不会涉及到太多的动态数据交互,一般全部直出就可以了,对,动态数据交互的方法也写进直出里面,没必要做同构了。

另外,为了首屏速度的一般在移动端上,这种一般不需要做 SEO,更多第时为了两点:

  1. 首屏速度一定要快,越快越好;
  2. 动态数据交互比较多,使用浏览器去渲染这部分代码更合适,不浪费服务端资源;

所以这时候就需要同构直出了。

HTTP 服务性能测试

压力测试

  • ab
    • Apache Bench
  • webbench

ab 压测例子:

# 模拟 200 个客户端并发请求,一共发出 1600 条请求
$ ab -c200 -n1600 http://127.0.0.1:3000/

# 模拟 50 个客户端并发请求,一共持续 15 秒
$ ab -c50 -t15 http://127.0.0.1:3000/
1
2
3
4
5

找到性能瓶颈

  • top
    • 在跑 ab 的时候,可以同时跑一下 top 命令,看 cpu 和内存的负载情况,找到性能的限制到底在哪个地方;
  • iostat
    • 硬盘性能

Node.js 性能分析工具

  • Node.js 自带 profile
  • Chrome devtool
  • Clinic.js

node 自带 profile 用法:

# 加个 --prof 的参数就好了
# 然后运行 ab 压测
# 然后它会自动在根目录下输出一个日志文件
$ node --prof entry.js

# 压测结束后,可以去分析日志文件
$ node --prof-process isolate-xxx.log > yyy.txt
1
2
3
4
5
6
7

Chrome devtool

在命令启动 node 程序:

# brk 的意思是一开始暂停运行,等待用户手动开始
$ node --inspect-brk entry.js
1
2

然后打开 chrome,访问 chrome://inspect,可以看到一项 node 服务,点击 inspect 就可以进入调试界面了。

点击 profiler,然后运行 ab 压测,压测结束后停止 profiler,然后就可以看分析结果了。

好用的库

服务端

  • cors
    • Node 优雅的跨域 CORS 模块
    • https://www.jianshu.com/p/f650dfad5574
  • proxy-agent
    • node 中间代理请求库
  • express-http-proxy
    • express 请求代理中间件
  • httpserver
    • 可以在命令行快速第启动一个 http 服务器
    • 看别人写的源码,能够快速地提高自己
  • sequelize
    • 连接、操作数据库

调试

  • debug 库
    • 可以多颜色输出
    • 命令行开关方便
    • 可以美化对象的打印
    • 同时支持 Node.js 和浏览器

参考链接