建议关注收藏点赞。
- 链接
 nodejs模块大全
目录
实用模块/工具
| 模块 | 说明 | 
|---|---|
| jsonwebtoken | JWT 登录鉴权(签发和验证) | 
| cors | 解决跨域请求问题 | 
| dotenv | 使用 .env文件管理配置 | 
| axios | 在 Node 中发起请求(后端调用第三方接口) | 
| multer | 上传文件(表单文件) | 
| cookie-parser | 操作 Cookie(登录相关) | 
| child_process | 执行命令 | 
| events | 事件系统 | 
| stream | 大文件处理、管道、压缩 | 
| Buffer | 二进制操作、音视频、协议层 | 
| 需求 | 推荐库/工具 | 
|---|---|
| Web 框架 | Express,Koa,Fastify | 
| 数据库 ORM | Sequelize,Prisma,Mongoose | 
| 环境变量 | dotenv | 
| 单测 | Jest,Mocha,Supertest | 
| 部署 | PM2,Docker,Vercel,Render | 
复习
- 为什么JS可以在浏览器中执行
 原理:待执行JS代码->JS解析引擎
 不同浏览器使用不同的 JavaScript 解析引擎:Chrome 浏览器的 V8 解析引擎性能最好
 Chrome 浏览器 => V8
 Firefox 浏览器 => OdinMonkey(奥丁猴)
 Safari 浏览器 => JSCore
 IE 浏览器 => Chakra(查克拉)
- 为什么 JavaScript 可以操作 DOM 和 BOM
 每个浏览器都内置 DOM、BOM API
- 浏览器中JS运行环境
  
基础语法 & 环境
- 推荐的项目结构分层
| 层级 | 职责 | 举例 | 
|---|---|---|
| router(路由层) | 导出router:接收请求,转发给 controller | /user/:id | 
| controller(控制器) | 处理请求参数、返回响应 | 调用 service、处理错误 | 
| service(业务层) | 写具体逻辑或数据库操作 | User.findById(id) | 
| model(模型层) | 定义数据结构 | Mongoose 模型 | 
| middleware(中间件层) | 登录验证、错误处理等 | auth.js、error.js | 
project/
├── app.js
├── routes/
│   └── user.js
├── controllers/
│   └── userController.js
├── services/
│   └── userService.js
├── models/
│   └── user.js
├── middleware/
│   ├── auth.js
│   └── errorHandler.js
- 定义
 Node.js 是基于 Chrome V8 引擎的 JavaScript 运行环境。nodejs官网
 Node.js 用作中间件。例如:在浏览器端和 Java 端使用 Node.js 作为中间件,Node.js 调用 Java 后端发布的接口,同时 Node.js 可以发布 HTTP 接口给浏览器端调用。
 默认使用 CommonJS 模块规范
