【青训营】- Node.js基础入门

244 阅读6分钟

Node.js简介

什么是Node.js?

Node.js不是一门语言,而是一个基于Google V8引擎,跨平台的JavaScript运行环境

Node.js安装与运行

Node.js在实际开发中使用偶数版本(长期维护版本)

⭐️Node.js应用举个简单的栗子
读取package.json内容
//index.js中
const {readFile} = require('fs');

//以‘utf-8’读取package.json,有错误抛出错误,没有错误console.log
readFile( './package.json ',{encoding: 'utf-8'}, (err,data)=>{
    if(err){
        throw err;
    }
    console.log(data);
})

\> `node index.js`
输出package.json文件内容

版本管理

  1. 如何快速切换Node.js版本

    n:一个npm全局开源包,是依赖npm来全局安装、使用的
    fnm:快速简单,兼容性支持.node-version.nvmrc文件
    nvm:独立的软件包,使用比较多

Node.js特点

  1. 异步I/O
    当Node.js执行I/O操作(文件的读写,网络请求与读写等)时,会在响应返回恢复操作,而不是阻塞线程并浪费CPU循环等待
    简单来说,当Node.js执行I/O操作然后在等待响应的时候,不会整个系统等待响应,中途还能干别的事,直到响应返回再恢复操作

    代码编写顺序和执行顺序无关

  2. 单线程
    Node.js保持了JavaScript在浏览器中单线程的特点
    👉优点:
    不用处处在意状态同步问题,不会发现死锁
    没有线程上下文切换带来的性能开销

    👉缺点:(解决方案在后)
    无法引用多核CPI
    错误会引起整个应用退出,健壮性不足
    大量计算占用CPU无法继续执行

    ⭐️ 举个栗子
    浏览器是多进程,JS引擎单线程
     Browser进程:浏览器主进程,只有一个
     插件进程:插件使用时才创建
     渲染进程:页面渲染、JS执行、事件处理
    
  3. 跨平台
    主要得益于在操作系统与Node上层模块系统之间构建了一层平台架构

  4. 应用场景
    Node.js在大部分领域都有一席之地,特别是I/O密集型

    例如:
    Web应用:Express/Koa
    前端构建:Webpacks<br>
    GUI客户端软件:VSCode、网易云音乐...
    其它:爬虫等...
    

模块化机制

何为模块化

根据功能或业务将一个大程序拆分成互相依赖的小文件,再用简单的方式拼装起来

为什么模块化?无模块化有什么问题?

1 .所有script标签必须保证顺序正确,否则会依赖报错
2. 全局变量存在命名冲突,占用内存无法回收
3. IIFE/namespace会导致代码可读性低等诸多问题...

CommonJS规范

Node.js支持CommonJS模块规范,采用同步机制加载模块
exports module.exports指向同一个地址
exports = module.exports = {}

加载方式

  1. 加载内置模块 require('fs')

  2. 加载相对||绝对路径的文件模块
    require('/User/.../file.js')
    require('./file.js')

  3. 加载npm包 require('lodash')

    ⭐️npm包查找原则:require('lodash')
      1. 当前目录node_modules
      2. 如果没有,父级目录的node_modules
      3. 如果没有,沿着路径向上递归,直到根目录下node_modules
      4. 找到只会回家再package.json main指向的文件,如果没有package.json则依次查找index.js、index、json、index.node
    

require.cache

require.cache中由于同步加载缓存着加载过的模块
如果没有缓存,文件模块查找耗时增加。如果每次require都需要重新遍历查找,性能较差

⭐️如何删除require.cache
//有缓存
const mod1 = require('./foo');
const mod2 = require('./foo');
console.log( mod1 === mod2 );//true

//无缓存
function requireUncaches(module){
    //删除require.cache
    delete require.cache[require.resolve(module)];
    return require(module);
}
const mod3 = requireUncaches('./foo');
console.log( mod1 === mod3 );//false

