NodeJS
2022-10-28 08:45:46 2 举报
AI智能生成
整理了NodeJS+Express+Webpack的知识体系
作者其他创作
大纲/内容
基础入门<br>
技术前提
HTML
CSS
浏览器JavaScript
ECMAScript
WebAPI
DOM
BOM
知识回顾<br>
JavaScript解析引擎
Chrome:V8(性能最好)
Firefox:OdinMonkey(奥丁猴)
Safri:JSCore
IE:Chakra
浏览器运行环境
Chrome为例
NodeJS是什么<br>
Node.js是一个基于 Chrome V8 引擎的 JavaScript 运行环境
弥补JavaScript的后端开发能力
什么是后端开发语言
Java
Python
PHP
C++<br>
官网:http://nodejs.cn/
注意<br>
浏览器是JavaScript的前端运行环境
NodeJS是JavaScript的后端运行环境
所以NodeJS无法调用DOM和BOM等浏览器内置的API
NodeJS可以做什么
本身只是运行环境,提供了基础的功能和API
更多强大的功能由工具和框架完成
Express<br>
可以快速构建Web应用的框架
官网:https://www.expressjs.com.cn/
Electron
可以构建跨平台的桌面应用
官网:https://www.electronjs.org/
Restify
可以快速构建API接口项目
官网:http://restify.com/
Mongoose
处理NodeJS与mongodb<br>
官网:http://www.mongoosejs.net/
NodeJS下载与安装
官网下载:http://nodejs.cn/
了解LTS和Current版本的区别<br>
LTS长期稳定版本
Current为新特性尝鲜版本,可能会有Bug或安全性漏洞
安装
基本都是下一步
注意选择安装位置
安装路径不要有中文
环境变量配置
定义系统变量<br>
在path中添加
检测NodeJS版本<br>
打开CMD
输入node -v<br>
NVM<br>
全称:Node Version Manager<br>
主要用来管理NodeJS版本,可以方便的切换不同的NodeJS版本
下载安装<br>
https://github.com/coreybutler/nvm-windows/releases
安装之前执行,npm uninstall nvm -g。确保删除了npm下载的nvm
安装步骤基本都是下一步,最后配置环境变量,一般也会自动配置
配置下载源
nvm node_mirror https://npm.taobao.org/mirrors/node/<br>nvm npm_mirror https://npm.taobao.org/mirrors/npm/
常用命令
nvm v或version:查看当前的nvm版本<br>
nvm list:列出所有安装的版本
nvm list installed<br>
nvm list available:列出所有远程服务器的版本
nvm install
npm install 12<br>
npm install 具体版本号<br>
nvm uninstall 具体版本号
卸载指定的版本<br>
nvm uninstall 12.22.12
nvm use 具体版本号
切换使用指定的版本node
nvm use 14.20.0
nvm current:显示当前的版本
HelloWorld示例<br>
创建Helloworld.js<br>
编写一个简单的log语句
打开终端,进入到js所在的目录<br>
开始->运行,输入CMD<br>
文件资源管理器地址栏,输入CMD<br>
按住Shift,在文件资源管理器空白处,右键
PowerShell和CMD都可以。或者其它第三方终端软件
输入node Helloworld.js<br>
常用终端命令
cd 目录名<br>
进入指定的目录
cd 绝对路径<br>
此处需要注意,如果切换到不同盘,需要使用盘符:,切换,才有效<br>
cd ..<br>
返回上一级目录
dir/ls
列举当前目录下的所有文件及文件夹<br>
ls是Linux下的
tap键
自动补全
上下键
切换历史命令
window盘符切换:盘符:
例如:d:,就可以换切到d盘<br>
ctrl + c<br>
中断正在执行的命令<br>
内置模块
官方文档<br>
http://nodejs.cn/api/
http://nodejs.cn/learn
https://nodejs.org/en/docs/
FS文件系统模块
require("fs")导入
回调方法
readFile(path [, options], callback):读取指定的文件内容<br>
path:必选参数,字符串,文件的路径
相对路径<br>
以node命令执行的目录做为参照路径,不是文件的路径<br>
绝对路径
options:可选参数,指定读取文件的编码格式
"utf-8"<br>
callback:必选参数,读取成功的回调函数,有err和dataStr两个参数
writeFile(path, data[, options], callback):向指定文件中写入内容
path:必选参数,字符串,文件的路径
data:必选参数,写入的数据
options:可选参数,写入的编码格式
callback:必选参数,回调函数
appendFile(path, data[, options], callback):向指定文件中附加内容
path:必选参数,字符串,文件的路径
data:必选参数,写入的数据
options:可选参数,写入的编码格式
callback:必选参数,回调函数
mkdir(path[, options], callback)
path
options
{ recursive: true }:允许创建多层级目录
callback
err
readdir(path[, options], callback)
读取目录<br>
stat(path[, options], callback)
读取文件或目录状态
path
options
callback
err
stats
isFile(): boolean<br>
isDirectory(): boolean
同步方法
与异步方法的名称前面一致,后以Sync结尾,参数没有回调函数<br>
练习:依次读取名为1, 2, 3这三个txt文件<br>
支持promise方法<br>
let fs = require("fs");<br>let fsPromises = fs.promises;//使用支持promise的api
相对路径带来一个很麻烦问题<br>
cd 0719 && node XXX.js<br>
node 0719/XXX.js<br>
注意:nodejs中的代码的相对路径是以node命令执行的目录为参照<br>
期约:Promise<br>
Promise 是异步编程的一种解决方案,比传统的解决方案“回调函数和事件”更合理和更强大。<br><br>所谓Promise,简单说就是一个容器,里面保存着某个未来才会结束的事件(通常是一个异步操作)的结果。<br><br>从语法上说,Promise 是一个对象,从它可以获取异步操作的消息。
解决了回调地狱<br>
回调函数中有回调,嵌套三次以上,那么就可以称为回调地狱
三种状态<br>
待定(pending):初始状态,既没有被兑现,也没有被拒绝。
已兑现(fulfilled):意味着操作成功完成。
已拒绝(rejected):意味着操作失败。
流程图
<br>
构造函数
new <T>(executor: (resolve: (value: T | PromiseLike<T>) => void, reject: (reason?: any) => void) => void): Promise<T>;
executor回调函数
resolve(data):成功执行的回调函数
触发then
reject(reason):失败或出错时执行的回调函数
触发catch
一个Promise对象只能有一个结果,那这个结果是由 resolve 或 reject 回调产生,由实际情况<br>
练习,将 fs 模块中的回调函数 readFile 改造为支持 Promise 的用法<br>
实例方法
then(回调函数)
当Promise执行resolve回调函数时,触发then
catch(回调函数)
当Promise执行reject回调函数时,触发catch
finally()
不管成功或失败都会执行
静态方法
Promise.all(iterable)
iterable 一般传一个数组,里面的值可以是Promise对象,也可以不是
如果iterable中都是成功兑现,那么执行then(),否则执行catch()<br>
只要有一个reject就会终止<br>
四个打麻将,有一个突然说不打了,那就解散
Promise.allSettled(iterable)
等到所有 promise 都已敲定(每个 promise 都已兑现或已拒绝)。
不管有没有失败的最后都在then中处理<br>
是否去聚餐,所有人都问了一遍都表态了,不管去不去,这个事件都结束了<br>
Promise.any(iterable)
接收一个 promise 对象的集合,当其中的任意一个 promise 成功,就返回那个成功的 promise 的值。
只要有一个成功就触发then
要求版本NodeJS版本在15以上
Promise.race(iterable)
等到任意一个 promise 的状态变为已敲定。不管是兑现还是拒绝
就像问题抢答,只要有人第一时间举手,不管答对还是答错,问题都结束了<br>
Promise.reject(reason)
返回一个状态为已拒绝的 Promise 对象,并将给定的失败信息传递给对应的处理函数。并将结果传给 catch 方法
Promise.resolve(value)
返回的 Promise 对象状态为已兑现,并且将该 value 传递给对应的 then 方法
支持链式写法
Promise 中的 then 是一种微任务<br>
异步函数:async/await
async
- async 是一个修饰符, async 修饰的函数叫做异步函数。但其中的代码都是同步代码<br>
await
注意:await 只能在 async 函数中使用,但 async 函数中不一定要有 await<br>
注意:const c = await Promise.reject(300);会报错。因为await无法处理reject
宏任务和微任务
两者都是异步代码,在同一个任务中,但是微任务比宏任务先执行<br>
宏任务
setTimeout、setInterval、UI更新(dom操作),setImmediate()
异步 AJAX 请求<br>
文件读取操作<br>
微任务<br>
Promise的then、catch、finally
await 后面的语句<br>
process.nextTick
MutationObserver
在Express无法捕获await代码的错误
解决办法
try-catch
练习<br>
一<br>
二
三<br>
Global模块
全局变量模块
__dirname
是两个下划线开头
当前执行的js文件路径的目录
__filename
当前执行的js文件路径
参考资料
https://nodejs.org/dist/latest-v14.x/docs/api/globals.html
path路径系统模块
关于文件读取的相对路径问题<br>
以执行node命令的窗口为参照<br>
解决方案
拼写绝对路径<br>
__dirname:当前文件所在的目录
path.join([...paths])
require("path")
常用方法
path.join([...paths])
反正一个路径拼接字符串
需要配合__dirname,才能转换路径
path.resovle([...paths])
返回一个绝对路径<br>
效果与 path.join(__dirname, "./") 类似<br>
path.basename(path[, ext])
获取文件名称,如果输入了ext可以去除后缀名
path.dirname(path)
获取目录名称
path.extname(path)
获取后缀名
path.isAbsolute(path)
判断是否是绝对路径
练习
获取文件名称,不包含后缀名,支持任务后缀名文件,比如["1.txt","2.ext", "3.js"]<br>输入结果是1, 2, 3
练习:搜索当前项目下的js文件,并输出名字,不包含后缀名<br>
思路<br>
如何获取项目下的目录及文件<br>
获取一个项目下所有JS文件<br>
获取子目录下的JS
使用递归来获取所有子目录下的JS文件
扩展,将所有搜索到的JS文件放到一个Map对象中,且文件名(不含后缀名)为key,文件路径为value<br>
assert模块
断言
引入
const assert = require('assert');
常用方法<br>
assert( 条件表达式, false显示错误信息);
assert.ok( 条件表达式, false显示错误信息);
assert.equal(actual, expected, [message])
assert.notEqual(actual, expected, [message])
assert.deepEqual(actual, expected, [message])
assert.notDeepEqual(actual, expected, [message])
assert.strictEqual(actual, expected, [message])
assert.notStrictEqual(actual, expected, [message])
http模块
客户端与服务器
<br>
http模块的作用:提供Http服务
创建一个简单的web服务器
导入http模块
require("http")
创建web服务实例
createServer()
绑定request事件
req:请求对象
url:请求资源路径及参数
method:请求方式
headers:请求头信息
res:响应对象
end("响应内容")
如果是对象,可以通过 JSON 中的 stringify() 格式化<br>
res.setHeader("Content-Type", "text/html; charset=utf-8");
中文乱码解决
writeHead(http状态码)
200:成功
404:资源未找到
5XX:服务端错误
4XX:客户端错误
3XX:重定向
启动服务器
server.listen(端口号, 回调函数)
ip地址:找电脑的
端口号:找电脑上的程序的<br>
如何停止服务器
Ctrl + C。光标一定要在终端中<br>
练习<br>
不同url响应不同内容
实现默认响应login.html<br>
响应html文件内容,结合path及fs模块完成
url处理
url模块
解析url地址
引入
require("url")
parse(string, boolean):将string转换为url,boolean是否将参数转换为对象<br>
query:参数字符串<br>
URLSearchParams
new URLSearchParams(url.query)
将字符串转换为Map对象
global模块
URL类
必须是一个完整的url地址
URLSearchParams类
服务器上有100条数据,实现请求带有两个参数分别是page_num和page_size,然后根据这两个参数,得到分页数据<br>
querystring模块
处理post请求参数<br>
req.on("data")事件中拼接参数
req.on("end")事件表示参数传递完毕
示例
引入
const querystring = require('querystring');
parse()
将body参数字符串转换成对象<br>
练习<br>
写一个login请求,在浏览器中输入/login.html地址时响应登录页面<br>
在登录页面中有一个表单,账号和密码,表单post提交到/loginPost地址判断账号密码是否为admin和123,如果是则响应welcome页面<br>
浏览器地址组成
http协议
http
https
ip地址或域名
在网络寻找计算机的<br>
提供外部服务<br>
www.baidu.com
192.168.1.100<br>
局域网,只能在局域网中使用
公网IP,需要申请<br>
提供内部服务
localhost<br>
127.0.0.1
端口号<br>
在计算机上寻找程序的,并不是每个程序都要端口号,只当程序需要对外提供数据时,才需要
默认是80
一般使用1000或以上的,1000以下的由计算机内部使用<br>
url
资源项目
端口号后面的第一个/项目名,可以没有<br>
资源文件路径
端口号或项目后面的第一个/路径名,可以没有<br>
/一个表示一级目录<br>
/a/b/c
会影响相对路径,因为相对只处理最后一个
参数
?后面的<br>
资源文件锚点<br>
#后面
BOM<br>
location
保存浏览器地址的对象
http模块
req.url
HTTP协议
超文本传输协议(英文:HyperText Transfer Protocol,缩写:HTTP)
请求协议
request,get请求没有请求数据(请求体),因为数据直接显示在url上,post的请求数据保存在请求体中
响应协议
response
postman
测试后台接口工具<br>
get请求
https://postman-echo.com/get
post请求
https://postman-echo.com/post
post请求也支持url传参
nodemon使用
下载:npm install -g nodemon<br>
运行:nodemon XXX.js<br>
也可以使用npx nodemon XXX.js来使用<br>
模块化<br>
基本概念
什么是模块化?
util
分页工具类<br>
moment
mock
dao
数据库增删改查
model
数据模板
router
负责路由处理
开发模式<br>
MVC<br>
M:数据模型
model
dao
V:视图模型
html
C:控制层,即router
MVVM
M
V
VM
优点
复用性
可维护性
按需加载
依赖明确
干掉Script标签<br>
模块化规范
AMD
Asynchronous Module Definition:异步模块定义
由于不是JavaScript原生支持,使用AMD规范进行页面开发需要用到对应的库函数,<br>也就是大名鼎鼎RequireJS,实际上AMD 是 RequireJS 在推广过程中对模块定义的规范化的产出<br>
define(id?, dependencies?, factory);
CMD
Common Module Definition:通用模块定义
CMD规范是国内发展出来的,就像AMD有个requireJS,<br>CMD有个浏览器的实现SeaJS,SeaJS要解决的问题和requireJS一样,<br>只不过在模块定义方式和模块加载(可以说运行、解析)时机上有所不同。<br>
define(['./a', './b'], function(a, b) {});
CommonJS
只能在NodeJS中使用<br>
导出模块
module.exports<br>
挂载属性
module.exports.属性名 = 值
赋值新对象
module.exports = {}
推荐使用<br>
exports
挂载属性<br>
不能赋值新对象,因为 exports指向module.exports,<br>即 exports = module.exports。所以 exports = {} 就无法导出内容<br>
注意:exports和module.exports不会导致后面的代码不运行
导入模块
require
导入的模块必须有导出<br>
导入一个模块其中的代码都会执行一次,多次导入只会执行一次。<br>因为module对象中有一个属性名为loaded,默认值为false。当模块被导入一次后,<br>就变为true,那么再次导入时不会再执行模块中的代码了<br>
ES6
需要支持ES6语法或者通过babel转换
在NodeJS只能通过mjs后缀的文件演示
ES6 Module 会自动采用严格模式<br>
导出模块
export
命名导出
export 定义变量语句<br>
export 定义函数语句<br>
export {变量1, 变量2 [as 别名]}<br>
ES6的简写方式
完整的为{key: value, key: value}
export default<br>
导出一个对象,一个模块中只能出现一次<br>
export default {}或常量值或函数或class {}<br>
导入模块
import
import '模块路径'<br>
引入样式,比较常用<br>
import 自定义名称 from '模块路径'<br>
自定义名称支持解构的写法<br>
推荐
通过 as 可以给解构的变量起别名<br>
当有export导出的内容时,只能导入export的内容<br>
当只export default的内容,那么就可以获取export default中的内容<br>
import * as 自定义名称 from '模块路径'<br>
可以引入所有内容
使用
在HTML中使用(了解)
在浏览器的JS使用
浏览器必须支持ES6语法
通过babel转换为ES5代码<br>
在NodeJS中使用
后缀名必须是.mjs。而不是js
通过babel转换为ES5代码<br>
优势
CommonJS和ES6的模块化区别<br>
值复制和动态映射
循环依赖
NodeJS的中模块化
分类
内置模块:官方提供,例如fs、path、global、http、url、querystring等
require("模块名称")
自定义模块:用户创建的每个JS文件都是
require("./模块名称")
注意:必须./开头,可以不写js后缀,默认模块名称为index
引入模块之后,只能使用该模块中通过exports暴露的变量<br>
第三方模块:由第三方开发提供的非官方模块,使用时需要提前下载
引入<br>
require("模块名称")<br>
jquery
moment
mock
vue
react
vuex
axios
主要使用CommonJS模块化规范,也做了轻微的修改
模块的导入
require
模块作用域
防止全局变量污染的问题
保证变量只能在其模块内使用,效果相当于私有变量
模块的导出
module<br>
exports<br>
挂载属性
指向对象
exports
是module.exports的简写
默认与module.exports指向同一个对象<br>
如果exports和module.exports指向不同对象,以后者为主<br>
NPM:包管理器<br>
什么是包
包就是第三方模块
NPM
全称:Node Package Manager,是NodeJS的包管理器
官网<br>
https://www.npmjs.com/ 网站上搜索自己所需要的包
从 https://registry.npmjs.org/ 服务器上下载自己需要的包<br>
版本查看命令
npm -v<br>
初始化项目<br>
命令<br>
npm init -y<br>
在项目根目录下,输入命令。会创建package.json
npm 规定,在项目根目录中,必须提供一个叫做 package.json 的包管理配置文件。<br>用来记录与项目有关的一些配置信息<br>
注意,项目名称不能使用中文
作用<br>
保存项目的配置信息<br>
同一个项目只要得到源码和package.json。<br>就可以通过npm i下载所有依赖到node_modules<br>因为node_modules体积一般都比较大<br>
package.json简介
name
项目的名称
version
版本号
private
如果你在你的package.json中设置了“private”:true,<br>那么npm将拒绝发布它。 这是防止私人存储库意外发布的一种方法。<br>
description
项目的描述信息
scripts
脚本命令
dependencies
项目中都用到了哪些包
--save/-S/-s
devDependencies
哪些包只在开发期间会用到,通过命令npm i -D/--dev 模块名<br>
main
项目入口文件
package-lock.json
在第一次执行npm install XXX命令时创建<br>
锁定所有模块的版本号及其依赖关系<br>
示例:下载jquery
下载源设置
设置淘宝下载源<br>
npm config get registry
npm config set registry=https://registry.npm.taobao.org/
查看设置信息:npm config list<br>
快速的切换下载仓库<br>
nrm:npm registry manager是npm的镜像源管理工具
安装
npm i -g nrm<br>
-g:全局安装
npm root -g:查看全局下载的位置
全局安装配置
npm config set prefix “D:\nodejs\node_global” //设置全局包目录<br>npm config set cache “D:\nodejs\node_cache” //设置缓存目录
npm config list:去检查设置是否生效
配置环境变量<br>
全局安装的命令可以直接在命令行中运行<br>
npm i nrm<br>
非全局安装<br>
可以通过npx nrm运行<br>
两个错误<br>
nrm : 无法加载文件 C:\Program Files\nodejs\nrm.ps1,因为在此系统上禁止运行脚本
nrm 报[TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string
常用命令
nrm -V<br>
nrm ls:列出可用的源
nrm current:查看当前使用的源
nrm use 源名:使用指定的源
nrm add baidu http://www.baidu.com:添加源
nrm del baidu:删除源
nrm test npm
使用命令 nrm test npm 来测试目标源的响应时间。如果不添加源名,则是测试所有源。
下载与卸载包<br>
下载moment日期处理包
官网:http://momentjs.cn/
命令
npm install moment<br>
简写:npm i moment
初始下载影响
node_modules 文件夹
package.json配置文件
package-lock.json 配置文件
版本规则
查看版本号<br>
npm view moment version
查看moment的最新版本号
npm view moment versions
查看moment的所有版本号
npm list<br>
查看当前项目所有第三方包使用的版本号
npm list moment<br>
查看当前项目moment使用的版本号
npm install moment@major.minor.patch
不指定版本时,默认为最新版本<br>
支持命令行
@具体版本号
@~版本号
@x 标识符
@^版本号
@* 标识符
在package.json使用<br>
<=版本号
@>版本号
@>=版本号
version1 - version2
常用下载命令参数<br>
npm install moduleName<br>
安装模块到项目目录下,并在package.json文件的dependencies节点写入依赖。
npm install -g moduleName<br>
-g 的意思是将模块安装到全局,具体安装到磁盘哪个位置,要看 npm config prefix 的位置。
NPX<br>
解决某些需要单独运行的脚本,必须先全局下载,设置环境变量后才能使用的问题<br>
使用方式
npx 脚本<br>
例如:npx nodemon --help<br>
先查看该命令是否下载,不需要全局下载
如果已经下载,就在node_module中找到并使用
如果没有下载,会先临时下载,然后再运行<br>
npm install --save moduleName<br>npm insatll -S moduleName<br>npm insatll -s moduleName<br>npm install -d moduleName
--save 的意思是将模块安装到项目目录下,并在package.json文件的dependencies节点写入依赖。
npm install --save-dev moduleName<br>npm install -D moduleName<br>
--save-dev 的意思是将模块安装到项目目录下,并在package.json文件的devDependencies节点写入依赖。
npm install --no-save moduleName<br>
不会在package.json中保存该依赖<br>
npm install<br>
根据package.json下载所有依赖
--only=prod<br>
不会下载 devDependencies 中的依赖<br>
练习<br>
下载nodemon插件,并且启动http服务
卸载包<br>
npm uninstall 模块名
npm uninstall 模块名 --save
npm uninstall 模块名 --save-dev
npm uninstall 模块名 -g<br>
发布包(了解)
注册账号<br>
https://www.npmjs.com/
登录账号
npm login
发布包
进入到发布项目的根目录下<br>
npm publish
删除发布的包
npm unpublish 包名 --force
总结
nvm
nodejs的版本管理器
nrm
镜像源管理器
npx
运行工具命令,免除全局下载和配置环境变量的麻烦<br>
对部门的使用不是很好
npm
包管理器
下载、卸载<br>
全局下载
-g参数<br>
npm config prefix<br>
全局下载的命令保存目录<br>
npm config cache<br>
全局下载的缓存保存目录<br>
将prefix中的目录配置到环境变量中<br>
注意目录的权限
解决错误提示中有Permited或Permission等关键的问题<br>
模块的加载机制
优先从缓存中加载
模块在第一次加载后会被缓存。 这也意味着多次调用 require() 不会导致模块的代码被执行多次。<br>注意:不论是内置模块、用户自定义模块、还是第三方模块,它们都会优先从缓存中加载,从而提高模块的加载效率。<br>
内置模块的加载机制<br>
内置模块是由 Node.js 官方提供的模块,内置模块的加载优先级最高。<br>例如,require('fs') 始终返回内置的 fs 模块,即使在 node_modules 目录下有名字相同的包也叫做 fs。<br>
自定义模块的加载机制<br>
使用 require() 加载自定义模块时,必须指定以 ./ 或 ../ 开头的路径标识符。在加载自定义模块时,如果没有指定 ./ 或 ../ 这样的路径标识符,则 node 会把它当作内置模块或第三方模块进行加载。<br><br> 同时,在使用 require() 导入自定义模块时,如果省略了文件的扩展名,则 Node.js 会按顺序分别尝试加载以下的文件:<br> 1.按照确切的文件名进行加载<br> 2.补全 .js 扩展名进行加载<br> 3.补全 .json 扩展名进行加载<br> 4.补全 .node 扩展名进行加载<br> 5.加载失败,终端报错<br>
第三方模块的加载机制<br>
如果传递给 require() 的模块标识符不是一个内置模块,也没有以 ‘./’ 或 ‘../’ 开头,则 Node.js 会从当前模块的父目录开始,尝试从 /node_modules 文件夹中加载第三方模块。<br><br> 如果没有找到对应的第三方模块,则移动到再上一层父目录中,进行加载,直到文件系统的根目录。<br><br> 例如,假设在 'C:\Users\nodejs\project\foo.js' 文件里调用了 require('tools'),则 Node.js 会按以下顺序查找:<br> C:\Users\nodejs\project\node_modules\tools<br> C:\Users\nodejs\node_modules\tools<br> C:\Users\node_modules\tools<br> C:\node_modules\tools<br>
目录作为模块<br>
当把目录作为模块标识符,传递给require() 进行加载的时候,有三种加载方式:<br><br> 在被加载的目录下查找一个叫做 package.json 的文件,并寻找 main 属性,作为 require() 加载的入口<br><br> 如果目录里没有 package.json 文件,或者 main 入口不存在或无法解析,则 Node.js 将会试图加载目录下的 index.js 文件。<br><br> 如果以上两步都失败了,则 Node.js 会在终端打印错误消息,报告模块的缺失:Error: Cannot find module 'xxx'<br>
Express
概述<br>
Express 是基于 Node.js 平台,快速、开放、极简的 Web 开发框架。
官网<br>
http://www.expressjs.com.cn/
为什么要学习Express?<br>
http 内置模块用起来很复杂,开发效率低;
Express 是基于内置的 http 模块进一步封装出来的,能够极大的提高开发效率。
HTTP模块与Express关系
类似于浏览器中 Web API 和 jQuery 的关系。后者是基于前者进一步封装出来的。
安装
npm install express --save
项目创建
使用项目生成器<br>
npm install -g express-generator
express --no-view myapp
在app.js中添加app.listen(端口号);<br>
npm i下载所有依赖<br>
node app.js运行<br>
手动搭建
基本使用
启动服务,绑定端口号
处理请求
不同的请求路径做不同的处理
get请求
url地址传递参数<br>
url地址获取参数
post请求
url地址传递参数<br>
url地址获取参数
表单提交参数
json格式的参数
获取表单数据
中文乱码
get请求中的参数的中文
post表单提交中的参数的中文
响应的内容中的中文
res.writeHead(200,{'Content-Type':'text/html;charset=utf-8'});//设置response编码为utf-8
主要针对res.end()方法
数据库与程序之间中文编码问题
请求转发
express没有内部的api来实现
示意图<br>
请求响应<br>
响应类型<br>
文本
res.send("文本内容")
html文件
html文件是无法直接与后面进行数据对接,只能通过ajax
res.sendFile()
res.send()
res.send()或end(),需要使用fs模块来读取
json或xml数据
res.json(对象)<br>
多媒体文件
处理静态资源
模板引擎
pug
https://pugjs.org/language/attributes.html
注意:在pug中空格是比较重要且麻烦,要特别注意使用<br>
res.render('页面名称')
设置响应头
响应码
中文乱码
重定向<br>
res.redirect('/users');
示意图
常见错误
重复响应
示例代码<br>
错误信息
全局参数处理
res.locals
影响当次请求
与模板之间的传值
app.locals
影响所有用户<br>
实现网站的点击量<br>
中间件<br>
静态资源处理<br>
app.use(express.static(path.join(__dirname, 'public')))
统一参数处理
app.use((req, res, next) => {})
next():放行函数
统一错误处理
自定义中间,配合请求中的next函数
后台跨域处理
当不同的js中的ajax访问不同域的接口时就会出现跨域问题<br>
不同域名之间<br>
通过ajax去访问不属于自己这个域中的接口<br>
下载<br>
npm install cors<br>
使用
const cors = require('cors');
app.use(cors());
测试代码
index.html<br>
登录拦截
express-session
下载<br>
npm install express-session --save
引入
const session = require("express-session");
配置session中间件<br>
参数
<br>
操作session<br>
req.session
自定义中间件<br>
判断每个请求是否有登录标记
白名单:不需要判断是否登录的请求
token
下载<br>
npm install jsonwebtoken express-jwt
参数资料<br>
https://www.npmjs.com/package/express-jwt
初始配置<br>
配置中间件,实现token验证<br>
生成token
通过jwt.sign() 生成 JWT 字符串,三个参数分别为:用户信息对象,加密密钥,配置对象
默认token是保存在请求头中的Authorization属性中<br>
获取token中用户信息<br>
req.auth
router提取<br>
加密处理<br>
下载<br>
npm install bcryptjs
引入
const bcrypt = require('bcryptjs');
设置加密等级,如果不设置默认为10,最高为10
bcrypt.genSaltSync(10);
获取加密内容
const hash = bcrypt.hashSync(password, salt);
加密内容比较
bcrypt.compareSync(password, hash)
文件上传<br>
下载
npm install multer
引入<br>
const multer = require('multer')
创建保存目录
配置<br>
文件处理<br>
单文件<br>
多文件
restful api接口<br>
传统接口名称<br>
[get] /users/getAll # 查询用户信息列表<br>
[get] /users/getById?id=值 # 查询某个用户信息<br>
[get] /users/add #去到添加用户页面,前后不分离的项目才会有<br>
[post] /users/save #添加和编辑保存都一样<br>
[get] /users/deleteById?id=值 #根据id删除数据<br>
[get] /users/search?条件参数<br>
【GET】 /users # 查询用户信息列表<br><br>【GET】 /users/1001 # 查看某个用户信息<br><br>【POST】 /users # 新建用户信息<br><br>【PUT】 /users/1001 # 更新用户信息(全部字段)<br><br>【PATCH】 /users/1001 # 更新用户信息(部分字段)<br><br>【DELETE】 /users/1001 # 删除用户信息<br><br>【PATCH】一般不用,用【PUT】
/users/:id
匹配/users/1001中的参数<br>
req.params.id
restful api只是一个规范与技术没有关系<br>
表单验证<br>
自定义逻辑
自定义中间件<br>
express-validator
下载
npm install --save express-validator
官方文档<br>
https://express-validator.github.io/docs/index.html
引入
const {body, validationResult} = require('express-validator');
验证器对象
选择一个使用即可
body([fields, message])
默认错误信息<br>
Invalid value
cookie([fields, message])
header([fields, message])
param([fields, message])
query([fields, message])
check([field, message])
field:检测的属性名<br>
message:默认的对应的错误信息
检测范围<br>
req.body
req.cookies
req.headers
req.params
req.query
checkSchema(schema)
oneOf(validationChains[, message])
在validationChains中至少有一个通过,否则提示错误信息
buildCheckFunction(locations)
locations
必须是一个数组,只能是body, cookies, headers, params 或 query中的值一个或几个
检测locations中指定的区域中的属性
错误结果对象
validationResult
结果格式<br>
示例
返回验证的错误信息对象<br>
静态方法
.withDefaults(options)
定义结果格式
实例方法<br>
.isEmpty()
是否有报错信息
.formatWith(formatter)
自定义错误信息
.array([options])
以数组的形式,保存所有错误信息
options
onlyFirstError: false
是否只保存一个错误信息
.mapped()
以对象的形式,保存所有错误信息
.throw()
将错误以异常的方式抛出
参数处理方法
.trim()
.default(default_value)
如果属性的值是['', null, undefined, NaN]中的一个,则将default_value赋给属性
.replace(values_to_replace, new_value)
.escape()
转义处理<br>
toBoolean(strict?: boolean)
toFloat()
toInt(radix?: number)
toDate()
.toArray()
将属性值转换为数组
.toLowerCase()
.toUpperCase()
.normalizeEmail()
.run(req)
执行验证链,并返回Promise对象
.customSanitizer(sanitizer)
自定义处理方法
验证规则方法<br>
.exists()
.if(condition)
condition((value, {req, location, path})){}
isEmail(options?: Options.IsEmailOptions)
isEmpty(options?: Options.IsEmptyOptions)
ignore_whitespace: boolean;
isLength(options: Options.MinMaxOptions)
min
数组最小长度
max
数组最大长度
isNumeric(options?: Options.IsNumericOptions)
no_symbols: boolean;
默认为false<br>
locale?: AlphanumericLocale;
isDecimal(options?: Options.IsDecimalOptions)
isBoolean(options?: Options.IsBooleanOptions)
isUppercase(): Return;
isLowercase()
isURL(options?: Options.IsURLOptions)
isUUID(version?: Options.UUIDVersion)
.isJWT()
.isString()
.isArray(options)
options
min
数组最小长度
max
数组最大长度
.isObject(options)
options
strict
true
false
isDate(options?: Options.IsDateOptions)
format?: string;
delimiters?: string[];
strictMode?: boolean;
.isInt(options?: Options.IsIntOptions)
allow_leading_zeroes
是否允许以0开头
lt?: number
最小值<br>
gt?: number
最大值
.isJSON(options?: Options.IsJSONOptions)
allow_primitives?: boolean;
isAfter(date?: string)
isBefore(date?: string)
contains(elem: any, options?: Options.ContainsOptions)
.not()
notEmpty(options?: Options.IsEmptyOptions): Return;
.optional(options)
options
nullable:boolean
是否允许为null值
checkFalsy:boolean
是否处理假值,如"", 0, false, null
matches(pattern: RegExp | string, modifiers?: string)
equals(comparison: string)
.bail()
当有错误时,立即终止验证链
.withMessage(message)
自定义错误信息<br>
字符串<br>
对象
message
errorCode
函数
(value, { req, location, path }) => {}
custom(validator: CustomValidator)
自定义验证规则
validator(value, { req, location, path }){}
.run(req[, options])
matchedData(req[, options])
const {matchedData} = require('express-validator');
req
options
includeOptionals:boolean
默认为false,是否包含假值
onlyValidData:boolean
默认为true,是否只显示通过验证的数据
locations
日志打印<br>
log4j
数据库<br>
MongoDB
概述
什么是MongoDB
MongoDB 是一个基于分布式文件存储的数据库。<br>由 C++ 语言编写。旨在为 WEB 应用提供可扩展的高性能数据存储解决方案。<br>
MongoDB 是一个介于关系型数据库和非关系型数据库(NoSql)之间的产品,是非关系数据库当中功能最丰富,最像关系数据库的。
关系型数据库(RDBMS )
ACID原则
A (Atomicity) 原子性
C (Consistency) 一致性
I (Isolation) 独立性
D (Durability) 持久性
特点
高度组织化结构化数据<br>- 结构化查询语言(SQL) (SQL)<br>- 数据和关系都存储在单独的表中。<br>- 数据操纵语言,数据定义语言<br>- 严格的一致性<br>- 基础事务
非关系型数据库(NoSQL)
概念
NoSQL一词最早出现于1998年,是Carlo Strozzi开发的一个轻量、开源、不提供SQL功能的关系数据库。<br><br>2009年,Last.fm的Johan Oskarsson发起了一次关于分布式开源数据库的讨论[2],来自Rackspace的Eric Evans再次提出了NoSQL的概念,这时的NoSQL主要指非关系型、分布式、不提供ACID的数据库设计模式。
BASE原则
概念
BASE:Basically Available, Soft-state, Eventually Consistent。 由 Eric Brewer 定义。<br><br>CAP理论的核心是:一个分布式系统不可能同时很好的满足一致性,可用性和分区容错性这三个需求,最多只能同时较好的满足两个。<br><br>BASE是NoSQL数据库通常对可用性及一致性的弱要求原则:
Basically Available --基本可用
Soft-state --软状态/柔性事务。 "Soft state" 可以理解为"无连接"的, 而 "Hard state" 是"面向连接"的
Eventually Consistency -- 最终一致性, 也是 ACID 的最终目的。
特点
- 代表着不仅仅是SQL<br>- 没有声明性查询语言<br>- 没有预定义的模式<br>- 键 - 值对存储,列存储,文档存储,图形数据库<br>- 最终一致性,而非ACID属性<br>- 非结构化和不可预知的数据<br>- CAP定理<br>- 高性能,高可用性和可伸缩性
优点
- 高可扩展性<br> - 分布式计算<br> - 低成本<br> - 架构的灵活性,半结构化数据<br> - 没有复杂的关系
缺点
- 没有标准化<br> - 有限的查询功能(到目前为止)<br> - 最终一致是不直观的程序
数据库代表
ACID VS BASE
分布式系统
概念
分布式系统(distributed system)由多台计算机和通信的软件组件通过计算机网络连接(本地网络或广域网)组成。<br><br>分布式系统是建立在网络之上的软件系统。正是因为软件的特性,所以分布式系统具有高度的内聚性和透明性。<br><br>因此,网络和分布式系统之间的区别更多的在于高层软件(特别是操作系统),而不是硬件。<br><br>分布式系统可以应用在不同的平台上如:Pc、工作站、局域网和广域网上等。
优点
可靠性(容错) :<br><br>分布式计算系统中的一个重要的优点是可靠性。一台服务器的系统崩溃并不影响到其余的服务器。<br><br>可扩展性:<br><br>在分布式计算系统可以根据需要增加更多的机器。<br><br>资源共享:<br><br>共享数据是必不可少的应用,如银行,预订系统。<br><br>灵活性:<br><br>由于该系统是非常灵活的,它很容易安装,实施和调试新的服务。<br><br>更快的速度:<br><br>分布式计算系统可以有多台计算机的计算能力,使得它比其他系统有更快的处理速度。<br><br>开放系统:<br><br>由于它是开放的系统,本地或者远程都可以访问到该服务。<br><br>更高的性能:<br><br>相较于集中式计算机网络集群可以提供更高的性能(及更好的性价比)。
缺点
故障排除:<br><br>故障排除和诊断问题。<br><br>软件:<br><br>更少的软件支持是分布式计算系统的主要缺点。<br><br>网络:<br><br>网络基础设施的问题,包括:传输问题,高负载,信息丢失等。<br><br>安全性:<br><br>开放系统的特性让分布式计算系统存在着数据的安全性和共享的风险等问题。
CAP定理(CAP theorem)
概念
在计算机科学中, CAP定理(CAP theorem), 又被称作 布鲁尔定理(Brewer's theorem), <br>它指出对于一个分布式计算系统来说,不可能同时满足以下三点:<br>
CAP
一致性(Consistency) (所有节点在同一时间具有相同的数据)
可用性(Availability) (保证每个请求不管成功或者失败都有响应)
分隔容忍(Partition tolerance) (系统中任意信息的丢失或失败不会影响系统的继续运作)
三种组合方式
CA - 单点集群,满足一致性,可用性的系统,通常在可扩展性上不太强大。
CP - 满足一致性,分区容忍性的系统,通常性能不是特别高。
AP - 满足可用性,分区容忍性的系统,通常可能对一致性要求低一些。
官网
中文官网:https://www.mongodb.org.cn/
英文官网:https://www.mongodb.com/
下载与安装
下载数据库,先安装<br>https://www.mongodb.com/try/download/community<br>
下载compass GUI,后安装<br>https://www.mongodb.com/try/download/compass<br>
安装,基本都是下一步<br>https://docs.mongodb.com/manual/administration/install-community/<br>
环境变量配置
添加变量名MongoDB_HOME,值为安装路径
在path中添加%MongoDB_HOME%\bin
专业术语
数据库结构
服务与客户端
使用命令操作
https://www.mongodb.org.cn/tutorial/2.html
https://mongodb.net.cn/manual/mongo/
compass gui操作
NodeJS操作
插件:http://www.mongoosejs.net/
下载<br>
引入
连接数据库<br>
创建数据表
插入数据<br>
删除数据
修改数据
查询数据
Mysql
参考资料<br>
https://www.npmjs.com/package/mysql
下载
npm i mysql
引入
const mysql = require("mysql");
基本使用<br>
连接数据库
执行sql代码
增删改查都是同一个方法
关闭连接
连接池<br>
示例<br>
创建连接池<br>
执行SQL<br>
getConnection(callback(err, connection))
connection.query(sql, callback)
执行sql命令
connection.release()
释放连接
query(sql, callback)<br>
执行sql命令,自动释放连接
关闭连接池
end()<br>
谨慎使用<br>
增删改查<br>
sql拼接
直接拼接sql会有被注入攻击的风险
防止sql注入攻击<br>
mysql.escape(参数)
connection.escape(参数)
pool.escape(参数)
预编译sql
占位符<br>
?
方式一<br>
方式二<br>
方式三<br>
方式四
只适合在添加和修改命令中使用<br>
Express中使用Mysql
代码提取<br>
提取连接数据库js文件
改造数据库方法支持Promise<br>
封装数据库通过类BaseDao
练习<br>
让base_dao支持promise写法,然后在router中使用<br>
AJAX
概述
ajax:Asynchronous javascript and xml,异步JavaScript和Xml
作用
局部刷新页面
发起异步请求
同异步请求的区别
- 同步请求:当一个页面中的内容发生改变时,需要全部刷新。当一个请求发起时,其他的请求不能发起<br>- 异步请求,当一个页面中的内容发生改变时,可以局部刷新。当一个请求发起时,其他的请求也能发起<br>
JavaScript的AJAX<br>
XMLHttpRequest对象概述(了解)
常用属性
onreadstatechange
用于监听异步请求对象状态(readyState)改变
status
服务器响应状态码
readyState
异步请求对象的状态
- 0:异步请求对象还没有初始化完成<br>- 1:开始发起请求<br>- 2:发起请求完成<br>- 3:开始读取服务器的响应<br>- 4:读取服务器响应完成<br>
responseText
响应正文
常用方法
open
flag:为true就是异步请求;否则为同步请求
send
发送参数
setRequestHeader<br>
- 设置请求头
Ajax入门案例(get请求)
开发流程:<br><br>- 创建异步请求对象<br>- 监听异步请求对象状态改变<br> - 判断服务器响应状态码为200<br> - 判断异步请求对象状态为4<br>- 打开连接<br> - 设置请求方式<br> - 设置请求路径<br> - 设置异步请求<br>- 发送参数<br>
Ajax入门案例(post请求)
开发流程:<br><br>- 创建异步请求对象<br>- 监听异步请求对象状态改变<br> - 判断服务器响应状态码为200<br> - 判断异步请求对象状态为4<br>- 打开连接<br> - 设置请求方式<br> - 设置请求路径<br> - 设置异步请求<br>- 设置请求头Content-Type<br> - xhr.setRequestHeader("Content-Type","application/x-www-form-urlencoded");<br>- 发送参数<br>
fetch(url, options)
Fetch API是基于promise的设计,返回的是Promise对象,它是为了取代传统xhr的不合理的写法而生的。
注意:mock的ajax拦截,无法拦截到fetch请求<br>
参考资料<br>
https://developer.mozilla.org/zh-CN/docs/Web/API/Fetch_API/Using_Fetch
优点<br>
fetch()使用 Promise,不使用回调函数,因此大大简化了写法,写起来更简洁。<br>
fetch()采用模块化设计,API 分散在多个对象上(Response 对象、Request 对象、Headers 对象),更合理一些;相比之下,XMLHttpRequest 的 API 设计并不是很好,输入、输出、状态都在同一个接口管理,容易写出非常混乱的代码。<br>
fetch()通过数据流(Stream对象)处理数据,可以分块读取,有利于提高网站性能表现,减少内存占用,对于请求大文件或者网速慢的场景相当有用。XMLHTTPRequest对象不支持数据流,所有的数据必须放在缓存里,不支持分块读取,必须等待全部拿到后,再一次性吐出来。
参数说明<br>
url
请求地址
options
配置对象
method<br>
get
默认值
post
mode
cors
无法跨域
no-cors
处理跨域<br>
headers
请求头部信息<br>
使用Headers创建的对象
'Content-Type': 'application/json'
提交的数据是json数据
body: JSON.stringify(对象)<br>
'Content-Type': 'application/x-www-form-urlencoded'
普通表单提交<br>
body: "name=张三&age=20"<br>
body
post 请求体对象<br>
JQuery中的AJAX
引入jQuery
jQuery.get(url, [data], [callback], [type])
url:待载入页面的URL地址<br>
data:待发送 Key/value 参数
callback:载入成功时回调函数
type:返回内容格式,xml, html, script, json, text, _default
jQuery.getJSON(url, [data], [callback])
jQuery.post(url, [data], [callback], [type])
jQuery.ajax(url,[settings])
settings
url
type
get
post
data: {foo:["bar1", "bar2"]}
发送到服务器的数据
dataType
预期服务器返回的数据类型。
xml, html, script, json, jsonp, text<br>
timeout: 1000<br>
success: function(data, textStatus, jqXHR){}
statusCode: {404: function() {<br> alert('page not found');<br> }
contentType
headers:
设置header信息<br>
AXIOS中的AJAX<br>
官网地址<br>
http://www.axios-js.com/
下载
npm install axios
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
支持Promise语法
常用方法
axios.request(config)
axios.get(url[, config])
axios.get(url, params)
params是get请求的参数<br>
也可以写在url中
axios.post(url, data)
data是表单提交的参数
axios.post(url[, data[, config]])
axios.delete(url[, config])
axios.put(url[, data[, config]])
axios.options(url[, config])
axios.head(url[, config])
axios.patch(url[, data[, config]])
axios(config)
axios.create([config])
axios.defaults
axios默认对象
其属性中包含config中的内容<br>
config
url
method
get(默认)<br>
post
put
delete
data
post和put提交的参数
params
get参数提交
baseURL
请求前缀<br>
headers
头部配置对象
timeout
请求超时时间,单位毫秒
responseType
xml, html, script, json, jsonp, text<br>
responseEncoding: 'utf8', // default
拦截器
axios.interceptors.request.use
axios.interceptors.response.use
代码规范<br>
Prettier
格式化代码
官网<br>
https://www.prettier.cn/
下载
npm install --save-dev --save-exact prettier
npm install -g prettier
也可以全局下载使用
创建配置文件
.prettierrc.json
格式规则配置文件
.prettierignore
忽略配置文件
执行格式化<br>
npx prettier --write .
格式化所有文件
npx prettier --write 文件路径<br>
格式化指定文件
npx prettier --write 文件夹路径<br>
格式化指定文件夹下所有文件
检查是否格式化<br>
npx prettier --check .
检查所有文件是否被格式化<br>
其它两种方式与执行命令一样
其它命令参数
--no-config
不使用配置文件<br>
--ignore-path
指定忽略文件的位置,默认使用./.prettierignore
--find-config-path和--config
指定配置文件路径
完整配置文件
ESLint
官网<br>
https://eslint.bootcss.com/
完整的规则
https://eslint.bootcss.com/docs/rules/
下载
npm install eslint --save-dev
npm install eslint -g
创建配置文件<br>
eslint --init<br>
支持的格式<br>
.eslintrc.js
yaml
.eslintrc.yaml
.eslintrc.yml
json<br>
.eslintrc.json
已弃用
.eslintrc
package.json
写在eslintConfig属性中
如果同一个目录下有多个配置文件,ESLint 只会使用一个
执行验证命令<br>
验证命令
eslint .<br>
验证所有文件<br>
eslint 文件路径<br>
eslint 文件目录<br>
options<br>
--fix
修改错误
--ext
指定文件后缀
--no-eslintrc
不使用配置文件
-c, --config
指定配置文件
常用规则
注意,ESLint会与Prettier部分规则重复,保持一致即可
单元测试框架<br>
jest
官网
https://jestjs.io/zh-Hans/
下载<br>
npm install --save-dev jest
mocha
官网
https://mochajs.org/
修饰器<br>
修饰器只能用于类和类的方法,不能用于函数,因为存在函数提升
第三方模块
core-decorators.js
Webpack
官网地址
https://webpack.docschina.org/
https://webpack.js.org/
webpack是什么<br>
webpack是一个模块打包工具,可以把前端项目中的js、css、scss/less、图片等文件都打包在一起,<br>实现自动化构建,给前端开发人员带来了极大的便利。<br>
为什么学习
明确模块(文件)之间的依赖
解决作用域问题
解决代码拆分问题,封装重用
浏览器支持模块化
初始化项目
创建文件夹webpack_demo01<br>
执行npm init -y<br>
创建src目录作为源码目录<br>
示例
安装与使用
当前最新版本:v5.73.0
npm install --save-dev webpack webpack-cli<br>
使用4+版本<br>
npm install --save-dev webpack webpack-cli
通过npx使用webpack或者全局安装
查看webpack版本
npx webpack -v<br>
配置
命令行参数(了解)
--config 配置文件路径<br>
配置文件(重点)
配置文件名称:webpack.config.js<br>
参考资料
https://webpack.js.org/awesome-webpack/#loaders
基础部分<br>
入门使用
entry
入口文件的路径<br>
单文件
'文件路径'
多文件
['文件路径1', '文件路径2', ...]
注意:后期再说明<br>
output
filename
输出的文件路径
可以指定保存的目录<br>
'固定名称'<br>
[name]:entry中key的名称,没有key则为main
[chunkhash]:基于每个 chunk 内容的 hash
[id]:使用内部 chunk id
[hash]:使用每次构建过程中,唯一的 hash 生成,源码不变hash不变
缓存处理:当服务更新时,如果文件名称一样,浏览器继续使用之前缓存的文件。<br>所以在正式服务器上可以通过除name之外的做为名称,可以解决缓存问题<br>
path<br>
输出的文件路径,只支持绝对路径<br>
path.resolve(__dirname, 'dist')
clean: true
每次编译后都会清空之前的内容<br>
publicPath: 'http://localhost:8080/'<br>
指定资源的绝对路径
常见错误
属性名写错
属性值写错
mode<br>
'none'
'development'
开发模式,代码不会压缩处理
'production'
生产模式,js代码会被压缩处理
了解一下,不同值打包的代码文件<br>
编译打包
全局安装
webpack
非全局安装<br>
npx webpack<br>
package.json配置执行脚本<br>
常用参数<br>
--watch:实时编译,但配置文件修改还是要重启
--config 配置文件名:指定配置文件<br>
编译成功后可以在dist目录下找到对应的内容
创建app.html
<script src="./dist/bundle.js" defer></script>
defer:等待页面加载完毕再加载脚本
在package.json中的scripts创建使用命令<br>
build
webpack
体验插件
自动创建html页面<br>
下载插件
npm install --save-dev html-webpack-plugin
参考资料<br>
https://www.npmjs.com/package/html-webpack-plugin
引入
const HtmlWebpackPlugin = require('html-webpack-plugin');
基本使用<br>
示例<br>
多页面配置
注意:一个htmlWebpackPlugin实例对应一个html页面<br>
常用配置<br>
title
生成的html文档标题,不能与template一起使用
filename
指定生成的html文档名称,默认为index.html
template<br>
指定html模板
inject
指定script插入的位置
body
head<br>
默认值
chunks
指定html引入的模块,模块名称就是entry中的key
excludeChunks
指定html不引入的模块
base
在html中添加一个base标签<br>
base标签会影响a、img、url等路径<br>
minify
压缩配置,需要指定mode为prodution<br>
参考资料<br>
https://www.npmjs.com/package/html-minifier-terser
true
配置对象
removeComments: true
移除注释<br>
collapseWhitespace: true
打包后移除html文件中的空白符
minifyCSS: true<br>
压缩内联css
minifyJS:true
压缩内联js
keepClosingSlash
在单元素上保留末尾的斜杠
完整示例
配置服务器
下载
npm install --save-dev webpack-dev-server
配置
devServer
static
指定资源目录,一般是dist的目录的路径<br>
字符串
对象
port
端口号
host
访问地址配置
'local-ip' | 'local-ipv4' | 'local-ipv6'
只支持局域网ip地址访问
localhost, 127.0.0.1
只能通过localhost或127.0.0.1访问<br>
0.0.0.0
支持任何地址访问
默认值
open
服务器开启时,打开指定的访问页面或地址<br>
数组
['app.html', 'http://www.baidu.com']
对象
target
['app.html', 'http://www.baidu.com']
app
name
指定打开的浏览器<br>
arguments
浏览器参数
compress:true
是否启动gzip压缩
client
overlay:true
在浏览器显示一个提示错误和警告的元素层
有bug,暂时无法使用<br>
liveReload: true<br>
热加载,只要代码发生变动,会使浏览器自动刷新
默认开启的<br>
hot: true<br>
热替换(Hot Module Replacement,HMR):可以让代码在页面不刷新的前提下得到最新的改动,<br>甚至不需要重新发起请求就能看到更新后的效果<br>
默认是开启的,建议关闭liveReload
原理图
配置<br>
devServer<br>
hot:true
注意,5.74.0版本配置有变化<br>
文件类型<br>
CSS,不需要额外配置
JS
module.hot.accept()
元素重复问题,暂时无法解决<br>
headers
头部对象<br>
Content-Type
Authorization
proxy: {}<br>
代理,可以解决跨域问题
"/api": 'http://localhost:8080'
当请求路径以/api开头时,将转发到指定的地址上
historyApiFallback: true, // 解决vue-router刷新404问题。后面才详细介绍
启动服务器
配置命令
通过npm run serve启动服务器<br>
资源管理
css样式处理
loader的作用<br>
webpack默认只处理js和json,如果需要处理其它文件需要对应的loader
没有对应的loader就会报错<br>
示例
在src下创建style.css<br>
在js中通过import引入样式<br>
创建div元素,然后使用style.css中的样式<br>
尝试编译,会报错<br>
下载<br>
npm install --save-dev style-loader css-loader
配置
style-loader必须在css-loader的前面
其它loader
less-loader
sass-loader<br>
stylus-loader
postcss-loader
分离CSS<br>
将css代码保存到独立的css文件中<br>
参考文档
https://github.com/webpack-contrib/mini-css-extract-plugin
下载
npm install --save-dev mini-css-extract-plugin
配置
步骤如上
压缩CSS
压缩CSS文件<br>
参考文档
https://www.npmjs.com/package/css-minimizer-webpack-plugin
下载
npm install css-minimizer-webpack-plugin --save-dev
配置
以上代码需要配合mode='production'才有效。<br>但也可以通过添加minimize: true,在optimization中也可以解决
配置选项
test
指定匹配的文件格式
Type: String|RegExp|Array<String|RegExp> - default: /\.css(\?.*)?$/i
include
子主题
Type: String|RegExp|Array<String|RegExp> Default: undefined
exclude
指定不需要处理的文件夹
Type: String|RegExp|Array<String|RegExp> Default: undefined
压缩JS文件
因为上面配置了CSS压缩,会导致JS压缩无法进行,所以需要单独的配置
下载
npm install terser-webpack-plugin --save-dev
参考资料
https://webpack.docschina.org/plugins/terser-webpack-plugin/
配置
<br>
webpack4
图片处理
使用方式<br>
img标签
引入图片<br>
创建img元素
将图片对象指定到img中的src属性
css背景图片
背景图片中的url<br>
file-loader
下载<br>
npm install --save-dev file-loader
配置<br>
<br>
url-loader
url-loader内部使用了file-loader,但是遇到小于10000,即8kb的png、jpg、jpeg、gif文件会转换成base64格式的字符串,并打包到css和js里
下载
npm install url-loader --save-dev
配置
<br>
注意:不能与file-loader一起使用<br>
txt文件处理
raw-loader
处理txt文件
否报错
安装
npm install raw-loader --save-dev
配置
<br>
asset资源处理
webpack5提供
参考资料
https://webpack.js.org/guides/asset-modules/
其它配置<br>
如果需要生成文件就可以配置该项进行路径和文件名称的配置
asset/resource
发送一个单独的文件,并导出URL(之前通过file-loader实现)
配置
<br>
asset/inline
导出一个资源的data URI (之前通过url-loader实现),不会生成文件
配置
<br>
asset
在导出一个data URI和一个单独的文件自由选择 (之前通过url-loader,并且配置资源体积实现)
配置
<br>
asset/source
导出资源的源代码 (之前通过raw-loader实现)
配置
<br>
加载字体
选择图标样式下载
https://www.iconfont.cn/collections/index?spm=a313x.7781069.1998910419.5&type=1
复制字体文件及样式文件到项目
配置
最新版本也可以不写这个配置,如果需要指定字体文件的保存目录,就需要写上generator
在页面元素上使用样式
数据文件处理
json文件
默认会处理
csv文件
下载
npm install --save-dev csv-loader<br>
配置
<br>
xml文件
下载
npm install --save-dev xml-loader
配置
<br>
toml文件
下载
npm install toml --save-dev
yaml文件
下载
npm install yamljs --save-dev
json5文件
下载
npm install json5 --save-dev
配置
<br>
<br>
源码映射<br>
源码映射,开发阶段需要设置,方便排错。否则报错的代码行号与源码行号对应不上
参考资料<br>
https://webpack.docschina.org/configuration/devtool/#development
配置<br>
开发时使用<br>
devtool
false
关闭sourcemap<br>
eval
默认值,每个module会封装到eval里包裹起来执行,并且会在末尾追加注释<br>
报错行号与源码无法对应<br>
eval-source-map
每个module会通过eval()来执行,并且生成一个DataUrl形式的SourceMap
报错行号与源码一一对应
source-map
生成一个SourceMap文件
构建速度慢<br>
重构速度慢
包含行/列映射
适用于生产环境
报错行号与源码一一对应
hidden-source-map
和source-map一样,但不会在bundle末尾追加注释
报错行号与源码无法对应<br>
inline-source-map
生成一个DataUrl形式的SourceMap文件
构建速度慢<br>
重构速度慢
适用于单页面项目
报错行号与源码一一对应
cheap-source-map
生成一个没有列信息的SourceMap文件,不包含loader的SourceMap
报错行号与源码一一对应
cheap-module-source-map
生成一个没有列信息的SourceMap文件,同时loader的SourceMap也被简化为只包含对应行的<br>
构建速度快<br>
重构速度快
包含行映射
适用于开发环境
报错行号与源码一一对应
转换ES6代码
ES6代码只有兼容的浏览器可以运行,如果遇到不兼容的浏览器时,<br>就需要使用babel来转换ES6代码为ES5代码<br>
安装
npm install -D babel-loader @babel/core @babel/preset-env
配置文件
.babelrc
js语法
babel.config.json
基础配置
无法处理一些新增的api,比如Promise、Object.assign等方法
高级配置<br>
下载
npm install --save-dev @babel/plugin-transform-runtime
配置
注意:上面corejs设置项,不同的值需要不同的依赖包<br>corejs的值 需要安装的依赖包
false npm install --save @babel/runtim<br>
2 npm install --save @babel/runtime-corejs2
3 npm install --save @babel/runtime-corejs3
代码分离<br>
方式一
index.js
another.js
配置<br>
编译
方式二
基于SplitChunksPlugin插件
splitChunks
chunks
all
async
initial
minSize
设置能够打包的最小体积,默认是20000byte<br>
minChunks
模块的最小引用次数,默认是1<br>
name
name指定是的output中的[name]值
如果指定了name,就只会打成一个文件
cacheGroups
splitChunks默认有两个缓存组:vender和default
{cacheGroup}<br>
test
filename
priority
enforce
name
reuseExistingChunk
参考资料<br>
https://webpack.docschina.org/guides/code-splitting/#splitchunksplugin
https://webpack.docschina.org/plugins/split-chunks-plugin
配置<br>
方法三<br>
外部化处理,即通过CDN方式引入第三方模块
方式四
动态加载
也称为懒加载,只需要代码执行之后才会加载
参考资料
https://webpack.docschina.org/guides/code-splitting/#prefetchingpreloading-modules
代码,不需要额外配置<br>
懒加载
演示代码<br>
预加载
当前导航下可能需要资源,官网说明无法演示。目前效果无懒加载一样
演示代码
预获取
将来某些导航下可能需要的资源。预获取是等网络空闲时提前下载js文件,比懒加载更好
演示代码<br>
效果查看
缓存处理
参考资料
https://webpack.docschina.org/guides/caching/
经常修改的文件要去除缓存
output
contenthash
没有修改过的文件要使用缓存<br>
splitChunks
不同环境切换<br>
命令行参数指定
参考资料
https://webpack.docschina.org/guides/environment-variables/
npx webpack --env production<br>
配置<br>
拆分配置文件
参考资料
https://webpack.docschina.org/guides/production/
创建config目录,保存所有配置文件
开发环境
webpack.config.dev.js
生产环境<br>
webpack.config.prod.js
使用命令指定配置文件<br>
npx webpack --config 配置文件名称<br>
npx webpack -c 配置文件名称<br>
配置npm命令
dev
webpack --config 路径/webpack.config.dev.js
prod
webpack --config 路径/webpack.config.prod.js
提取公共配置文件<br>
解决两个配置中的重复代码<br>
名称
webpack.config.common.js
合并配置文件<br>
下载
npm install webpack-merge -d<br>
参考资料<br>
https://www.npmjs.com/package/webpack-merge
webpack.config.js
代码优化<br>
参考资料
https://webpack.docschina.org/guides/tree-shaking/
tree-shaking
写在webpack配置文件中
development
去掉没有引入的代码(dead-code)<br>
optimization
usedExports:true
production
将自定义模块的函数直接运行,并得到结果<br>
sideEffects
写在package.json
boolean
true
所有文件都认为有副作用<br>
false
数组
认为有副作用的文件列表<br>
高级部分
模块解析<br>
参考资料<br>
https://webpack.docschina.org/configuration/resolve/
resolve
alias
"@": path.resolve(__dirname, "./src"),
vscode配置@路径识别
下载插件
path intellisense
进入设置
extensions
指定模块导入的路径解析顺序<br>
默认是js, json等<br>
enforceExtension
强制要求不使用扩展名才能引入<br>
true,不能加后缀名
false,加不加都可以
modules
指定node_modules的路径数组,按顺序解析
modules: [path.resolve(__dirname, 'node_modules'), 'node_modules'],
mainFiles
导入模块时,只写了目录,没有写具体文件时,通过mainFiles来自动导入指定的文件<br>
示例
Shimming<br>
参考资料
https://webpack.docschina.org/guides/shimming/
预置全局变量
细粒度
比较设置js中的this指向
下载
npm install imports-loader --save-dev
配置
<br>
子主题
下载
npm install exports-loader --save-dev
将js文件中没有被export或exports的变量,也可以通过require或import引入来使用
ESLint
Githooks-Husky
0 条评论
下一页