它们都是基于nodejs开发的
Webpack
Vite
BabelVSCode
Figma
Postman
常用的命令行指令
C:/D: 切换盘符
dir 列出当前目录下的所有文件
cd 目录名 进入到指定目录
md 目录名 创建一个文件夹
rd 目录名 删除一个文件夹
.表示当前目录
..表示上一级目录
当我们在命令行窗口打开一个文件,或调用一个程序时,系统会首先在当前目录下寻找文件程序,如果找到了则直接打开如果没有找到则会依次到环境变量path的路径中寻找,直到找到为止,如果没找到则报错。
所以我们可以将一些经常需要访问的程序和文件的路径添加到path中,这样我们就可以在任意位置来访问这些文件和程序了
进程
- 进程就是一个一个的工作计划(工厂中的车间)
线程
- 线程是计算机最小的运算单位(工厂中的工人)线程是干活的
- 线程
传统的服务器都是多线程的
- 每进来一个请求,就创建一个线程去处理请求
Node的服务器单线程的
- Node处理请求时是单线程,但是在后台拥有一个I/O线程池
node中的js引擎使用的是chrome的v8引擎
node特点:
1.非阻塞、异步的I/O
2.事件和回调函数
3.单线程(主线程是单线程,后台I/O线程池)
4.跨平台
node为了对模块管理引入CommonJS规范
模块的引用:
使用 require()函数来引入一个模块
例如:var 变量 = require(“模块的标识”);
模块的定义:
- node中一个js文件就是一个模块
- 默认情况下在js文件中编写的内容,都是运行在一个独立的函数中,外部的模块无法访问
- 导出变量和函数
- 使用 exports
- 例子:
exports.属性 = 属性值;
exports.方法 = 函数;
- 使用module.exports
- 例子:
module.exports.属性 = 属性值;
module.exports.方法 = 函数;
module.exports = {};
模块的标识就是模块的名字或路径
node通过模块的标识来寻找模块的
对于核心模块(npm中下载的模块),直接使用模块的名字对其进行引入
var fs = require(“fs”);
var express = require(“express”);
对于自定义的文件模块,需要通过文件的路径来对模块进行引入
路径可以是绝对路径,如果是相对路径必须以./或 …/开头
var router = require(“./router”);
包结构:
bin
- 二进制的可执行文件,一般都是一些工具包中才有
lib
- js文件
doc
- 文档
test
- 测试代码
package.json
- 包的描述文件
package.json
- 它是一个json格式的文件,在它里面保存了包各种相关的信息
name 包名
version 版本
dependencies 依赖
main 包的主要的文件
bin 可执行文件
- 通过npm可以对node中的包进行上传、下载、搜索等操作
- npm会在安装完node以后,自动安装
- npm的常用指令
npm -v 查看npm的版本
npm version 查看所有模块的版本
npm init 初始化项目(创建package.json)
npm i/install 包名 安装指定的包
npm i/install 包名 --save 安装指定的包并添加依赖
npm i/install 包名 -g 全局安装(一般都是一些工具)
npm i/install 安装当前项目所依赖的包
npm s/search 包名 搜索包
npm r/remove 包名 删除一个包
文件系统可以实现与硬盘的交互
- Buffer(缓冲区)
- Buffer和数组的结构的非常类似,Buffer是用来存储二进制数据的
- Buffer的方法
- Buffer.from(字符串)
- 将一个字符串中内容保存到一个buffer中
- buf.toString()
- 将buffer转换为一个字符串
- Buffer.alloc(size)
- 创建一个指定大小的buffer对象
- Buffer.allocUnsafe(size)
- 创建一个指定大小的buffer对象,可以包含敏感数据
- fs模块
- 在Node通过fs模块来对系统中的文件进行操作,fs模块是node中已经继承好了,不需要在使用npm下载,直接引入即可
- 引入fs
var fs = require("fs");
- fs模块中的大部分操作都提供了两种方法,同步方法和异步方法
同步方法带sync
异步方法没有sync,都需要回调函数
- 写入文件
1.同步写入
2.异步写入
3.简单写入
4.流式写入
- 读取文件
1.同步读取
2.异步读取
3.简单读取
4.流式读取
- 方法
- 打开文件
fs.open(path, flags[, mode], callback)
fs.openSync(path, flags[, mode])
- 读写文件
fs.write(fd, string[, position[, encoding]], callback)
fs.writeSync(fd, string[, position[, encoding]])
fs.read(fd, buffer, offset, length, position, callback)
fs.readSync(fd, buffer, offset, length, position)
- 关闭文件
fs.close(fd,callback)
fs.closeSync(fd);
- 简单文件读取和写入
//文件如果不存在会自动创建
fs.writeFile(file, data[, options], callback)
fs.writeFileSync(file, data[, options])
fs.readFile(path[, options], callback)
fs.readFileSync(path[, options])
- 流式文件读取和写入
- 流式读取和写入适用于一些比较大的文件
fs.createWriteStream(path[, options])
fs.createReadStream(path[, options])
简单的流式写入例子
const fs = require('fs');
// 创建一个可写流,指定要写入的文件路径
const writeStream = fs.createWriteStream('output.txt');
// 假设有一个大数据源,这里使用循环生成一些示例数据
for (let i = 0; i < 10000; i++) {
// 写入数据到可写流
writeStream.write(`这是第 ${i + 1} 行数据\n`);
}
// 在数据写入完成后,关闭可写流
writeStream.end();
// 监听可写流的 'finish' 事件,以便在写入完成后执行其他操作
writeStream.on('finish', () => {
console.log('数据写入完成。');
});
// 监听可写流的 'error' 事件,以处理写入过程中的错误
writeStream.on('error', (err) => {
console.error('写入错误:', err);
});
简单的流式读取的例子
const fs = require('fs');
// 创建一个可读流,指定要读取的文件路径
const readStream = fs.createReadStream('largefile.txt');
// 监听可读流的 'data' 事件,以处理读取到的数据块
readStream.on('data', (chunk) => {
console.log(`读取到 ${chunk.length} 字节的数据块:`);
console.log(chunk.toString()); // 处理数据块的逻辑,这里简单地打印出来
});
// 监听可读流的 'end' 事件,以处理读取结束的情况
readStream.on('end', () => {
console.log('文件读取结束。');
});
// 监听可读流的 'error' 事件,以处理读取过程中的错误
readStream.on('error', (err) => {
console.error('读取错误:', err);
});
文件的重命名和移动
const fs = require('fs');
// 定义原始文件路径和目标文件路径
const oldFilePath = 'oldfile.txt';
const newFilePath = 'newfile.txt';
// 执行文件重命名(移动)操作
fs.rename(oldFilePath, newFilePath, (err) => {
if (err) {
console.error('文件重命名失败:', err);
} else {
console.log('文件重命名成功。');
}
});
文件的删除
const fs = require('fs');
const filePath = '要删除的文件路径.txt';
// 使用 fs.unlink() 方法删除文件
fs.unlink(filePath, (err) => {
if (err) {
console.error(`删除文件时发生错误: ${err}`);
} else {
console.log(`文件 ${filePath} 已成功删除`);
}
});
//注意,再node14.1以后版本中也可以使用fs.rm(filePath, (err) => {})
创建文件夹
const fs = require('fs');
const folderPath = '新文件夹';
fs.mkdir(folderPath, (err) => {
if (err) {
console.error(`创建文件夹时发生错误: ${err}`);
} else {
console.log(`文件夹 ${folderPath} 已成功创建`);
}
});
//递归创建
fs.mkdir( './a/b/c', {recursive: true} ,err => {
if(err) {
console.log('创建失败~');
return;
}
console.log('创建成功');
);
删除文件夹
const fs = require('fs');
const folderPath = '要删除的文件夹';
fs.rmdir(folderPath, (err) => {
if (err) {
console.error(`删除文件夹时发生错误: ${err}`);
} else {
console.log(`文件夹 ${folderPath} 已成功删除`);
}
});
读取文件夹内容
const fs = require('fs');
const folderPath = '要读取的文件夹';
fs.readdir(folderPath, (err, files) => {
if (err) {
console.error(`读取文件夹内容时发生错误: ${err}`);
} else {
console.log(`文件夹 ${folderPath} 中的内容: ${files}`);
}
});
检查文件夹是否存在
const fs = require('fs');
const folderPath = '要检查的文件夹';
if (fs.existsSync(folderPath)) {
console.log(`文件夹 ${folderPath} 存在`);
} else {
console.log(`文件夹 ${folderPath} 不存在`);
}
fs模块查看资源状态
const fs = require('fs');
const resourcePath = '要查看状态的资源路径';
fs.stat(resourcePath, (err, stats) => {
if (err) {
console.error(`获取资源状态时发生错误: ${err}`);
} else {
console.log('资源状态信息:');
console.log(`是否为文件: ${stats.isFile()}`);
console.log(`是否为文件夹: ${stats.isDirectory()}`);
console.log(`文件大小(字节): ${stats.size}`);
console.log(`创建时间: ${stats.ctime}`);
console.log(`最后修改时间: ${stats.mtime}`);
}
});
__dirname 是 Node.js 中的一个特殊变量,它表示当前执行脚本所在的目录的绝对路径
Node.js 中的 path
模块是用于处理文件路径的核心模块之一。它提供了一组方法,用于执行跨平台的路径操作,使你能够轻松地处理文件和目录路径,而不必担心不同操作系统的差异。以下是一些 path
模块的常见用法和方法:
path.join(...paths)
: 这个方法将多个路径片段连接起来,并返回一个标准化的路径。它会自动处理斜杠(/
或\
)以及不同操作系统下的路径分隔符问题。
const path = require('path');
const fullPath = path.join('目录', '子目录', '文件.txt');
console.log(fullPath); // 输出: 目录/子目录/文件.txt(Unix系统)或目录\子目录\文件.txt(Windows系统)
path.resolve(...paths)
: 这个方法从右到左解析路径,直到构建出一个绝对路径。通常用于构建文件的绝对路径。
const path = require('path');
const absolutePath = path.resolve('相对路径', '到文件.txt');
console.log(absolutePath); // 输出: /绝对路径/到文件.txt(Unix系统)或 C:\绝对路径\到文件.txt(Windows系统)
path.dirname(path)
: 返回指定路径的目录名部分。
const path = require('path');
const dirName = path.dirname('/目录/子目录/文件.txt');
console.log(dirName); // 输出: /目录/子目录
path.basename(path, ext)
: 返回指定路径的文件名部分,可以选择是否包含文件扩展名。
const path = require('path');
const fileName = path.basename('/目录/子目录/文件.txt');
console.log(fileName); // 输出: 文件.txt
const baseNameWithoutExt = path.basename('/目录/子目录/文件.txt', '.txt');
console.log(baseNameWithoutExt); // 输出: 文件
path.extname(path)
: 返回指定路径的文件扩展名部分。
const path = require('path');
const extName = path.extname('/目录/子目录/文件.txt');
console.log(extName); // 输出: .txt
path
模块还包括其他方法,用于处理路径、规范化路径、检查路径的绝对性等等。这些方法使得在处理文件和目录路径时更加方便和可靠,尤其在跨不同操作系统的开发中非常有用。
buffer就是一段长度的内存区域
创建buffer
//1. alloc
Let buf = Buffer.alloc(10);//console.log(buf);
//2. allocUnsafe
Let buf_2 = Buffer.allocUnsafe(10);//console.log(buf_2);
//3. from
Let buf_3 = Buffer.from('hello');
Let buf_4 = Buffer.from([ 105,108,111,118,101,121,111,117]);//console.log(buf_4);
请求行
请求头
空行
请求体
//请求行
GET /path/to/resource HTTP/1.1
//请求头
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
//空行
//请求体
请求行:
包含了请求的方法、目标URL和HTTP版本
POST /api/users/login HTTP/1.1
请求头:
包含了关于请求的元信息,例如主机、用户代理、接受的内容类型等
Host: example.com
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64)
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
如何获取请求行、请求头和请求体
const http = require('http');
// 创建HTTP服务器
const server = http.createServer((req, res) => {
// 获取请求行
const requestLine = req.method + ' ' + req.url + ' ' + req.httpVersion;
console.log('请求行:', requestLine);
// 获取请求头部
const requestHeaders = req.headers;
console.log('请求头部:', requestHeaders);
// 定义一个变量来存储请求体数据
let requestBody = '';
// 监听请求的数据事件,以获取请求体数据
req.on('data', (chunk) => {
requestBody += chunk.toString();
});
// 监听请求结束事件,处理请求体数据
req.on('end', () => {
console.log('请求体:', requestBody);
// 响应客户端
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('请求已处理\n');
});
});
// 监听端口
server.listen(3000, () => {
console.log(`服务器运行在 http://localhost:${port}/`);
});
获取路径和查询字符串(方法1)
因为使用req.url返回的是包含路径和查询字符串的一个整体,可以使用
url
模块进一步拆分出路径和查询字符串
const http = require('http');
const url = require('url'); // 引入url模块
// 创建HTTP服务器
const server = http.createServer((req, res) => {
// 获取请求的完整URL
const requestUrl = req.url;
// 使用url模块来解析URL
const parsedUrl = url.parse(requestUrl, true);//true表示将查询字符串转换为对象
// 获取路径和查询字符串
const path = parsedUrl.pathname;
const query = parsedUrl.query;
// 打印路径和查询字符串
console.log('路径:', path);
console.log('查询字符串:', query);
// 响应客户端
res.writeHead(200, { 'Content-Type': 'text/plain' });
res.end('URL已解析\n');
});
// 监听端口
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}/`);
});
获取路径和查询字符串(方法2)
const http = require('http');
// 创建HTTP服务器
const server = http.createServer((req, res) => {
// 获取请求的完整URL
const requestUrl = req.url;
// 使用URL构造函数来解析URL
const parsedUrl = new URL(requestUrl, 'http://127.0.0.1');
// 获取路径和查询字符串
const path = parsedUrl.pathname;
const query = parsedUrl.searchParams;
res.end('URL已解析\n');
});
// 监听端口
server.listen(3000, () => {
console.log(`服务器运行在 http://localhost:3000/`);
});
设置HTTP响应报文
const http = require('http');
// 创建HTTP服务器
const server = http.createServer((req, res) => {
// 设置响应行
res.writeHead(200, { 'Content-Type': 'text/plain' });
// 设置响应头部
res.setHeader('Custom-Header', 'Hello, Custom Header');
// 设置响应体
res.write('Hello, World!\n');
// 结束响应
res.end();
});
// 监听端口
const port = 3000;
server.listen(port, () => {
console.log(`服务器运行在 http://localhost:${port}/`);
});
在Node.js中,一个文件就是一个模块,每个模块具有自己的作用域,可以独立开发、测试和维护。Node.js使用
CommonJS
模块系统来实现模块化。
要创建一个模块,只需在文件中定义变量、函数或对象,然后使用module.exports
将它们导出,以便其他文件可以访问它们。例如,创建一个名为myModule.js
的模块:
// myModule.js
// 定义一个变量
const message = "Hello, World!";
// 定义一个函数
function greet(name) {
return `Hello, ${name}!`;
}
// 导出变量和函数
module.exports.message = message;
module.exports.greet = greet;
要在其他文件中使用模块,可以使用require
函数引入它。引入模块后,你可以访问模块中导出的变量、函数或对象。例如,在另一个文件中使用上面的模块:
// main.js
// 引入模块
const myModule = require('./myModule');
// 使用导出的变量和函数
console.log(myModule.message); // 输出 "Hello, World!"
console.log(myModule.greet("Alice")); // 输出 "Hello, Alice!"
Node.js还提供了一些内置模块,例如fs
(文件系统)、http
(HTTP服务器与客户端)、path
(路径处理)等。这些内置模块可以直接引入和使用,无需额外安装。例如:
const fs = require('fs');
const http = require('http');
const path = require('path');
除了内置模块外,Node.js社区还开发了大量第三方模块,可以通过npm(Node.js包管理器)安装和使用。要使用第三方模块,首先需要安装它,然后可以使用require
函数引入它。例如,安装并使用lodash
模块:
// 安装lodash模块
// npm install lodash
// 在代码中引入lodash模块
const _ = require('lodash');
// 使用lodash的函数
const result = _.sum([1, 2, 3, 4, 5]);
console.log(result); // 输出 15
这些是Node.js模块化的基本概念和示例。模块化是Node.js开发中的核心概念,它有助于组织和管理代码,提高可维护性和可重用性。
基本流程:
**安装包:例如,安装lodash
包:
npm install lodash
这将在项目的node_modules
目录下安装lodash
包,并将其添加到package.json
文件的dependencies
中。
导入包: 使用require
来导入已安装的包。例如:
const _ = require('lodash');
这将导入lodash
包并将其赋值给变量_
,以便你可以在代码中使用它。
使用包: 例如,使用lodash
的map
函数:
const numbers = [1, 2, 3, 4, 5];
const squaredNumbers = _.map(numbers, (num) => num * num);
console.log(squaredNumbers);
在这个示例中,我们使用lodash
包中的map
函数来对数组中的每个元素进行平方运算。
运行代码: 最后,运行你的Node.js代码。你可以使用node
命令来执行你的脚本,例如:
node yourScript.js
这将运行你的代码,并在控制台中输出结果。
内部流程:
当你使用require
导入一个包时,Node.js会按以下顺序查找和加载模块:
首先,Node.js会尝试查找内置模块(例如fs
、http
等)或核心模块,如果找到匹配的模块,它将被加载。
如果没有找到匹配的核心模块,Node.js会查找node_modules
目录。它会从当前模块的目录开始,逐级向上查找,直到找到匹配的模块或到达文件系统的根目录。
在node_modules
目录中,Node.js会查找并加载匹配模块名的目录,然后尝试加载该目录中的package.json
文件。如果找到package.json
文件,Node.js会读取其中的main
字段,该字段指定了模块的入口文件(通常是一个JavaScript文件),然后加载入口文件。
如果没有找到package.json
文件或main
字段,Node.js将默认尝试加载包目录中的index.js
文件。
最终,Node.js会将加载的模块缓存起来,以避免重复加载相同的模块。
Nodemon 是一个Node.js开发的热重载工具,它有助于提高Node.js应用程序的开发效率。Nodemon监视你的Node.js应用程序文件的更改,并在文件发生更改时自动重新启动应用程序,无需手动停止和启动。这对于在开发过程中进行实时调试和测试非常有用,因为它可以减少手动重启应用程序的需求。
设置环境变量是为了在操作系统中存储和访问全局配置信息,以供不同应用程序和系统组件共享和使用。