ESModules(简称ESM)

  • ESM是在ES6语言层面提出的一种模块化标准
  • ESM中主要有import、export两个关键词,不能console.log打印两个关键字

如何使用ESM

ESM是在模块在编译的时候输出(提前加载)

  1. node>=13:
    在Node层面,后缀改为.mjs后直接编写,比如:node main.mjs
    项目package.json中,添加 <scrip> 标签中添加 type="module"
  2. node<=12:
    --experimental-modules

CommonJS VS ESM

  • CommonJS模块输出的是一个值的拷贝;ESM模块输出的是值的引用

  • CommonJS模块是运行时加载;ESM是在模块在编译的时候输出(提前加载)

    CommonJS 和 ESM可以混用,但是最好不要!

其它模块化规范

名称区别
AMD异步加载,推崇依赖前置
CMD异步加载,推崇就近依赖
UMD兼容AMD和CommonJS模式
ES Modules语言层面的模块化规范,与环境无关,可借助babel编译

⭐️模块化规范对应的环境

模块.jpg

包管理机制

npm介绍

npm是Node.js中的包管理器,提供了安装、删除等命令来管理包

 ⭐️一些有关的介绍
 - dependencies  业务依赖,应用发布后正常执行所需要的包
 - devDependencies  开发依赖、只用于开发环境
 - peerDependencies  同等依赖、比如一个webpack插件依赖特点版本的webpack
 - bundledDependencies  打包依赖(npm run pack),必须已经在devDep或dep声明过
 - optionalDependencies  可选依赖

私有npm

  • 镜像公司内部私有
  • 镜像设置 npm config set registry=url

其它

npm | yarn => lock/扁平/缓存...
pnpm => monorepo/硬、符号链接/安全性高...

异步编程

Callback

Promise

Promise是一个具有四个状态的有限状态机,其中三个核心状态为Pending(挂起),Fulfilled(完成)、Rejected(拒绝),以及还有一个未开始状态

123456.jpeg

⭐️使用PromiseCallback
!使用Callback有时会有一些很深的嵌套
!使用Promise可以使嵌套扁平化

如何将Callback转为Promise形式?

util.promisifh

await

await函数使用try、catch捕获异常(注意并行处理)

Event

发布订阅模式,Node.js内置events模块 比如HTTP sever on ('requests')事件监听

Web应用开发

Koa介绍

Koa——基于Node.js平台的下一代Web开发框架。它仅仅提供了一个轻量优雅的函数库,使编写Web应用变得得心应手,不在内核方法中绑定任何中间件

Koa执行过程

-服务启动
   -实例化application
   -注册中间件
   -创建服务,监听端口
-接受/处理请求
    -获取请求req,res对象
    -req -> request、 req -> respose封装
    -request&response -> context
    -执行中间件
    -输出设置到ctx.body上的内容

⭐️图示:

123456.jpg

Koa中间件

Koa应用程序是一个包含一组中间件的函数对象,他是按照洋葱模型组织和执行的

Koa中间件繁多,质量参差不齐,需要合理选择,高效组合

123456.jpg

⭐️一条请求在中间件的历经之路

123456.jpg

基于Koa的前端框架

开源:ThinkJS/Egg...
内部:Turbo、E让、Gulu...

线上部署

Node.js基于事件驱动、异步非阻塞模式,可以用于高并发场景,同时避免了线程创建、线程上下文切换所产生的资源开销

⭐️解决上文中Node.js单线程造成的缺点方法:

  1. 利用多核CPU
    Node.js提供了cluster/child_process模块
  2. 提高健壮性:
    可以使用Node.js进程管理工具来守护进程,从而提高健壮性
  3. 复杂计算占用CPU卡住了怎么办
    使用多进程与进程通信
    !通过父进程监听子进程降低CPU卡住的可能性

最后

之前有学习使用过一些Node.js,通过这一次的系统学习,更加了解的服务端开发与前端开发的联系和区别。学习路漫漫,想成为一名合格的前端工程师,这些知识都是需要了解的,加油哇~
如果有任何不对的记录,欢迎指正~!~