Node.js
1.Node.js简介
Node.js简介
不是一门语言,而是一个JavaScript运行环境,类似于Java的JVM
Node.js上一个基于Google V8 引擎的、垮平台的
JavaScript运行环境
版本:有奇数版本和偶数版本,偶数版本是LTS长期维护版本
安装与运行
index.js
const { readFile } = require('fs');
readFile('./package.json', { encoding: 'utf-8' }, (err, data) => {
if (err) {
throw err;
}
console.log(data);
})
运行
node index.js
版本管理
使用nvm管理Node.js
Mac&&Linux版本
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.38.0/install.sh | bash
// 安装指定版本的Node
nvm install 16.6.2
// 列出系统中已经安装的版本
nvm ls
// 使用指定版本的Node
nvm use 16.6.2
// 卸载指定版本
nvm uninstall 16.6.2
特点
异步I/O
当Node.js执行I/O操作时,会在响应返回并恢复操作,而不是阻塞线程并浪费CPU循环等待
代码编写顺序与执行顺序无关
const { readFile } = require('fs');
readFile('./package.json', { encoding: 'utf-8' }, (err, data) => {
if (err) {
throw err;
}
console.log(data);
});
console.log(123456);
单线程
Node.js保持了JavaScript在浏览器中单线程的特点
优点
不用处处在意状态同步的问题,不会发送死锁
没有线程上下文切换带来的性能开销
缺点
无法利用多核CPU
错误会引起整个应用退出,健壮性不足
大量计算导致CPU无法继续执行
以浏览器为例,浏览器是多进程,JS引擎是单线程
浏览器进程一般包括浏览器进程、GPU进程、渲染器进程、插件进程。
- GUI渲染进程
- JS引擎进程+V8
- 事件触发线程
- 定时器触发线程
- 异步请求线程
垮平台
兼容Windows和*nix平台,主要得益于在操作系统与Node.js上层模块之间构建了一层平台架构。
应用场景
Node.js适用于I/O密集型的应用
- Web应用:
Express/Koa - 前端构建:
Webpack - GUI客户端软件:
VScode/网易云音乐 - 其他:实时通讯、爬虫、CLI等
2.模块化机制
模块化简介
1.什么是模块化?
根据功能或业务将一个大程序拆分成互相依赖的小文件,再用简单的方式拼接起来
2.为什么模块化?无模块化问题
所有script标签必须保证顺序正确,否则会依赖报错
全局变量存在命名冲突,占用内存无法被回收
IIFE/namespace会导致代码可读性低等诸多问题
CommonJS规范
Node.js支持CommonJS模块规范,采用同步机制加载模块
exports===module.exports,在内存中指向同一块引用
加载方式
-
加载内置模块
require('fs') -
加载相对|绝对路径的文件模块
require('c:\abc\file.js') require('.\file.js') -
加载npm包
require('lodash')
npm包查找原则:require('lodash'
- 当前目录
node_modules - 如果没有,父级目录的
node_modules - 如果没有,沿着路径向上递归,直到根目录下
node_modules - 找到之后会加载
package.json的main指向的文件,如果没有package.json文件则依次查找index.js,index.json,index.node
require.cache中缓存着加载过的模块,缓存的原因:同步加载
- 文件模块查找耗时时,如果每次
require都需要重新遍历查找,性能会比较差; - 在实际开发中,模块可能包含副作用代码
- AMD 是 RequireJS 在推广过程中规范化产出,异步加载,推崇依赖前置;
- CMD 是 SeaJS 在推广过程中规范化产出,异步加载,推崇就近依赖;
- UMD (Universal Module Definition) 规范,兼容 AMD 和 CommonJS 模式
- ES Modules (ESM),语言层面的模块化规范,与环境无关,可借助 babel 编译
ESM是在ES6语言层面提出的一种模块化标准
ESM中主要有import和export两个关键词,不能console打印两个关键词
m1.mjs文件
<script type="module" src="m1.mjs"></script>
3.包管理机制
npm介绍
包一般包括index.js和package.json
NPM是Node.js中的包管理器,提供了安装、删除等其他命令来管理包
package.json文件
- name 包名称
- version 版本号
- main 入口文件
- scripts 执行脚本
- dependencies 线上依赖
- devDependencies 开发依赖
- repository 代码托管地址
更多配置
package.json | npm Docs (npmjs.com)
- dependencies 业务依赖,应用发布后正常执行所需要的包
- devDependencies 开发依赖,只用于开发环境
- peerDependencies 同等依赖,比如一个 webpack 插件依赖特定版本的 webpack
- bundledDependencies 打包依赖(npm run pack),必须已经在 devDep 或者 dep声明过
- optionalDependencies 可选依赖
私有NPM
镜像公司内部私有npm
镜像设置
npm config set registry=https://xxxxxxx
- 并行安装
- 扁平管理
- 锁文件
- 缓存优化
常用命令
npm init
npm config
npm run [cmd]
npm install [pkg]
npm uninstall [pkg]
npm update [pkg]
npm info [pkg]
npm publish
4.异步编程
callback
promise
promise是一个具有四个状态的有限状态机,其中有三个核心状态
pending挂起fulfilled完成rejected拒绝
以及一个未开始状态
async
await函数使用try catch捕获异常
event
发布订阅模式Node.js内置events模块
如HTTP serve on('request')事件监听
5.Web应用开发
http模块
const http = require('http');
http.createServer((req, res) => {
res.end('hello');
}).listen(3000, () => {
console.log('启动成功');
});
Koa介绍
基于Node.js平台的下一代Web开发框架
const app = new Koa();
app.use(async ctx => {
ctx.body = 'hello';
});
app.listen(3000, () => {
console.log('启动成功');
});
执行过程
- 服务启动
- 实例化 application
- 注册中间件
- 创建服务、监听端口
- 接受/处理请求
- 获取请求 req、res 对象
- req -> request、res -> response 封装
- request & response -> context
- 执行中间件
- 输出设置到 ctx.body 上的内容
中间件
Koa应用程序是一个包含一组中间件函数的对象,它是按照洋葱模型组织和执行的
6.开发调试
断点调试
node --inspect=0.0.0.0:9229 bootstrap.js
ndb工具
npm install ndb -g
ndb node bootstrap.js
使用vscode调试
线上调试
- SDK上报
- 写入到文件
7.线上部署
Node.js虽然是单线程模型,但是其基于事件驱动、异步非阻塞模式,可应用于高并发场景,同时避免了线程创建、线程之间上下文切换所产生的资源开销。
利用多核CPU
Node.js提供了cluster/child_process模块
进程管理工具
- 多进程
- 自动重启
- 负载均衡
- 日志查看
- 性能监控
nodeman
pm2