- 优点
- 高并发能力。在 Java、PHP 或者 .Net 等服务端语言中,会为每一个客户端的连接创建一个新的线程,而每个线程需要耗费大约 2 MB 内存。也就是说,理论上一个 8GB 的服务器,可以同时连接的最大用户数为 4000 个左右。而 Node.js 不会为每个客户创建新的线程,仅仅使用一个线程。所以,使用 Node.js,一个 8GB 的服务器,可以同时处理超过 4 万用户的连接。
- 高性能服务器。Node.js 基于 V8 引擎,V8 引擎是 Google 公司使用 C++ 开发的一种高性能引擎。与开发者编写的低端的 C 语言具有非常相近的执行效率。
- 强大的工具和框架:
 基于 Express 框架(http://www.expressjs.com.cn/)快速构建 Web 应用
 基于 Electron 框架(https://electronjs.org/)跨平台的桌面应用
 基于 restify 框架(http://restify.com/)快速构建 API 接口项目
 读写和操作数据库、创建实用的命令行工具辅助前端开发
| 工具/框架 | 简介 | 特点 | 
|---|---|---|
| Express.js | 用于构建Web应用和API的轻量级框架 | 简洁、快速、支持RESTful API、强大的路由功能 | 
| NestJS | 基于TypeScript的现代化Node.js框架,适用于企业级应用 | 支持TypeScript、模块化架构、易于集成各种库 | 
| Koa.js | 由Express原班人马开发的框架,目标是更小更强大 | 支持async/await、灵活的中间件机制 | 
| Socket.io | 实现实时、双向通信的JavaScript库 | 支持WebSocket、易于集成、支持广播和房间功能 | 
| Electron.js | 使用Web技术构建跨平台桌面应用 | 跨平台、支持丰富的原生API | 
| PM2 | Node.js进程管理工具,支持生产环境的应用管理 | 进程管理、负载均衡、日志管理、性能监控 | 
| Mongoose | MongoDB的ODM库,简化与MongoDB的交互 | Schema支持、数据验证、查询构建、模型功能强大 | 
- Node 和浏览器的区别
 浏览器是 JavaScript 的前端运行环境。
 Node.js 是 JavaScript 的后端运行环境。无法调用 DOM 和 BOM 等浏览器内置 API。
- 安装运行
 LTS是长期稳定版 企业项目推荐安装
node -v #查看版本
node xx.js #运行某个nodejs文件
导入导出
require 和 module.exports(CommonJS)
// math.js
const add = (a, b) => a + b;
module.exports = {
   
   
  add
};
// app.js
const {
   
    add } = require('./math');//同步 加载阻塞执行
console.log(add(2, 3)); // 5
模块化
- 加载模块
 require方法加载执行这个模块代码。
 模块的加载机制:- 优先从缓存中加载。模块第一次加载后会缓存,即多次调用require()并不会使模块代码被执行多次。提高加载效率。
- 内置模块的加载优先级最高。require(‘fs’) 始终返回内置的 fs 模块,即使在 node_modules 目录下有名字相同的包也叫做 fs。
- 自定义模块加载:require() 加载自定义模块必须指定以 ./ 或 …/ 开头路径标识符。如果没有,则 node 会把它当作内置模块或第三方模块加载。
- 第三方模块加载:如果不是一个内置模块,也没有以 ‘./’ 或 ‘…/’ 开头,则 Node.js 会从当前模块父目录开始,尝试从 /node_modules 文件夹中加载第三方模块。
 如果没有找到,则移动到再上一层父目录中,直到文件系统的根目录。
- 目录作为模块:三种加载方式:
 目录下查找 package.json 的文件,并寻找 main 属性,作为 require() 加载入口
 如果目录里没有 package.json 文件,或者 main 入口不存在或无法解析,则 Node.js 试图加载目录下 index.js 文件。
 如果以上两步都失败,则在终端打印错误消息,Error: Cannot find module ‘xxx’
- require() 导入自定义模块,如果省略文件扩展名,则按顺序分别尝试加载以下的文件:
 按照确切文件名加载
 补全 .js 扩展名进行加载
 补全 .json 扩展名进行加载
 补全 .node 扩展名进行加载
 加载失败,终端报错
 
- 模块有模块作用域,防止全局变量污染。每个.js自定义模块都有一个module对象,存储有关信息。
- module.exports 对象
 自定义模块中使用 module.exports 对象,将模块内成员共享出去,供外界使用。外界用 require() 导入自定义模块时,得到 module.exports 所指向的对象。
- exports 对象
 简化。默认exports 和 module.exports 指向同一个对象。最终共享结果以 module.exports 指向的对象为准。
- exports 和 module.exports 的使用误区
 require() 模块时永远是 module.exports 指向的对象
 注意:为了防止混乱,建议大家不要在同一个模块中同时使用 exports 和 module.exports
  
- Node.js 中的模块化规范
 Node.js 遵循CommonJS 模块化规范
 CommonJS 规定:每个模块内部 module对象代表当前模块,exports 属性(即 module.exports)是对外接口。
const http=require('http')//导入内置模块
const custom=require('./custom.js')//导入用户自定义模块
const moment=require('moment')//导入第三方模块
console.log(http,custom,moment)//打印的是他们的module.exports内容
require('./modA');
require('./modB');
console.log('main module:', module);
//module 不会 直接包含 require('./modA') 和 require('./modB') 的详细信息
//但它间接包含子模块的信息 —— 体现在 module.children 属性里。
//modA.js
module.exports = {
   
    myModule: module };
//modB.js
module.exports = {
   
    myModule: module };
//main.js
const modA = require('./modA');
const modB = require('./modB');
console.log('modA module:', modA.myModule);
console.log('modB module:', modB.myModule);
console.log('main module:', module);
//使用moment包  npm安装moment
const moment=require('moment')//导入第三方模块
const dt=moment().format('YYYY-MM-DD HH:mm:ss')
console.log(dt)
启用ES6模块化支持
- ES 模块 import/export 在 Node 中的使用(.mjs、type: “module”)
 为啥要转ES模块?与浏览器一致、静态分析优势
 使用:将扩展名从.js改为.mjs;package.json中添加type: "module"
- 引入模块
 import express from 'express替代之前的require
//app.js
import express from 'express'
import userRouter from './router/user_router.js'
const app = express()
app.use('/api', userRouter)//挂载路由器
app.listen(80, () => {
   
   
  console.log('server running at http://127.0.0.1')
})
//router.js
import express from 'express'
import {
   
    getAllUser } from '../controller/user_ctrl.js'
const router = new express.Router()
router.get('/user', getAllUser)//第二个是回调函数
export default router
//router_handler.js
import db from '../db/index.js'
// 使用 ES6 的按需导出语法,将 getAllUser 方法导出出去
export async function getAllUser(req, res) {
   
   
  try {
   
   
    const [rows] = await db.query('select id, username, nickname, xxx from ev_users')
    res.send({
   
   
      status: 0,
      message: '获取用户列表数据成功!',
      data: rows,
    })
  } catch (err) {
   
   //try...catch捕获异常
    res.send({
   
   
      status: 1,
      message: '获取用户列表数据失败!',
      desc: err.message,
    })
  }
}
//db_index.js
import mysql from 'mysql2'
const pool = mysql.createPool({
   
   
  host: '127.0.0.1',
  port: 3306,
  database: 'my_db_01',
  user: 'root',
  password: 'admin123',
})
export default pool.promise()
路径处理模块 path
Node 路径不能直接用 + 拼,需用 path 保证跨平台正确性。
- 路径动态拼接的问题
 在使用 fs 模块操作文件时,如果提供的操作路径是以 ./ 或 …/ 开头的相对路径时,容易出现路径动态拼接错误的问题。
 原因:代码在运行的时候,会以执行 node 命令时所处的目录,动态拼接出被操作文件的完整路径。
 解决方案:在使用 fs 模块操作文件时,直接提供完整的路径,不要提供 ./ 或 …/ 开头的相对路径,从而防止路径动态拼接的问题。
 __dirname 是 Node.js 全局变量,表示当前模块(文件)所在目录的绝对路径,用于拼接路径
//__dirname: /Users/yourname/project
fs.readFile(__dirname+'/path.txt','utf8',function(err,datastr){
   
   
	if(err)return console.log('文件读取失败'+err.message)
	//err=null时读取成功,反之读取失败
	console.log(datastr)
})
/*
__dirname 是当前文件夹路径(不是工作目录)
path.resolve():返回绝对路径
path.join():拼路径,自动处理斜杠
*/
const path = require('path');
// 获取绝对路径
const abs = path.resolve(__dirname, 'data', 'test.txt');
console.log(abs); // /xxx/data/test.tx
// 拼接路径
const full = path.join('/a', '/b', 'c.txt'); // /a/b/c.txt
path.join([...paths])//多个路径片段连接
path.basename(path,[ext])
//获取路径的最后一部分,用于获取路径中的文件名
//ext 可选,文件扩展名
const fpath='/a/b/c/index.html'
var filename=path.basename(fpath)//index.html
var name_without_ext=path.basename(fpath,'.html')//index
path.extname(path)//获取扩展名部分
const fext=path.extname(fpath)
文件系统模块 fs
fs.writeFile() 方法只能用来创建文件,不能用来创建路径
 重复调用 fs.writeFile() 写入同一个文件,新写入内容会覆盖之前的旧内容
// 同步读写(适合 CLI 脚本)
const fs = require('fs');
fs.writeFileSync('data.txt', 'hello');       // 写文件
const content = fs.readFileSync('data.txt'); // 读文件
console.log(content.toString());             // Buffer 转字符串
// 异步读写(适合服务端)
const fs = require('fs').promises;
async function readData() {
   
   
  const data = await fs.readFile('data.txt', 'utf-8');
  console.log(data);
}
readData();
fs.readFile(path,[options],callback)//callback回调函数
//参数2 可选 编码格式
//参数3 文件读取完成,通过回调函数拿到读取结果
fs.readFile('./path.txt','utf8',function(err,datastr){
   
   
	if(err)return console.log('文件读取失败'+err.message)
	//err=null时读取成功,反之读取失败,datastr=undefined
	console.log(datastr)
})
fs.writeFile(file_path,data.[options],callback)
//data 要写入file的内容
//callback 文件写入完成后的回调函数
//是否写入成功也是判断err
- 实例:将html文件中的js css部分拆出来成一单独文件
[\s\S] 只匹配 一个字符;
[\s\S]* 才是匹配 任意数量的字符(包括 0 个);
[\s\S]*? 是非贪婪地匹配任意数量字符,直到匹配到后续的模式。
const fs=require('fs')
const path=require('path')
const regStyle=/<style>[\s\S]*<\/style>/
const regScript=/<script>[\s\S]*<\/script>/
fs.readFile(path.join(__dirname,'index.html'),'utf8',(err,datastr)=>{
   
   
	if(err)return console.log('文件读取失败'+err.message)
	
	resolveCSS(datastr)
	resolveJS(datastr)
	resolveHTML(datastr)
})
function resolveCSS(htmlstr){
   
   
	const r1=regStyle.exec(htmlstr)
	const newcss=r1[0].replace('<style>','').replace('</style>','')
	fs.writeFile(path.join(__dirname,'index.css'),newcss,err=>{
   
   
		if(err)return console.log('文件写入失败'+err.message)
		console.log('css写入成功')
	})
}
function resolveJS(htmlstr){
   
   
	const r2=regScript.exec(htmlstr)
	const newjs=r2[0].replace('<script>','').replace('</script>','')
	fs.writeFile(path.join(__dirname,'./index.js'),newjs,err=>{
   
   
		if(err)return console.log('文件写入失败'+err.message)
		console.log('js写入成功')
	})
}
function resolveHTML(htmlstr){
   
   
	const newhtml=htmlstr.replace(regStyle,'<link rel="stylesheet" href="./index.css"/>').replace(regScript,'<script src="./index.js"></script>')
	fs.writeFile(path.join(__dirname,'./index.html'),newhtml,err=>{
   
   
		if(err)return console.log('文件写入失败'+err.message)
		console.log('html写入成功')
	})
}
Promise
nvm是用来切换nodejs版本的
v14之前,由于 node.js 官方提供的 fs 模块仅支持以回调函数的方式读取文件,不支持 Promise 的调用方式。需要安装 then-fs 这个第三方包npm install then-fs,支持基于 Promise 方式读取文件的内容
 调用 then-fs 提供的 readFile() 方法,可以异步地读取文件的内容,它的返回值是 Promise 实例对象,可以调用 .then() 方法为每个 Promise 异步操作指定成功和失败之后的回调函数。
import thenFs from 'then-fs'
thenFs.readFile('./1.txt','utf8').then(res=>{
   
   console.log(res)},err=>{
   
   console.log('err',err)})
//err失败回调可选的
thenFs.readFile('./1.txt','utf8').then(res=>{
   
   console.log(res)})
//如果有多个这样的读取,要保证文件的读取顺序,需要用链式调用
/*
如果上一个 .then() 方法中返回了一个新的 Promise 实例对象,则可以通过下一个 .then() 继续进行处理。通过 .then() 方法的链式调用,就解决了回调地狱的问题。
*/
thenFs.readFile('./1.txt','utf8')//返回promise实例对象
.catch(err=>{
   
    //捕获错误
	console.log(err.message)
})
.then((r1)=>{
   
   //指定成功的回调函数
	console.log(r1)
	return thenFs.readFile('./2.txt','utf8')
})
.then((r2)=>{
   
   
	console.log(r2)
	return thenFs.readFile('./3.txt','utf8')
})
.then((r3)=>{
   
   
	console.log(r3)
})
.catch(err=>{
   
    //捕获错误
	console.log(err.message)
})
Node.js fs.promises API 到 Node.js v14 起正式推荐使用,const fs = require('fs').promises;引入后就可以开始使用了。
const fs = require('fs').promises;
async function readFilesInOrder(files) {
   
   
  const results = [];
  for (const file of files) {
   
   
    try {
   
   
      const content = await fs.readFile(file, 'utf8');
      console.log(`内容 (${
     
     file}):\n`, content);
      results.push(content);
    } catch (err) {
   
   
      console.error(`读取 ${
     
     file} 出错:`, err);
    }
  }
  return results;
}
// 示例文件名数组
const fileList = ['file1.txt', 'file2.txt', 'file3.txt'];
readFilesInOrder(fileList).then(contents => {
   
   
  console.log('\n所有文件读取完成');
});
//更喜欢用 .then() 链式写法(不使用 async/await)
const fs = require('fs').promises;
function readFilesInOrder(files) {
   
   
  let promise = Promise.resolve();
  const results = [];
  files.forEach(file => {
   
   
    promise = promise
      .then(() => fs.readFile(file, 'utf8'))
      .then(content => {
   
   
        console.log(`内容 (${
     
     file}):\n`, content);
        results.push(content);
      })
      .catch(err => console.error(`读取 ${
     
     file} 出错:`, err));
  });
  return promise.then(() => results);
}
readFilesInOrder(fileList).then(contents => {
   
   
  console.log('\n所有文件读取完成');
});
const fs = require('fs');
function initp(fpath){
   
   
    return new Promise(function(resolve, reject){
   
   
        fs.readFile(fpath, 'utf8', (err, dataStr) => {
   
   
            if (err) {
   
   
                reject(err);      // 读取失败,触发 fail 回调
            } else {
   
   
                console.log(dataStr); // 可选:打印内容
                resolve(dataStr);     // 成功,触发 suc 回调
            }
        });
    });
}
function suc(data){
   
   
    console.log("成功回调函数触发:", data);
}
function fail(err){
   
   
    console.error("失败回调函数触发:", err);
}
initp('./1.txt').then(suc, fail);
进程信息:process
console.log(process.argv); // 获取命令行参数
console.log
 
                   
                   
                   
                   最低0.47元/天 解锁文章
最低0.47元/天 解锁文章
                           
                       
       
           
                 
                 
                 
                 
                 
                
               
                 
                 
                 
                 
                
               
                 
                 扫一扫
扫一扫
                     
                     
              
             
                  
 被折叠的  条评论
		 为什么被折叠?
被折叠的  条评论
		 为什么被折叠?
		 
		  到【灌水乐园】发言
到【灌水乐园】发言                                
		 
		 
    
   
    
   
             
					 
					 
					


 
            