尚硅谷NodeJs笔记
原视频: 尚硅谷Node.js零基础视频教程,nodejs新手到高手
1.基础
1.1. 基础命令
- node -v 查看版本号
- node hello.js 运行js文件
1.2. 注意事项
Node.js中不能使用BOM和DOM的API
1 | console.log('hello world'); |
说明:浏览器中的javascript语法包括如下内容组成部分
node.js语法的组成部分
2.Buffer(缓冲器)介绍与创建
2.1 概念
Buffer 是一个类似于数组的 对象 ,用于表示固定长度的字节序列
Buffer 本质是一段内存空间,专门用来处理 二进制数据 。
2.2 特点
Buffer 大小固定且无法调整
Buffer 性能较好,可以直接对计算机内存进行操作
每个元素的大小为 1 字节(byte)
2.3 使用
- 创建 Buffer
Node.js 中创建 Buffer 的方式主要如下几种
- Buffer.alloc
- Buffer.allocUnsafe
- Buffer.from
1 | // 创建了一个长度为 10 字节的 Buffer,相当于申请了 10 字节的内存空间,每个字节的值为 0 |
- Buffer 与字符串的转化
toString 方法将 Buffer 转为字符串 (toString 默认是按照 utf-8 编码方式进行转换的。)
1 | let buf_4 = Buffer.from([105, 108, 111, 118, 101, 121, 111, 117]); |
- Buffer 的读写
Buffer 可以直接通过 [] 的方式对数据进行处理。
注意:
如果修改的数值超过 255 ,则超过 8 位数据会被舍弃
一个 utf-8 的中文字符 一般 占 3 个字节
1 | //读取 |
3. fs模块(file system)
fs 全称为 file system ,称之为 文件系统 ,是 Node.js 中的 内置模块 ,可以对计算机中的磁盘进行操
作。
3.1 文件写入
文件写入就是将 数据 保存到 文件 中,我们可以使用如下几个方法来实现该效果
方法 | 说明 |
---|---|
writeFile | 异步写入 |
writeFileSync | 同步写入 |
appendFile / appendFileSync | 追加写入 |
createWriteStream | 流式写入 |
- writeFile 异步写入
语法: fs.writeFile(file, data[, options], callback)
参数说明:file 文件名
data 待写入的数据
options 选项设置 (可选)
callback 写入回调
返回值: undefined
1 | // require 是 Node.js 环境中的'全局'变量,用来导入模块 |
- writeFileSync同步写入
语法:
fs.writeFileSync(file, data[, options])
参数与 fs.writeFile 大体一致,只是没有 callback 参数
返回值:undefined
1 | // require 是 Node.js 环境中的'全局'变量,用来导入模块 |
Node.js 中的磁盘操作是由其他 线程 完成的,结果的处理有两种模式:
同步处理 JavaScript 主线程 会等待 其他线程的执行结果,然后再继续执行主线程的代码,
效率较低
异步处理 JavaScript 主线程 不会等待 其他线程的执行结果,直接执行后续的主线程代码,
效率较好
- appendFile / appendFileSync追加写入
appendFile 作用是在文件尾部追加内容,appendFile 语法与writeFile语法完全相同
语法:
fs.appendFile(file, data[, options], callback)
fs.appendFileSync(file, data[, options])
返回值: 二者都为 undefined
1 | // require 是 Node.js 环境中的'全局'变量,用来导入模块 |
- createWriteStream流式写入
语法: fs.createWriteStream(path[, options])
参数说明:
- path 文件路径
- options 选项配置( 可选 )
- 返回值: Object
1 | // require 是 Node.js 环境中的'全局'变量,用来导入模块 |
程序打开一个文件是需要消耗资源的 ,流式写入可以减少打开关闭文件的次数。
流式写入方式适用于 大文件写入或者频繁写入 的场景, writeFile 适合于 写入频率较低的场景
3.2 文件读取
文件读取顾名思义,就是通过程序从文件中取出其中的数据,我们可以使用如下几种方式
方法 | 说明 |
---|---|
readFile | 异步读取 |
readFileSync | 同步读取 |
createReadStream | 流式读取 |
- readFile 异步读取
语法: fs.readFile(path[, options], callback)
参数说明:
- path 文件路径
- options 选项配置
- callback 回调函数
- 返回值:undefined
1 | var fs = require('fs'); |
- readFileSync 同步读取
语法: fs.readFileSync(path[, options])
参数说明:
- path 文件路径
- options 选项配置
- 返回值: string | Buffer
1 | var fs = require('fs'); |
- createReadStream 流式读取
语法: fs.createReadStream(path[, options])
参数说明:
- path 文件路径
- options 选项配置( 可选 )
- 返回值: Object
1 | var fs = require('fs'); |
3.3 文件移动与重命名
在 Node.js 中,我们可以使用 rename 或 renameSync` 来移动或重命名 文件或文件夹
语法:
- fs.rename(oldPath, newPath, callback)
- fs.renameSync(oldPath, newPath)
参数说明:
- oldPath 文件当前的路径
- newPath 文件新的路径
- callback 操作后的回调(同步)
1 | var fs = require('fs'); |
1 | var fs = require('fs'); |
3.4 文件删除
在 Node.js 中,我们可以使用 unlink 或 unlinkSync 来删除文件
语法:
- fs.unlink(path, callback)
- fs.unlinkSync(path)
参数说明:
- path 文件路径
- callback 操作后的回调
1 | var fs = require('fs'); |
1 | var fs = require('fs'); |
3.5 文件夹操作
借助 Node.js 的能力,我们可以对文件夹进行 创建 、 读取 、 删除 等操作
方法 | 说明 |
---|---|
mkdir / mkdirSync | 创建文件夹 |
readdir / readdirSync | 读取文件夹 |
rmdir / rmdirSync | 删除文件夹 |
mkdir / mkdirSync | 创建文件夹 |
在 Node.js 中,我们可以使用 mkdir 或 mkdirSync 来创建文件夹
语法:
- fs.mkdir(path[, options], callback)
- fs.mkdirSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置( 可选 )
- callback 操作后的回调
1 | var fs = require('fs'); |
1 | var fs = require('fs'); |
1 | var fs = require('fs'); |
1 | var fs = require('fs'); |
- readdir / mkdirSync 读取文件夹
在 Node.js 中,我们可以使用 readdir 或 readdirSync 来读取文件夹
语法:
- fs.readdir(path[, options], callback)
- fs.readdirSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置( 可选 )
- callback 操作后的回调
1 | var fs = require('fs'); |
1 | var fs = require('fs'); |
- rmdir / mkdirSync 删除文件夹
在 Node.js 中,我们可以使用 rmdir 或 rmdirSync 来删除文件夹
语法:
- fs.rmdir(path[, options], callback)
- fs.rmdirSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置( 可选 )
- callback 操作后的回调
1 | var fs = require('fs'); |
3.6 查看资源状态
在 Node.js 中,我们可以使用 stat 或 statSync 来查看资源的详细信息
语法:
- fs.stat(path[, options], callback)
- fs.statSync(path[, options])
参数说明:
- path 文件夹路径
- options 选项配置( 可选 )
- callback 操作后的回调
1 | var fs = require('fs'); |
3.7 相对路径问题
fs 模块对资源进行操作时,路径的写法有两种:
相对路径
./座右铭.txt 当前目录下的座右铭.txt
座右铭.txt 等效于上面的写法
../座右铭.txt 当前目录的上一级目录中的座右铭.txt
绝对路径
D:/Program Files windows 系统下的绝对路径
/usr/bin Linux 系统下的绝对路径
相对路径中所谓的 当前目录 ,指的是 命令行的工作目录 ,而并非是文件的所在目录
所以当命令行的工作目录与文件所在目录不一致时,会出现一些 BUG
3.8 __dirname
dirname 与 require 类似,都是 Node.js 环境中的’全局’变量,dirname 保存着 当前文件所在目录的绝对路径 ,可以使用 dirname 与文件名拼接成绝对路径
let data = fs.readFileSync(dirname + ‘/data.txt’);
3.9 练习复制文件脚本
1 | var fs = require('fs'); |
4.path 模块
path 模块提供了 操作路径 的功能,我们将介绍如下几个较为常用的几个 API:
API | 说明 |
---|---|
path.resolve | 拼接规范的绝对路径 常用 |
path.sep | 获取操作系统的路径分隔符 |
path.parse | 解析路径并返回对象 |
path.basename | 获取路径的基础名称 |
path.dirname | 获取路径的目录名 |
path.extname | 获得路径的扩展名 |
1 | var path = require('path'); |
5.http模块
5.1 使用 nodejs 创建 HTTP 服务
1 | //1. 导入 http 模块 |
http.createServer 里的回调函数的执行时机: 当接收到 HTTP 请求的时候,就会执行
注意事项:
- 命令行 ctrl + c 停止服务
- 当服务启动后,更新代码 必须重启服务才能生效
- 响应内容中文乱码的解决办法response.setHeader(‘content-type’,’text/html;charset=utf-8’);
5.2 HTTP 请求报文
注意事项:
- request.url 只能获取路径以及查询字符串,无法获取 URL 中的域名以及协议的内容
- request.headers 将请求信息转化成一个对象,并将属性名都转化成了『小写』
- 关于路径:如果访问网站的时候,只填写了 IP 地址或者是域名信息,此时请求的路径为『 / 』
- 关于 favicon.ico:这个请求是属于浏览器自动发送的请求
1 | //1. 导入 http 模块 |
5.3 HTTP 响应报文
1 | write 和 end 的两种使用情况: |
1 | //1. 导入 http 模块 |
5.4 静态资源服务
静态资源是指 内容长时间不发生改变的资源 ,例如图片,视频,CSS文件,JS文件,HTML文件,字体文件等
动态资源是指 内容经常更新的资源 ,例如百度首页,网易首页,京东搜索列表页面等
1 | //1. 导入 http 模块 |
5.5 设置资源类型(mime类型)
HTTP 服务可以设置响应头 Content-Type 来表明响应体的 MIME 类型,浏览器会根据该类型决定如何处理资源:
mime 类型结构: [type]/[subType]
常见: text/html text/css image/jpeg image/png application/json
对于未知的资源类型,可以选择 application/octet-stream 类型,浏览器在遇到该类型的响应
时,会对响应体内容进行独立存储,也就是我们常见的 下载 效果
5.6 GET 和 POST 请求场景小结
GET 请求的情况:
- 在地址栏直接输入 url 访问
- 点击 a 链接
- link 标签引入 css
- script 标签引入 js
- img 标签引入图片
- form 标签中的 method 为 get (不区分大小写)
- ajax 中的 get 请求
POST 请求的情况:
- form 标签中的 method 为 post(不区分大小写)
- AJAX 的 post 请求
6.Node.js 模块化
6.1 介绍
- 什么是模块化与模块 ?
将一个复杂的程序文件依据一定规则(规范)拆分成多个文件的过程称之为 模块化,其中拆分出的 每个文件就是一个模块 ,模块的内部数据是私有的,不过模块可以暴露内部数据以便其他模块使用
- 什么是模块化项目 ?
编码时是按照模块一个一个编码的, 整个项目就是一个模块化的项目
- 模块化好处
- 防止命名冲突
- 高复用性
- 高维护性
6.2 初体验
1 | *******************me.js |
6.3 暴漏数据
模块暴露数据的方式有两种:
- module.exports = value
- exports.name = value
1 | *******************me.js |
6.4 导入模块
在模块中使用 require 传入文件路径即可引入文件
require 使用的一些注意事项:
- 对于自己创建的模块,导入时路径建议写 相对路径 ,且不能省略 ./ 和../
- js 和 json 文件导入时可以不用写后缀,c/c++编写的 node 扩展文件也可以不写后缀,但是一般用不到
- 如果导入其他类型的文件,会以js文件进行处理
- 如果导入的路径是个文件夹,则会 首先 检测该文件夹下package.json 文件中 main 属性对应的文件,如果存在则导入,反之如果文件不存在会报错。如果 main 属性不存在,或者 package.json 不存在,则会尝试导入文件夹下的index.js 和index.json,如果还是没找到,就会报错
- 导入 node.js 内置模块时,直接 require 模块的名字即可,无需加 ./ 和 ../
6.5 导入自定义模块的基本流程
这里我们介绍一下 require 导入 自定义模块 的基本流程
- 将相对路径转为绝对路径,定位目标文件
- 缓存检测
- 读取目标文件代码
- 包裹为一个函数并执行(自执行函数)。通过 arguments.callee.toString() 查看自执行函数
- 缓存模块的值
- 返回 module.exports 的值
6.6 CommonJS 规范
module.exports 、 exports 以及 require 这些都是 CommonJS 模块化规范中的内容。而 Node.js 是实现了 CommonJS 模块化规范,二者关系有点像 JavaScript 与 ECMAScript
6.7 ES6模块和CommonJS模块比对
在JavaScript中,import和require都是用来导入模块的方式,但它们属于不同的模块系统,并且主要在ES6模块(ECMAScript 2015及以后版本)和CommonJS模块系统中使用。
- ES6模块(使用import和export)
语法:使用import从其他模块导入绑定(变量、函数、类等),使用export导出绑定以便其他模块可以导入。
静态结构:import和export的语句在编译时解析,这有助于JavaScript引擎进行更好的静态分析和优化(如树摇(tree-shaking))。
语法更简洁:与CommonJS的require和module.exports相比,import和export的语法更简洁、更直观。
默认导出与具名导出:ES6模块支持默认导出(每个模块只能有一个)和具名导出(可以导出多个)。
浏览器支持:原生支持ES6模块的现代浏览器可以直接使用import和export。
- CommonJS模块(使用require和module.exports)
语法:使用require函数来导入模块,使用module.exports或exports来导出模块中的成员。
动态结构:require函数在运行时执行,这意呀着它可以动态地解析依赖。
语法较复杂:与ES6模块的import和export相比,CommonJS的require和module.exports语法略显复杂。
Node.js:Node.js最初实现了CommonJS模块规范,但自Node.js v12起,它开始原生支持ES6模块(尽管需要通过特定的配置或使用.mjs扩展名)。
- 区别总结
语法:import/export vs require/module.exports/exports。
静态与动态:ES6模块是静态的,CommonJS模块是动态的。
浏览器支持:ES6模块在现代浏览器中受到原生支持,而CommonJS模块主要用于Node.js环境(尽管可以通过工具如Browserify或Webpack在浏览器中使用)。
使用场景:新项目倾向于使用ES6模块,因为它们提供了更好的静态分析、更简洁的语法和更广泛的浏览器支持。然而,由于Node.js的广泛使用和大量现有代码库的存在,CommonJS模块仍然非常普遍。
- 混用
在Node.js中,你可以通过特定的配置(如type: “module”在package.json中)来让项目支持ES6模块,但这意味着你需要将所有模块都迁移到ES6模块语法。然而,在单个项目中混用ES6模块和CommonJS模块通常是不推荐的,因为它可能会导致意外的行为和不一致性。
6.8 ES6暴漏数据
在ES6模块中,你可以使用export关键字来导出函数、对象或原始值,以便其他模块可以使用它们。有两种主要的导出方式:默认导出(每个模块只能有一个)和具名导出(可以导出多个)
- 默认导出
1 | - // math.js |
- 具名导出
1 | // math-utils.js |
- 导入默认导出
1 | // app.js |
- 导入具名导出
1 | // app.js |
你也可以使用as关键字为导入的绑定重命名:
1 | import { multiply as mul, subtract } from './math-utils.js'; |
- 导入整个模块
虽然不常见,但你也可以使用星号(*)语法来导入整个模块的内容,但这通常会导致命名冲突,因此不推荐这样做。
1 | // 注意:不推荐这样做,因为它会将math-utils.js中导出的所有内容导入到一个名为mathUtils的对象中 |
6.9 暴漏数据注意事项
浏览器默认不支持ES6模块和commonjs模块
在使用ES6模块时,请确保你的环境(如浏览器或Node.js)支持它们。
在Node.js中,你需要将文件扩展名从.js更改为.mjs,或者在package.json中设置”type”: “module”,以便Node.js将.js文件作为ES6模块处理。
ES6模块是静态解析的,这意味着在编译时就会确定模块的依赖关系,这有助于进行静态分析和优化(如树摇)。
与CommonJS模块不同,ES6模块中的代码只会在被导入时执行一次(即,模块是单例的)。
浏览器通过<script type="module">
标签来识别和处理 ES6 模块。如果你只是使用<script>
标签而不指定 type=”module”,那么浏览器会将其视为传统的脚本,并忽略 ES6 模块的特性。
1
2
3
4 <script type="module">
import sum from './me.js';
console.log(sum(1, 2));
</script>type=”module” 是 HTML
<script>
标签的一个属性,它告诉浏览器该<script>
标签包含的是一个 JavaScript ES6 模块。在 HTML 文档中引入 JavaScript 代码时,通常使用<script>
标签,而默认情况下,浏览器会将
7 包管理
7.1 介绍
- 包是什么
『包』英文单词是 package ,代表了一组特定功能的源码集合
- 包管理工具
管理『包』的应用软件,可以对「包」进行 下载安装 , 更新 , 删除 , 上传 等操作借助包管理>工具,可以快速开发项目,提升开发效率包管理工具是一个通用的概念,很多编程语言都有包管理工具,所以 掌握好包管理工具非常重要
常用的包管理工具
下面列举了前端常用的包管理工具
npm
yarn
cnpm
7.2 npm
npm 全称 Node Package Manager,翻译为中文意思是『Node 的包管理工具』
npm 是 node.js 官方内置的包管理工具,是 必须要掌握住的工具
7.2.1 npm的安装 npm -v
node.js 在安装时会 自动安装 npm ,所以如果你已经安装了 node.js,可以直接使用 npm
可以通过 npm -v 查看版本号测试,如果显示版本号说明安装成功,反之安装失败
7.2.2 初始化: npm init (下载包前要初始化)
创建一个空目录,然后以此目录作为工作目录 启动命令行工具 ,执行 npm init
npm init 命令的作用是将文件夹初始化为一个『包』, 交互式创建 package.json 文件
package.json 是包的配置文件,每个包都必须要有 package.json
package.json 内容示例:
1
2
3
4
5
6
7
8
9
10
11 {
"name": "1-npm", #包的名字
"version": "1.0.0", #包的版本
"description": "", #包的描述
"main": "index.js", #包的入口文件
"scripts": { #脚本配置
"test": "echo \"Error: no test specified\" && exit 1"
},
"author": "", #作者
"license": "ISC" #开源证书
}
初始化的过程中还有一些注意事项:
- package name ( 包名 ) 不能使用中文、大写,默认值是 文件夹的名称 ,所以文件夹名称也不能使用中文和大写
- version ( 版本号 )要求 x.x.x 的形式定义,x必须是数字,默认值是 1.0.0
- ISC 证书与 MIT 证书功能上是相同的,关于开源证书扩展阅读 http://www.ruanyifeng.com/blog/2011/05/how_to_choose_free_software_licenses.html
- package.json 可以手动创建与修改
- 使用 npm init -y 或者 npm init –yes 极速创建 package.json
7.2.3 搜索包
- 搜索包的方式有两种
- 命令行『npm s/search 关键字』 eg:npm s uniq
- 网站搜索 网址是 https://www.npmjs.com/
7.2.4 下载&删除安装包
1 | ## 格式 |
运行之后文件夹下会增加两个资源
- node_modules 文件夹 存放下载的包
- package-lock.json 包的锁文件 ,用来锁定包的版本
安装 uniq 之后, uniq 就是当前这个包的一个 依赖包 ,有时会简称为 依赖
比如我们创建一个包名字为 A,A 中安装了包名字是 B,我们就说 B 是 A 的一个依赖包 ,也会说
A 依赖 B
7.2.4.1 安装包报错处理
- ssl认证问题
npm set strict-ssl=false
7.2.5 require 导入 npm 包基本流程
在当前文件夹下 node_modules 中寻找同名的文件夹
在上级目录中下的 node_modules 中寻找同名的文件夹,直至找到磁盘根目录
总结
- require导入内置模块 require(‘http’)
- require导入自定义模块require(‘./aa.js’)
- require导入npm包 require(‘uniq’)
7.2.6 生产环境与开发环境
开发环境是程序员 专门用来写代码 的环境,一般是指程序员的电脑,开发环境的项目一般 只能程序员自己访问
生产环境是项目 代码正式运行 的环境,一般是指正式的服务器电脑,生产环境的项目一般 每个客户都可以访问
7.2.7 生产依赖与开发依赖
我们可以在安装时设置选项来区分 依赖的类型 ,目前分为两类:
类型 | 命令 | 补充 |
---|---|---|
生产依赖 | npm i -S uniq npm i -S uniq |
-S 等效于 –save, -S 是默认选项 包信息保存在 package.json 中 dependencies 属性 |
开发依赖 | npm i -D less npm i –save-dev less |
-D 等效于 –save-dev 包信息保存在 package.json 中 devDependencies 属性 |
举个例子方便大家理解,比如说做蛋炒饭需要 大米 , 油 , 葱 , 鸡蛋 , 锅 , 煤气 , 铲子 等
其中 锅 , 煤气 , 铲子 属于开发依赖,只在制作阶段使用
而 大米 , 油 , 葱 , 鸡蛋 属于生产依赖,在制作与最终食用都会用到
所以 开发依赖 是只在开发阶段使用的依赖包,而 生产依赖 是开发阶段和最终上线运行阶段都用到
的依赖包
7.2.8 全局安装
我们可以执行安装选项 -g 进行全局安装
1 | npm i -g nodemon # nodemon http.js 热启动命令 |
注意,也可以局部安装,但是使用nodemon需要使用 npx nodemon http.js临时运行安装在项目中的 nodemon,而不需要全局安装
全局安装完成之后就可以在命令行的任何位置运行 nodemon 命令,该命令的作用是 自动重启 node 应用程序
说明:
全局安装的命令不受工作目录位置影响
可以通过 npm root -g 可以查看全局安装包的位置
不是所有的包都适合全局安装 , 只有全局类的工具才适合,可以通过 查看包的官方文档来确定
安装方式 ,这里先不必太纠结
7.2.9 安装包依赖
在项目协作中有一个常用的命令就是 npm i ,通过该命令可以依据 package.json 和 package-lock.json 的依赖声明安装项目依赖
node_modules 文件夹大多数情况都不会存入版本库
npm i
npm install
7.2.10 安装指定版本的包
项目中可能会遇到版本不匹配的情况,有时就需要安装指定版本的包,可以使用下面的命令的
npm i <包名@版本号>
npm i jquery@1.11.2
7.2.11 配置命令别名
通过配置命令别名可以更简单的执行命令
配置 package.json 中的 scripts 属性
1 | { |
- 配置完成之后,可以使用别名执行命令
npm run server
npm run start
不过 start 别名比较特别,使用时可以省略 run
npm start
补充说明:
npm start 是项目中常用的一个命令,一般用来启动项目
npm run 有自动向上级目录查找的特性,跟 require 函数也一样
对于陌生的项目,我们可以通过查看 scripts 属性来参考项目的一些操作
7.2.12 安装cnpm
- 方式一:通过 npm 来安装 cnpm 工具
1 | # 直接安装cnpm命令, 原来npm命令并不变,使用cnpm才会去淘宝进行加载 |
- 方式二:npm 配置淘宝镜像 (npm配置淘宝镜像比cnpm命令快一些)
1 | # 修改npm的镜像配置--直接配置(使用npm即用的淘宝镜像) |
- 方式三:npm 使用工具进行切换(nrm)
1 | - npm install -g nrm |
补充说明:
建议使用第二种方式 进行镜像配置,因为后续修改起来会比较方便
虽然 cnpm 可以提高速度,但是 npm 也可以通过淘宝镜像进行加速,所以 npm 的使用率还 是高于 cnpm
7.3 yarn
7.3.1 yarn介绍
yarn 是由 Facebook 在 2016 年推出的新的 Javascript 包管理工具,官方网址: https://yarnpkg.com/
- yarn特点
yarn 官方宣称的一些特点
- 速度超快:yarn 缓存了每个下载过的包,所以再次使用时无需重复下载。 同时利用并行下载以最大化资源利用率,因此安装速度更快
- 超级安全:在执行代码之前,yarn 会通过算法校验每个安装包的完整性
- 超级可靠:使用详细、简洁的锁文件格式和明确的安装算法,yarn 能够保证在不同系统上无差异的工作
7.3.2 yarn安装
我们可以使用 npm 安装 yarn
npm i -g yarn
7.3.3 yarn常用命令
功能 | 命令 |
---|---|
初始化 | yarn init / yarn init -y |
安装包 | yarn add uniq 生产依赖 yarn add less –dev 开发依赖 yarn global add nodemon 全局安装 |
删除包 | yarn remove uniq 删除项目依赖包 yarn global remove nodemon 全局删除包 |
安装项目依赖 | yarn |
运行命令别名 | yarn <别名> # 不需要添加 run |
7.3.4 yarn 配置淘宝镜像
1 | yarn config set registry https://registry.npmmirror.com/ |
7.4 npm 和 yarn 选择
大家可以根据不同的场景进行选择
- 个人项目
如果是个人项目, 哪个工具都可以 ,可以根据自己的喜好来选择- 公司项目
如果是公司要根据项目代码来选择,可以通过锁文件判断 项目的包管理工具
npm 的锁文件为 package-lock.json
yarn 的锁文件为 yarn.lock
包管理工具 不要混着用,切记,切记,切记
7.6 发布包
我们可以将自己开发的工具包发布到 npm 服务上,方便自己和其他开发者使用,操作步骤如下:
- 创建文件夹,并创建文件 index.js, 在文件中声明函数,使用 module.exports 暴露
- npm 初始化工具包,package.json 填写包的信息 (包的名字是唯一的)
- 注册账号 https://www.npmjs.com/signup
- 激活账号 ( 一定要激活账号 )(chenyj123)
- 修改为官方的官方镜像 (命令行中运行
nrm use npm
)- 命令行下 npm login 填写相关用户信息
- 命令行下 npm publish 提交包 👌 (chenyj_math)
7.7 更新包
后续可以对自己发布的包进行更新,操作步骤如下
- 更新包中的代码
- 测试代码是否可用
- 修改 package.json 中的版本号 (一定要修改,远端已经存在之前版本,也可删除重新发布)
- 发布更新 (npm publish)
7.8 删除包
执行如下命令删除包
npm unpublish –force
删除包需要满足一定的条件,
https://docs.npmjs.com/policies/unpublish
你是包的作者
发布小于 24 小时
大于 24 小时后,没有其他包依赖,并且每周小于 300 下载量,并且只有一个维护者 (写的哪个版本,就会删除哪个版本)
7.9 扩展内容
在很多语言中都有包管理工具,比如:
除了编程语言领域有包管理工具之外,操作系统层面也存在包管理工具,不过这个包指的是『 软件包 』
8.nvm
8.1 介绍&安装使用
nvm 全称 Node Version Manager 顾名思义它是用来管理 node 版本的工具,方便切换不同版本的Node.js
nvm 的使用非常的简单,跟 npm 的使用方法类似
下载安装
首先先下载 nvm,下载地址 https://github.com/coreybutler/nvm-windows/releases ,
选择 nvm-setup.exe 下载即可(网络异常的小朋友可以在资料文件夹中获取)
切换镜像源:
nvm node_mirror https://npmmirror.com/mirrors/node/
nvm npm_mirror https://npmmirror.com/mirrors/npm/
8.2 常用命令
9.express
9.1 express 介绍
express 是一个基于 Node.js 平台的极简、灵活的 WEB 应用开发框架,官方网址: https://www.expressjs.com.cn/
简单来说,express 是一个封装好的工具包,封装了很多功能,便于我们开发 WEB 应用(HTTP 服务)
9.2 express 使用
9.2.1 初体验
- 下载
express 本身是一个 npm 包,所以可以通过 npm 安装
npm init
npm i express
- js代码
1 | var express = require('express'); |
启动
1
2
3`node <文件名>`
或者
`nodemon <文件名>`然后在浏览器就可以访问 http://127.0.0.1:3000/home 👌
9.2.2 express 路由
官方定义: 路由确定了应用程序如何响应客户端对特定端点的请求
一个路由的组成有 请求方法 , 路径 和 回调函数 组成
express 中提供了一系列方法,可以很方便的使用路由,使用格式如下:app.(path,callback)
1 | var express = require('express'); |
- 注意:验证post的方法,目前已知有ajax 及 表单,验证html如下
1 |
|
9.2.3 获取请求参数
express 框架封装了一些 API 来方便获取请求报文中的数据,并且兼容原生 HTTP 模块的获取方式
1 | app.get('/login',(req,res)=>{ |
9.2.4 获取路由参数
eg:https://npcitem.jd.hk/10051796795661.html , 取得10051796795661参数
1 | var express = require('express'); |
9.2.5 相应设置参数
1 | //获取请求的路由规则 |
9.3 express 中间件
中间件(Middleware)本质是一个回调函数
中间件函数 可以像路由回调一样访问 请求对象(request) , 响应对象(response)
中间件的作用 就是 使用函数封装公共操作,简化代码
9.3.1 定义全局中间件
每一个请求 到达服务端之后 都会执行全局中间件函数
1 | let recordMiddleware = function(request,response,next){ |
9.3.2 多个全局中间件
1 | app.use(function (request, response, next) { |
9.3.3 定义路由中间件
如果 只需要对某一些路由进行功能封装 ,则就需要路由中间件
1 | app.get('/路径',`中间件函数`,(request,response)=>{ |
9.4 静态资源中间件
express 内置处理静态资源的中间件
1 | //引入express框架 |
注意事项:
index.html 文件为默认打开的资源
如果静态资源与路由规则同时匹配,谁先匹配谁就响应
路由响应动态资源,静态资源中间件响应静态资源
9.5 获取请求体数据body-parser
获取请求体数据 body-parser
- 安装&导包
npm i body-parser
const bodyParser = require(‘body-parser’);
- 获取中间件函数
//处理 querystring 格式的请求体
let urlParser = bodyParser.urlencoded({extended:false});
//处理 JSON 格式的请求体
let jsonParser = bodyParser.json();
- 设置路由中间件,然后使用 request.body 来获取请求体数据
1 | app.post('/login', urlParser, (request,response)=>{ |
9.6 图片防盗链
1 | var express = require('express'); |
9.7 Router
9.7.1 Router 介绍
express 中的 Router 是一个完整的中间件和路由系统,可以看做是一个小型的 app 对象。对路由进行模块化,更好的管理路由
9.7.2 Router 使用
- 创建独立的 JS 文件(homeRouter.js)
1 | //1. 导入 express |
- 主文件
1 | const express = require('express'); |
9.8 EJS模板引擎
模板引擎是分离 用户界面和业务数据 的一种技术 (分离html和js)
9.8.1 什么是 EJS
EJS 是一个高效的 Javascript 的模板引擎
官网: https://ejs.co/
中文站: https://ejs.bootcss.com/
1 | //1.安装ejs |
9.8.2 EJS常用语法
执行JS代码
<% code %>
输出转义的数据到模板上
<%= code %>
输出非转义的数据到模板上
<%- code %>
9.8.3 express中使用EJS
npm i ejs
- home.ejs
1 |
|
- 15_模板引擎_express中使用ejs.js
1 | var express = require('express'); |
9.8.4 express-generator
npm install -g express-generator 全局安装命令
express -h 查看帮助
express -e <目录名> 或 –view =ejs <目录名> 当前目录或指定目录初始化可直接创建)
express i 安装依赖
npm start 启动
9.8.5 文件上传
1 | <form method="post" action="./fileDeal" enctype="multipart/form-data"> |
9.8.6 文件处理
- 引入包npm i formidable@2.1.2 (高版本会报错)
- formidable
1 | var express = require('express'); |
10.Mongodb
10.1 介绍
MongoDB 是一个基于分布式文件存储的数据库(并不是单纯的内存数据库),官方地址 https://www.mongodb.com/
操作语法与 JavaScript 类似,容易上手,学习成本低
Mongodb 中有三个重要概念需要掌握
数据库(database) 数据库是一个数据仓库,数据库服务下可以创建很多数据库,数据库中可以存放很多集合
集合(collection) 集合类似于 JS 中的数组,在集合中可以存放很多文档
文档(document) 文档是数据库中的最小单位,类似于 JS 中的对象
10.2 下载与启动
下载地址: https://www.mongodb.com/try/download/community
建议选择 zip 类型, 通用性更强配置步骤如下:
- 将压缩包移动到 C:\Program Files 下,然后解压
- 创建 C:\data\db 目录,mongodb 会将数据默认保存在这个文件夹
- 以 mongodb 中 bin 目录作为工作目录,启动命令行
- 运行命令 mongod
- 访问http://localhost:27017 测试 或启动客户端工具mongo.exe工具
自定义配置启动:
新建data log etc 3个目录
在etc下新建mongodb.conf配置文件
db存放的目录
dbpath=D:\mongodb-windows-x86_64-5.0.24\mongodb-win32-x86_64-windows-5.0.24\data
后台启动需要配置日志输出
logpath=D:\mongodb-windows-x86_64-5.0.24\mongodb-win32-x86_64-windows-5.0.24\log\mongodb.log
运行命令启动
mongod –config D:\mongodb-windows-x86_64-5.0.24\mongodb-win32-x86_64-windows-5.0.24\etc\mongodb.conf
10.3 命令行交互
- 数据库操作
显示所有的数据库
show dbs
切换到指定的数据库,如果数据库不存在会自动创建数据库(刚创建不会显示,只有加入数据,才会创建)
use 数据库名
显示当前所在的数据库
db
删除当前数据库
use 库名
db.dropDatabase()
- 集合操作
创建集合
db.createCollection(‘集合名称’)
显示当前数据库中的所有集合
show collections
删除某个集合
db.集合名.drop()
重命名集合
db.集合名.renameCollection(‘newName’)
- 文档操作
插入文档
db.集合名.insert(文档对象);
查询文档
db.集合名.find(查询条件)
_id 是 mongodb 自动生成的唯一编号,用来唯一标识文档
更新文档
db.集合名.update(查询条件,新的文档) 默认全部子弹更新
db.集合名.update({name:’张三’},{$set:{age:19}}) 指定字段更新
删除文档
db.集合名.remove(查询条件)
update 方法默认只会更新符合查询条件的第一条文档。这是因为在进行更新操作时,MongoDB默认只会更新匹配的第一条文档,除非你显式指定 multi: true 选项,这样才会更新所有匹配的文档。例如,你可以这样使用 update 方法来更新所有匹配的文档:
db.集合名.update(查询条件, 更新操作, { multi: true })
10.4 mongoose
Mongoose 是一个对象文档模型库,官网 http://www.mongoosejs.net/
方便使用代码操作 mongodb 数据库
npm i mongoose@5.13.15
10.4.1 初步使用
1 | //1. 安装 mongoose |
10.4.2 字段类型
10.4.3 字段值验证
Mongoose 有一些内建验证器,可以对字段值进行验证
- 必填项
1 | title: { |
- 默认值
1 | author: { |
- 枚举值
1 | gender: { |
- 唯一值
1 | username: { |
1 | let BookSchema = new mongoose.Schema({ |
10.4.4 CURD
数据库的基本操作包括四个,增加(create),删除(delete),修改(update),查(read)
- 增加
1 | // 插入一条 |
- 删除
1 | // 删除一条数据 |
- 更新
1 | // 更新一条数据 |
- 查询
1 | // 查询一条数据 |
10.4.5 条件控制
- 运算符
在 mongodb 不能 > < >= <= !== 等运算符,需要使用替代符号
使用 $gt
< 使用 $lt
= 使用 $gte
<= 使用 $lte
!== 使用 $ne
db.students.find({id:{$gt:3}}); id号比3大的所有的记录
- 逻辑运算
$or 逻辑或的情况
db.students.find({KaTeX parse error: Expected ‘EOF’, got ‘}’ at position 23: …e:18},{age:24}]}̲);and 逻辑与的情况db.students.find({$and: [{age: {$lt:20}}, {age: {$gt: 15}}]});正则匹配条件中可以直接使用 JS 的正则语法,通过正则可以进行模糊查询db.students.find({name:/imissyou/});
10.4.6 个性化读取
- 字段筛选
1 | //0:不要的字段 |
- 数据排序
1 | //sort 排序 |
- 数据截取
1 | //skip 跳过 limit 限定 |
10.4.7 图形化管理工具
我们可以使用图形化的管理工具来对 Mongodb 进行交互,这里演示两个图形化工具
Robo 3T 免费 https://github.com/Studio3T/robomongo/releases
Navicat 收费 https://www.navicat.com.cn/
11.接口
11.1 RESTful API
RESTful API 是一种特殊风格的接口,主要特点有如下几个:
- URL 中的路径表示 资源 ,路径中不能有 动词 ,例如 create , delete , update 等这些都不能有
- 操作资源要与 HTTP 请求方法 对应
- 操作结果要与 HTTP 响应状态码 对应
扩展阅读: https://www.ruanyifeng.com/blog/2014/05/restful_api.html
11.2 json-server
json-server 本身是一个 JS 编写的工具包,可以快速搭建 RESTful API 服务
官方地址: https://github.com/typicode/json-server
操作步骤:
全局安装 json-server
npm i -g json-server
创建 JSON 文件(db.json),编写基本结构
以 JSON 文件所在文件夹作为工作目录 ,执行如下命令
json-server –watch db.json
1 | { |
12.会话控制
所谓会话控制就是 对会话进行控制
HTTP 是一种无状态的协议,它没有办法区分多次的请求是否来自于同一个客户端, 无法区分用户
而产品中又大量存在的这样的需求,所以我们需要通过 会话控制 来解决该问题.
常见的会话控制技术有三种:
- cookie
- session
- token
12.1 cookie
- cookie 是什么
cookie 是 HTTP 服务器发送到用户浏览器并保存在本地(浏览器)的一小块数据
cookie 是保存在浏览器端的一小块数据
cookie 是按照域名划分保存的
浏览器向服务器发送请求时,会自动将 当前域名下 可用的 cookie 设置在请求头中,然后传递给服务器
这个请求头的名字也叫 cookie ,所以将cookie 理解为一个 HTTP 的请求头也是可以的
不同浏览器中的 cookie 是相互独立的,不共享
- express中使用cookie
- 设置
1 | //设置 cookie |
- 删除
1 | //删除cookie |
- 获取
1 | npm -i cookie-parser |
12.2 session
session 是保存在 服务器端的一块儿数据 ,保存当前访问用户的相关信息
实现会话控制,可以识别用户的身份,快速获取当前用户的相关信息
1 | var express = require('express'); |
12.3 session和cookie的区别
cookie 和 session 的区别主要有如下几点
- 存在的位置
- cookie:浏览器端
- session:服务端
- 安全性
- cookie 是以明文的方式存放在客户端的,安全性相对较低
- session 存放于服务器中,所以安全性 相对 较好
- 网络传输量
- cookie 设置内容过多会增大报文体积, 会影响传输效率
- session 数据存储在服务器,只是通过 cookie 传递 id,所以不影响传输效率
- 存储限制
- 浏览器限制单个 cookie 保存的数据不能超过 4K ,且单个域名下的存储数量也有限制
- session 数据存储在服务器中,所以没有这些限制
12.4 token
token 是服务端生成并返回给 HTTP 客户端的一串加密字符串, token 中保存着 用户信息
实现会话控制,可以识别用户的身份,主要用于移动端 APP
- token 的特点
- 服务端压力更小
- 数据存储在客户端
- 相对更安全
- 数据加密
- 可以避免 CSRF(跨站请求伪造)
- 扩展性更强
- 服务间可以共享
- 增加服务节点更简单
12.4.1 JWT
JWT(JSON Web Token )是目前最流行的跨域认证解决方案,可用于基于 token 的身份验证 , JWT 使token的生成与校验更规范
我们可以使用 jsonwebtoken 包 来操作 token
扩展阅读: https://www.ruanyifeng.com/blog/2018/07/json_web_token-tutorial.html
13.模块工具使用
压缩文件archiver: https://blog.csdn.net/X1432564581/article/details/106398056