更新文章

1. 终于踩完一个坑了
This commit is contained in:
DefectingCat
2021-05-13 14:34:50 +08:00
parent 8c712b007e
commit 1b15bd7f5b
22 changed files with 8881 additions and 22513 deletions

4
.gitignore vendored
View File

@ -4,4 +4,6 @@ db.json
*.log
node_modules/
public/
.deploy*/
.deploy*/
package-lock.json
yarn.lock

22232
package-lock.json generated

File diff suppressed because it is too large Load Diff

View File

@ -18,7 +18,7 @@
},
"dependencies": {
"babel": "^6.23.0",
"commitizen": "^4.2.3",
"commitizen": "^4.2.4",
"conventional-changelog-cli": "^2.1.1",
"gulp": "^4.0.2",
"gulp-clean-css": "^4.3.0",
@ -38,13 +38,13 @@
"hexo-renderer-ejs": "^1.0.0",
"hexo-renderer-marked": "^4.0.0",
"hexo-renderer-stylus": "^2.0.1",
"hexo-server": "^2.0.0",
"hexo-theme-fluid": "^1.8.9",
"npm-check-updates": "^11.4.1",
"hexo-theme-fluid": "^1.8.10",
"nunjucks": "^3.2.3"
},
"devDependencies": {
"@babel/core": "^7.13.15",
"@babel/preset-env": "^7.13.15"
"@babel/core": "^7.14.2",
"@babel/preset-env": "^7.14.2",
"npm-check-updates": "^11.5.11",
"hexo-server": "^2.0.0"
}
}

View File

@ -0,0 +1,22 @@
在权威指南以及高级程序设计都出了新版之后,在其中遇到的一些新的 ECMAScript 的新特性也该记录下来了。
## 函数
### 条件式调用
在 ES2020 中,可以使用`?.()`来条件式的调用一个函数。这和对象的条件式访问类似在正常情况下如果直接访问一个不存在nulll 或 undefined的表达式会抛出 TypeError。而使用条件式调用在这种情况下则整个表达式的值为 undefined不会抛出异常。
```js
const test = (num, fn) => {
fn?.(num);
};
```
当然他们也有一些些小小的区别:
```js
test.fn(); // 常规属性访问,常规调用
test?.fn(); // 条件式属性访问,常规调用
test.fn?.(); // 常规属性访问,条件式调用
```

File diff suppressed because it is too large Load Diff

View File

@ -1,78 +0,0 @@
传统对象的键key只能是字符串
Map 的键key可以是任何类型的不像对象一样只能是字符串。
```js
let map = new Map([
[1, 'test'],
['1', 'str']
])
```
`map[key]`不是使用 Map 的正确方式,虽然`map[key]`也有效,例如我们可以设置`map[key] = 2`,这样会将 Map 视为 JavaScript 的 plain object因此它暗含了所有相应的限制没有对象键等。所以我们应该使用 Map 方法:`set``get`等。
`map.set`方法每次都会返回 Map 本身,所以可以使用“链式”调用:
```js
let map = new Map();
map.set(obj, 'this is a object')
.set('test', 12312313123)
.set('obj', obj)
```
## Map 迭代
Map 有三种迭代方法
* `map.keys()` —— 遍历并返回所有的键returns an iterable for keys
* `map.values()` —— 遍历并返回所有的值returns an iterable for values
* `map.entries()` —— 遍历并返回所有的实体returns an iterable for entries`[key, value]``for..of`在默认情况下使用的就是这个。
这三个方法都是能够将 Map 键值迭代出来,同时它们自身也是可迭代的:
```js
for (let i of map.entries()) {
console.log(i);
}
```
> 迭代的顺序与插入值的顺序相同。与普通的 Object 不同Map 保留了此顺序。
### 从对象创建 Map
对象方法`Object.entries()`的返回格式正好与创建 Map 构造函数相同,因此可以使用该方法使用对象创建 Map。
```js
let obj = {
name: 'xfy',
age: 18
}
console.log(Object.entries(obj));
let map = new Map(Object.entries(obj));
console.log(map.get('age'));
```
### 从 Map 创建对象
`Object.fromEntries()`方法的作用是相反的,它可以从 Map 迭代返回的键值对中创建对象。并且具有各种类型的键会被转换为字符串。
```js
let test = 'xfy';
let map = new Map([
[1, 3],
[test, 4]
])
let obj = Object.fromEntries(map.entries());
console.log(obj);
```
Set
Set 是一个特殊的类型集合 —— “值的集合”(没有键),它的每一个值只能出现一次。
### Set 迭代

View File

@ -0,0 +1,486 @@
## 数据结构
数据库
集合
文档
## 插入数据
集合为自动创建
选中数据库,如果不存在则自动创建:
```bash
use test
# 'switched to db test'
```
如果不添加数据则数据库不显示
```bash
show dbs
admin 41 kB
config 61.4 kB
local 41 kB
```
集合不需要手动进行创建,直接插入数据会自动创建集合
```bash
db.names.insertOne({name:'xfy'})
{ acknowledged: true,
insertedId: ObjectId("60371efde948e229844958fb") }
```
## 数据重复时
当数据重复时mongodb使用`_id`来区分数据。如果没有手动插入`_id`,则会自动生成一个 id。也可以手动插入。二者不相同。
id 不可修改。
![image-20210413233218343](images/MongoDB%E9%9B%B6%E7%A2%8E%E7%AC%94%E8%AE%B0/image-20210413233218343.png)
## 关系型数据库
### ACID 设计模式
A**A**tomicity原子性。事务里所做的操作要么全部做完要么都不做。
C**C**onsistency一致性。数据库要一直处于一致的状态事务的运行不会改变数据库原本的一致性约束。
I**I**solation独立性。并发的事务之间不会互相影响。
D**D**urability持久性。事务一旦提交后所作的修改将会永久的保存在数据库上。
事物:一次性执行多条 SQL 语句的操作。
这四个特性是关系型数据库要同时满足的。
## 非关系型数据库
### CAP 定理
在[理论计算机科学](https://zh.wikipedia.org/wiki/理論計算機科學)中,**CAP定理**CAP theorem又被称作**布鲁尔定理**Brewer's theorem它指出对于一个[分布式计算系统](https://zh.wikipedia.org/wiki/分布式计算)来说,不可能同时满足以下三点:
- 一致性(**C**onsistency (等同于所有节点访问同一份最新的数据副本)
- [可用性](https://zh.wikipedia.org/wiki/可用性)**A**vailability每次请求都能获取到非错的响应——但是不保证获取的数据为最新数据
- [分区容错性](https://zh.wikipedia.org/w/index.php?title=网络分区&action=edit&redlink=1)**P**artition tolerance以实际效果而言分区相当于对通信的时限要求。系统如果不能在时限内达成数据一致性就意味着发生了分区的情况必须就当前操作在C和A之间做出选择。
![1_Br1FrvKnK3hU6Xl_LbDkwg](images/MongoDB%E9%9B%B6%E7%A2%8E%E7%AC%94%E8%AE%B0/1_Br1FrvKnK3hU6Xl_LbDkwg.png)
### NoSQL 技术优势
根据 CAP 的核心定义,可以将 CAP 分成三个部分CA、CP、AP。
NoSQL 很好的融合了 CA、CP、AP 定理:
* CA单点集群满足一致性可用性的系统通常在可扩展性上不够强大。
* CP满足一致性分区容错性的系统通常在性能上不是特别高。
* AP满足可用性分区容错性的选题通常可能对一致性要求低一些。
### 优点与缺点
* 优点:
* 高可扩展性*
* 分布式计算
* 低成本
* 架构的灵活性,半结构化数据
* 没有复杂的关系
* 缺点:
* 没有标准化
* 有限的查询功能(目前)
## MongoDB
### 基本概念
文档是一组键值对key-valueBSON
需要注意:
* 文档中的键值对是有序的;
* 文档中的值可以是多种类型;
* MongoDB 区分类型和大小写;
* 同一个文档中不能有重复的键;
* 文档中的键是字符串。
> 键值对需要注意的部分和 JavaScript 的对象很类似。
集合MongoDB 集合组,类似于 RDBMS关系数据库管理系统Relational Database Management System中的表格。
集合命名需要注意:
* 集合名不能是空字符串;
* 集合名不能含有`\0`字符串(空字符串),这个字符表示集合名的结尾;
* 集合名不能以`system.`开头,这是为系统保留的前缀;
* 用户创建的集合名不能含有保留字符。
### 术语
| SQL术语/概念 | MongoDB术语/概念 | 解释/说明 |
| :----------- | :--------------- | :---------------------------------- |
| database | database | 数据库 |
| table | collection | 数据库表/集合 |
| row | document | 数据记录行/文档 |
| column | field | 数据字段/域 |
| index | index | 索引 |
| table joins | | 表连接,MongoDB不支持 |
| primary key | primary key | 主键,MongoDB自动将_id字段设置为主键 |
### 系统保留数据库
1. admin“root” 数据库
2. local这个数据永远不会被复制可以用来存储限于本地单台服务器的任意集合。
3. config当 mongdo 用于分片时config 数据库在内部使用,用于保存分片的相关的信息。
### 创建集合
使用`createCollection()`方法来创建集合。
```js
db.createCollection(name, options);
```
options 参数:
| 字段 | 类型 | 描述 |
| :---------- | :--- | :----------------------------------------------------------- |
| capped | 布尔 | (可选)如果为 true则创建固定集合。固定集合是指有着固定大小的集合当达到最大值时它会自动覆盖最早的文档。 **当该值为 true 时,必须指定 size 参数。** |
| autoIndexId | 布尔 | 3.2 之后不再支持该参数。(可选)如为 true自动在 _id 字段创建索引。默认为 false。 |
| size | 数值 | (可选)为固定集合指定一个最大值,即字节数。 **如果 capped 为 true也需要指定该字段。** |
| max | 数值 | (可选)指定固定集合中包含文档的最大数量。 |
### 集合其他操作
查看当前库中的所有集合
```js
show collections
```
删除集合
```js
db.games.drop()
```
### 数据类型
MongoDB支持以下数据类型:
- **String字符串**: mongodb中的字符串是UTF-8有效的。
- **Integer整数**: 存储数值。整数可以是32位或64位具体取决于您的服务器。
- **Boolean布尔**: 存储布尔(true/false)值。
- **Double双精度**: 存储浮点值。
- **Min/ Max keys最小/最大键)**: 将值与最低和最高BSON元素进行比较。
- **Arrays数组**: 将数组或列表或多个值存储到一个键中。
- **Timestamp时间戳**: 存储时间戳。
- **Object对象**: 嵌入式文档。
- **Null (空值)**: 存储Null值。
- **Symbol符号**: 与字符串相同,用于具有特定符号类型的语言。
- **Date日期**: 以UNIX时间格式存储当前日期或时间。
- **Object ID对象ID** : 存储文档ID。
- **Binary data二进制数据**: 存储二进制数据。
- **Code代码**: 将JavaScript代码存储到文档中。
- **Regular expression正则表达式**: 存储正则表达式
### 更新数据
语法:
```js
db.collection.update(
<query>,
<update>,
{
upsert: <boolean>,
multi: <boolean>,
writeConcern: <document>,
collation: <document>,
arrayFilters: [ <filterdocument1>, ... ],
hint: <document|string> // Available starting in MongoDB 4.2
}
)
```
`updateMany`就相当于`update`使用了`multi: true`这个可选属性
```js
use test
db.user.find();
db.user.insertMany(
[
{name: 'xfy',age:18,sex:'man'},
{name: 'xfy1',age:12,sex:'man'},
{name: 'xfy2',age:16,sex:'man'},
{name: 'xfy3',age:19,sex:'man'},
{name: 'xfy4',age:28,sex:'man'},
]
)
db.user.updateOne(
{age: 18},
{$set:{name:'dfy'}}
)
db.user.findOne({name:'dfy'})
db.user.updateMany(
{sex:'man'},
{$set:{sex:'woman'}}
)
```
#### 多个条件
`update`时,如果有多个条件,则默认是需要所有条件都满足。类似于 sql 中的 `and`连接。
```js
db.user.updateOne(
{name:'xfy',age:18},
{$set:{name:'dfy'}}
)
```
如果需要满足其中一个条件,需要使用`$or`操作符
```js
db.user.updateOne(
{$or:[name:'xfy',age:18]},
{$set:{name:'dfy'}}
)
```
### 删除文档
删除使用`remove()`方法。接受一个参数`justOne`,为`true`时,只删除一个文档。否则删除匹配到的所有文档。默认为`false`
```js
db.collection.remove(
<query>,
<justOne>
)
```
还有其他选项
```js
db.collection.remove(
<query>,
{
justOne: <boolean>,
writeConcern: <document>,
collation: <document>
}
)
```
删除集合中的所有数据
```js
db.collectionName.remove({})
```
### 查询文档
查询集合中的文档使用`find()`方法。
```js
db.collection.find()
```
在没有添加查询条件的情况下,`find()`方法默认会返回所有的数据。但返回的数据是未格式化的。使用`pretty()`以格式化显示。
```js
db.collection.find().pretty()
```
`findOne()`默认就只返回一条数据(查询到的第一条),并且就是格式化显示的,所以不能使用`pretty()`方法。
```js
db.user.findOne().pretty()
// TypeError: (intermediate value).pretty is not a function
```
#### 条件查询
多个条件同时满足的查询。和更新数据类似,传入多个条件时,默认为同时都需要满足。
```js
db.user.find({name:'xfy',age:18})
```
同理,满足单个条件时,使用`$or`操作符
```js
db.user.find({$or:[{name:'xfy'},{age:18}]})
```
### 条件操作符
条件操作符用于比较两个表达式,并从 mongodb 集合中获取数据。
| $ | Symbol | Words |
| :----- | :----- | :----------------------- |
| `$gt` | > | greater than |
| `$lt` | < | less than |
| `$gte` | ≥ | greater than or equal to |
| `$lte` | ≤ | less than or equal to |
| `$ne` | != | not equal |
```js
db.user.find()
db.user.updateMany({name:'dfy',age:18}, {$set:{name:'xfy'}})
db.user.find({$or:[{name:'xfy'},{age:18}]})
db.user.find(
{age:{$lt:18}}
)
db.user.find(
{age:{$gte:12,$lte:18}}
)
db.user.find(
{$or:[{
age:{$lt: 12}
},
{
age:{$gt: 18}
}
]}
)
db.user.find(
{age:{$gt: 20},$or:[{name:'xfy4'}]}
)
```
### 按类型查询
`$type`:用来根据类型来匹配对应的结果。
`limit()`方法:用来指定读取集合中数据的记录数量。
```js
db.user.find({age:18}).limit(2)
```
`skip()`方法:用来跳过指定数量的记录。默认为 0
### 排序查询
`sort()`方法可以通过参数指定排序的字段。使用参数`1`升序排列,使用`-1`降序排列。
```js
db.user.find({age:{$type: 'number'}}).sort({age: -1})
```
### 聚合操作
管道
- `$project`:修改输入文档的结构。可以用来重命名、增加或删除域,也可以用于创建计算结果以及嵌套文档。
- `$match`:用于过滤数据,只输出符合条件的文档。$match使用MongoDB的标准查询操作。
- `$limit`用来限制MongoDB聚合管道返回的文档数。
- `$skip`:在聚合管道中跳过指定数量的文档,并返回余下的文档。
- `$unwind`:将文档中的某一个数组类型字段拆分成多条,每条包含数组中的一个值。
- `$group`:将集合中的文档分组,可用于统计结果。
- `$sort`:将输入文档排序后输出。
- `$geoNear`:输出接近某一地理位置的有序文档。
表达式
| 表达式 | 描述 | 实例 |
| :-------- | :--------------------------------------------- | :----------------------------------------------------------- |
| $sum | 计算总和。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$sum : "$likes"}}}]) |
| $avg | 计算平均值 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$avg : "$likes"}}}]) |
| $min | 获取集合中所有文档对应值得最小值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$min : "$likes"}}}]) |
| $max | 获取集合中所有文档对应值得最大值。 | db.mycol.aggregate([{$group : {_id : "$by_user", num_tutorial : {$max : "$likes"}}}]) |
| $push | 在结果文档中插入值到一个数组中。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$push: "$url"}}}]) |
| $addToSet | 在结果文档中插入值到一个数组中,但不创建副本。 | db.mycol.aggregate([{$group : {_id : "$by_user", url : {$addToSet : "$url"}}}]) |
| $first | 根据资源文档的排序获取第一个文档数据。 | db.mycol.aggregate([{$group : {_id : "$by_user", first_url : {$first : "$url"}}}]) |
| $last | 根据资源文档的排序获取最后一个文档数据 | db.mycol.aggregate([{$group : {_id : "$by_user", last_url : {$last : "$url"}}}]) |
```js
db.sc.aggregate([
{
管道:{聚合操作表达式}
}
])
```
例:以`sex`属性为分组,求和`grade`属性:
`_id`用来指定分组的字段
```js
db.sc.aggregate([
{
$group:{_id:'$sex', sumgrade:{$sum:'$grade'}}
}
])
```
`$sum:1`用于计算整个文档数量
```js
db.sc.aggregate([{
$group:{_id:'$sex', people:{$sum:1}}
}])
```
管道处于平级状态,可以向下传递使用
```js
db.sc.aggregate([
{
$group:{_id: '$sex', renshu:{$sum: 1}}
},
{
$sort: {renshu:1}
}
])
```
### 查询指定字段
```
{
_id: 123,
data: {
page: 1,
list: [1,2,3,4,5]
}
}
```
如上述只需要查询出指定`page``list `属性,可以直接使用`find()`方法的过滤projection操作。
projection 参数的使用方法
```js
db.collection.find(query, projection)
```
若不指定 projection则默认返回所有键指定 projection 格式如下,有两种模式
```js
db.collection.find(query, {title: 1, by: 1}) // inclusion模式 指定返回的键,不返回其他键
db.collection.find(query, {title: 0, by: 0}) // exclusion模式 指定不返回的键,返回其他键
```
因此:
```js
db.pop.find(
{'data.page' : 1},
{'data.list':1}
)
```

View File

@ -0,0 +1,365 @@
众所周知JavaScript 是一门单线程的语言。但它的实现环境可以帮助我们创建多进程甚至是多线程,这样在遇到高压力的性能计算时,可以更好的利用多核 CPU 资源。
## 基本概念
- 调度:线程作为调度和分配的基本单位,进程作为拥有资源的基本单位;
- 并发性:不仅进程之间可以并发执行,同一个进程的多个线程之间也可并发执行;
- 拥有资源:进程是拥有资源的一个独立单位,线程不拥有系统资源,但可以访问隶属于进程的资源;
- 系统开销:在创建或撤消进程时,由于系统都要为之分配和回收资源,导致系统的开销明显大于创建或撤消线程时的开销。进程和线程的关系:
基本总结,一个进程可以有多个线程,线程之间可以相互通信。
进程是 `CPU资源分配` 的最小单位;进程内的线程共享进程的资源。
线程是 `CPU计算调度` 的最小单位。线程是真正用来执行程序的,执行计算的
### 多进程与多线程
- 多进程:在同一个时间里,同一个计算机系统中如果允许两个或两个以上的进程处于运行状态。多进程带来的好处是明显的,比如你可以听歌的同时,打开编辑器敲代码,编辑器和听歌软件的进程之间丝毫不会相互干扰。
- 多线程:程序中包含多个执行流,即在一个程序中可以同时运行多个不同的线程来执行不同的任务,也就是说允许单个程序创建多个并行执行的线程来完成各自的任务。
以Chrome浏览器中为例当你打开一个 Tab 页时其实就是创建了一个进程一个进程中可以有多个线程比如渲染线程、JS 引擎线程、HTTP 请求线程等等。当你发起一个请求时,其实就是创建了一个线程,当请求结束后,该线程可能就会被销毁。
## 多进程优势
例如我们有大量的 CPU 计算任务需要进行,而使用单个进程的性能必定需要等待前个任务计算完才能计算下一个。因为是 CPU 大量计算的任务,这使用事件循环也不好处理。
做个简单的例子,这里使用斐波那契数列做个 CPU 任务的模拟,为了模拟到位,这里使用比较耗时的递归来计算斐波那契数列。
```ts
const start = Date.now();
const fibo = (n: number): number => {
if (n <= 1) {
return n;
}
return fibo(n - 1) + fibo(n - 2);
};
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
console.log(`pid: ${process.pid} result: ${fibo(40)} time: ${Date.now() - start}ms`);
```
我的 Ryzen 7 4800U 有 16 个核心(超线程),但不推荐直接占满所有的进程,所里这里计算了 8 次,用于等下与 8 个进程对比。由于是但进程的模式,所有整个计算过程是阻塞的,且 pid 是相同的,耗时也是累加的。也就是说计算完这 8 个斐波那契数列需要总共花费 8321 毫秒。
```bash
$ npx ts-node test.ts
pid: 2112 result: 102334155 time: 1549ms
pid: 2112 result: 102334155 time: 2600ms
pid: 2112 result: 102334155 time: 3549ms
pid: 2112 result: 102334155 time: 4472ms
pid: 2112 result: 102334155 time: 5445ms
pid: 2112 result: 102334155 time: 6388ms
pid: 2112 result: 102334155 time: 7360ms
pid: 2112 result: 102334155 time: 8321ms
```
## 多进程改造
Node 是单进程这就会存在一个问题无法充分利用CPU等资源。Node提供 [child_process](http://nodejs.cn/api/child_process.html) 实现子进程,从而试下广义的多进程模式。通过 `child_process` 可以实现一个主进程,多个子进程模式,主进程称为 `master` 进程,子进程称为`worker` 进程。
Node 提供了 `child_process` 模块来创建子进程,创建的方法包括*异步*和*同步*。这里只涉及到异步创建。
### 创建多进程
node 中有提供`child_process`模块,这个模块中,提供了多个方法来创建子进程:
```js
const { spawn, exec, execFile, fork } = require('child_process');
```
在这里的 fork 创建是最为方便且容易理解的,后续就使用 fork 来进行多进程改造。当然 exec 和 execFile 也可以运行其他的脚本,这里只需要用上 fork。
关于其他的,可以去 [Child process | Node.js v16.1.0 Documentation (nodejs.org)](https://nodejs.org/api/child_process.html#child_process_asynchronous_process_creation) 查看。
### 进程间通信
node 主要是主进程与子进程间的通信,主进程和子进程之间是通过 IPCInter Process Communication进程间通信进行通信的IPC 也是由底层的 libuv 根据不同的操作系统来实现的。
我这里将斐波那契的计算分为两个文件,分别是`app.ts`作为主进程用来创建和管理子进程,和`worker.ts`用来计算斐波那契数列。
主进程这里使用`for`循环来根据 CPU 的数量创建子进程。同时因为 node 使用事件循环的工作模式,所以这里不推荐一次性沾满所有的 CPU 超线程node 底层会用到其他核CPU进行事件循环的处理。如果创建了过多的子进程可能会导致内存溢出甚至阻塞事件循环。最终导致整体性能下降。
```ts
// app.ts
import os from 'os';
import { fork } from 'child_process';
import path from 'path';
const cpus = os.cpus().length;
// 大于4个超线程时派分子进程
const len = cpus >= 4 ? cpus / 2 : 1;
const file = path.resolve(__dirname, 'worker.ts');
for (let i = 0; i < len; i++) {
const worker = fork(file);
worker.send(40);
}
```
而 worker 就简单一点了,它只负责接受主进程发送的消息并计算即可。
```ts
const start = Date.now();
const fibo = (n: number): number => {
if (n <= 1) {
return n;
}
return fibo(n - 1) + fibo(n - 2);
};
process.on('message', (num) => {
const result = `pid: ${process.pid} result: ${fibo(num)} time: ${
Date.now() - start
}ms`;
console.log(result);
});
```
### 运行
虽然将子进程单独分成了一个文件,但这里只需要运行主进程文件即可。可以看到相较于之前的单进程逐个计算八次,这里利用多个进程同时计算,总共耗时在 2000 毫秒左右。
```bash
$ node app.js
pid: 30800 result: 102334155 time: 2116ms
pid: 34432 result: 102334155 time: 2043ms
pid: 26580 result: 102334155 time: 2052ms
pid: 21552 result: 102334155 time: 2148ms
pid: 1648 result: 102334155 time: 2112ms
pid: 18840 result: 102334155 time: 2131ms
pid: 33228 result: 102334155 time: 2213ms
pid: 26144 result: 102334155 time: 2184ms
```
这里只涉及到了多进程的九牛一毛,面对多进程的管理后续还有许多工作需要做,包括进程守护与管理,以及监听端口的问题。使用 fork 都有对应的解决方案,不过这里不深究。上述斐波那契案例只是为了体验下多进程带来的性能上的提升,而 Node.js 常用的案例还是作为 Web 服务器。下面就使用官方基于 fork 的模块 cluster 来改造我之前的一个 koa 后端。
## cluster
cluster 就是在 fork 的基础上进行封装的模块,它可以更方便的使我们去创建多个进程并进行管理。
### 项目概览
先来看下这个项目的大概情况,这个项目很简单,使用 koa 搭建的一个后端 API 服务器。数据库使用的 MongoDB 来存储数据koa 的主要工作就是根据 http 携带的参数查询数据库中的数据,并返回。
```ts
import Koa from 'koa';
import option from './config';
import router from './routers/index';
import logger from 'koa-logger';
import { cors } from './middleware/CORS';
const app = new Koa();
app.use(logger());
app.use(cors);
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(option.port);
console.log(`⚡[server]: running on ${option.port}!`);
```
目前这是标准的 koa 服务器,为了后续对比,先使用 abApache HTTP server benchmarking tool来进行个简单的测试
```bash
root@xfy-virtual-machine:~# ab -c 100 -n 3000 http://192.168.0.110/home/multidata
# ...省略一部分不重要的内容
Concurrency Level: 100
Time taken for tests: 25.130 seconds
Complete requests: 3000
Failed requests: 0
Total transferred: 14250000 bytes
HTML transferred: 13299000 bytes
Requests per second: 119.38 [#/sec] (mean)
Time per request: 837.660 [ms] (mean)
Time per request: 8.377 [ms] (mean, across all concurrent requests)
Transfer rate: 553.77 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 7 1.8 7 13
Processing: 80 824 179.3 764 1620
Waiting: 68 775 168.3 717 1614
Total: 83 831 179.4 771 1629
Percentage of the requests served within a certain time (ms)
50% 771
66% 802
75% 861
80% 896
90% 1102
95% 1223
98% 1346
99% 1488
100% 1629 (longest request)
root@xfy-virtual-machine:~#
```
发了 100 个并发3000 个请求,耗时 25 秒,吞吐量 119。数据还行虽然当时测的时候它占满了我 16 个超线程有点震惊,但最后每秒请求还是只有 120 左右。
### 添加进程
虽然 JavaScript 是单线程的,但是它的实现环境 NodeJs 是多线程的。在没有实现多进程的情况下node 的事件循环也会利用到当前系统下多余的 CPU 超线程的。也就是说,单进程的情况下,它也可以占满所有的 CPU 核心,最大化性能。
但一个主进程的事件循环和多个主进程同时工作,在某些情况下,提供的性能是不同的。同时进程不推荐直接占满所有 CPU 的超线程,最好只占一半,留下事件循环等其他的操作的空间。否则可能会适得其反,导致最终性能的下降。
cluster 用起来相比`child_process.fork()`略微要容易理解一点:
```ts
import os from 'os';
import Koa from 'koa';
import option from './config';
import router from './routers/index';
import logger from 'koa-logger';
import cluster, { worker } from 'cluster';
import { cors } from './middleware/CORS';
const app = new Koa();
const cpus = os.cpus().length;
// 大于4个超线程时派分子进程
const len = cpus >= 4 ? cpus / 2 : 1;
if (cluster.isMaster) {
console.log(`主进程${process.pid}正在运行`);
// 衍生工作进程
for (let i = 0; i < len; i++) {
cluster.fork();
}
cluster.on('exit', (worker, code, signal) => {
console.log(`工作进程${worker.process.pid}已经退出`);
});
console.log(`⚡[server]: running on ${option.port}!`);
} else {
app.use(logger());
app.use(cors);
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(option.port);
console.log(`工作进程${process.pid}已经启动!`);
}
```
使用`cluster.isMaster`来判断当前是否是主进程,如果是主进程则 fork 对应数量的子进程,如果不是,则直接执行子进程的逻辑。监听的端口等小问题都由 cluster 帮我们解决了。
改造很简单,只需要把之前对应的业务逻辑放到 else 语句里即可。
改造完成之后就是来看下激动人心的数据了:
```bash
root@xfy-virtual-machine:~# ab -c 100 -n 3000 http://192.168.0.110/home/multidata
# ...省略一部分不重要的内容
Concurrency Level: 100
Time taken for tests: 11.157 seconds
Complete requests: 3000
Failed requests: 0
Total transferred: 14250000 bytes
HTML transferred: 13299000 bytes
Requests per second: 268.89 [#/sec] (mean)
Time per request: 371.905 [ms] (mean)
Time per request: 3.719 [ms] (mean, across all concurrent requests)
Transfer rate: 1247.27 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 5 2.0 5 21
Processing: 150 358 108.8 334 968
Waiting: 140 343 104.0 320 949
Total: 168 364 109.6 339 983
Percentage of the requests served within a certain time (ms)
50% 339
66% 385
75% 416
80% 433
90% 497
95% 564
98% 668
99% 794
100% 983 (longest request)
root@xfy-virtual-machine:~#
```
发了 100 个并发3000 个请求,耗时 11 秒,吞吐量 268。整体性能翻了一倍左右这应该是当前这个 koa 项目对这颗 4800U 的最大利用了。
### 再快一点点
上述使用多进程已经很快了但是突然发现了一个盲点那就是每次请求都会查询一次数据库无论查询的数据是否是相同的。我们都知道访问一个数据最快的方式是从内存中取得数据其次是内存型数据库如redis
```
内存 -> 内存数据库 -> 传统数据库(可能是磁盘上的数据)
```
于是想到了缓存,当查询参数相同时,直接返回上次查询的结果,不用再次劳驾我们的 MongoDB 了。这种缓存方式适用于连续查询同一个数据,当查询不同的数据时,还是需要查询数据库。这也是为了再查询和节约内存之间做了个抉择。
这里为查询 Mongo 做了个小小的更新,每次查询数据库之前,都检查下会不会命中缓存。
```ts
// 使用 string 在 Map 中存储缓存数据
const strQuery = JSON.stringify(query);
/**
* 检查缓存对象中是否有数据,
* 如果有数据则再检查是否有Map
* 如果都有,则直接返回缓存的数据,不查询数据库
*/
if (cacheObj.hasOwnProperty(collection)) {
if (cacheObj[collection].has(strQuery)) {
res = cacheObj[collection].get(strQuery);
console.log('命中缓存');
} else {
await queryMongo();
cacheObj[collection] = new Map();
res ? cacheObj[collection].set(strQuery, res) : void 0;
}
} else {
await queryMongo();
cacheObj[collection] = new Map();
res ? cacheObj[collection].set(strQuery, res) : void 0;
}
```
再来看下测压的数据:
```bash
root@xfy-virtual-machine:~# ab -c 100 -n 3000 http://192.168.0.112/home/multidata
# ...省略一部分不重要的内容
Concurrency Level: 100
Time taken for tests: 9.406 seconds
Complete requests: 3000
Failed requests: 0
Total transferred: 14250000 bytes
HTML transferred: 13299000 bytes
Requests per second: 318.94 [#/sec] (mean)
Time per request: 313.543 [ms] (mean)
Time per request: 3.135 [ms] (mean, across all concurrent requests)
Transfer rate: 1479.44 [Kbytes/sec] received
Connection Times (ms)
min mean[+/-sd] median max
Connect: 2 6 2.1 5 28
Processing: 58 300 176.8 252 1148
Waiting: 47 292 175.0 245 1139
Total: 67 306 177.1 257 1154
Percentage of the requests served within a certain time (ms)
50% 257
66% 296
75% 321
80% 353
90% 426
95% 590
98% 1092
99% 1106
100% 1154 (longest request)
```
发了 100 个并发3000 个请求,耗时 9 秒,吞吐量 318。但这是 3000 个请求全部都请求同一个数据时的结果,实际情况提升估计没有这么大,但还是有一点的。如果连续访问同一条数据比较多的话,那么这中缓存还是能带来一些性能提升的,至少心里安慰是有了

View File

@ -0,0 +1,857 @@
## 类型
```ts
// 基础类型 null, undefined, symbol, boolean, void
const count: number = 123;
const teacherName: string = 'Dell';
// 对象类型
class Person {}
const teacher: {
name: string;
age: number;
} = {
name: 'Dell',
age: 18
};
const numbers: number[] = [1, 2, 3];
const dell: Person = new Person();
const getTotal: () => number = () => {
return 123;
};
```
### 基本类型
当复制和变量定义不在同一行时ts 就无法推断类型。
```js
string, number
```
```js
null, undefined, symbol, boolean, void
```
### 引用值
数组,对象,类,函数
## 函数返回类型
函数也可以指定返回值的静态类型
```ts
function test(data: { x: number }): object {
console.log(data.x);
return data;
}
test({ x: 123 });
```
如果没有返回值,则使用`void`指定
```ts
function test(data: { x: number }): void {
console.log(data.x);
}
test({ x: 123 });
```
### never
指定`never`返回值表示该函数永远不会执行完
```ts
function test(): never {
while (true) {}
}
```
### 解构参数类型注解
```ts
function add({
firstNumber,
secondNumber,
}: {
firstNumber: number;
secondNumber: number;
}): number {
return firstNumber + secondNumber;
}
add({ firstNumber: 1, secondNumber: 2 });
```
### 匿名函数的类型注解
```ts
const fn = (data: { x: number }): number => {
return data.x;
};
const fnc: (str: string) => string = (str) => {
return str;
};
```
## 数组和元组
### 数组的类型注解
```ts
const arr: (number | string)[] = [1, '2', 3];
const arr: (number | string)[] = [1, '2', 3];
const objArr: object[] = [{}, {}];
const obj1Arr: { name: string }[] = [{ name: 'xfy' }];
const obj2Arr: ({ name: string } | number)[] = [{ name: 'xfy' }, 123];
```
### 类型别名
类型别名和`interface`类似
```ts
type User = {
name: string;
age: number;
};
const arr1: User[] = [{ name: 'xfy', age: 18 }];
interface User1 {
name: string;
age: number;
}
const arr2: User1[] = [{ name: 'xfy', age: 18 }];
```
### 元组
tuple数据解构和数组类似但可以指定每一项的数据类型。
```ts
const tuple: [string, number] = ['xfy', 18];
const csv1: [string, number][] = [];
```
## interface
interface 用于定义一个新的类型集合
```ts
interface Person3 {
name: string;
}
const sayName = (person: Person3): void => {
console.log(person.name);
};
sayName({ name: 'xfy' });
```
### 类型别名和`interface`区别
类型别名可以直接指定单个类型,而接口必须为一个对象
```ts
interface Person1 {
name: string;
}
type Person2 = string;
```
能用接口的尽量使用接口来定义。
### 可选类型
一种类似于可选链的语法,通过 interface 注解可选的数据类型
```ts
interface Person4 {
name: string;
age?: number;
}
const fn1 = (person: Person4): void => {
console.log(person.name);
};
fn1({ name: 'xfy', age: 18 });
```
### 只读
```ts
interface Person5 {
readonly name: string;
age?: number;
}
const fn2 = (person: Person5): void => {
console.log(person.name);
person.name = 'test'; // Cannot assign to 'name' because it is a read-only property.
};
fn2({ name: 'xfy', age: 18 });
```
### 强类型检查
当 interface 注解类型时通过直接传递对象字面量就会进行强类型检查。ts 会检查对象字面量内的每个属性,多余的属性将无法通过检查。
而通过使用一个对象表达式将一个变量进行传递时,检查不会那么严格。
```ts
interface Person6 {
readonly name: string;
age?: number;
}
const fn3 = (person: Person6): void => {
console.log(person.name);
// person.name = 'test';
};
fn3({ name: 'xfy', sex: 'female' }); // 'sex' does not exist in type 'Person6'.
const person1 = {
name: 'xfy',
sex: 'female',
};
fn3(person1);
```
### 其他属性注解
通过 interface 直接注解的类型无法传递对象字面量传递未注解的属性,可以使用定义其他变量的类型注解
```ts
interface Person6 {
readonly name: string;
age?: number;
[propName: string]: any;
}
const fn3 = (person: Person6): void => {
console.log(person.name);
// person.name = 'test';
};
fn3({ name: 'xfy', sex: 'female' });
```
### 注解方法
除了注解指定的属性类型,还可以注解方法,并注解函数的返回值类型
```ts
interface Person6 {
readonly name: string;
age?: number;
[propName: string]: any;
say(): string;
}
const fn3 = (person: Person6): void => {
console.log(person.name);
// person.name = 'test';
};
fn3({
name: 'xfy',
sex: 'female',
say() {
return 'yyy';
},
});
```
### 类
使用 implements 语法
```ts
interface Person6 {
readonly name: string;
age?: number;
[propName: string]: any;
say(): string;
}
class User2 implements Person6 {
name: 'test';
say() {
return 'yyy';
}
}
```
### 接口继承
接口继承的语法与类继承类似
```ts
interface Person7 {
readonly name: string;
age?: number;
[propName: string]: any;
say(): string;
}
interface Teach extends Person7 {
teach(): void;
}
const test3 = (person: Teach): void => {};
test3({
name: 'xfy',
say() {
return 'yyy';
},
teach() {},
});
```
## 类
TypeScript 中为类定义了多个声明关键字。帮助类声明公共与私有属性。
### public
默认情况下直接声明的属性是通过 public 声明的,即在外部也能正常访问该属性。
```ts
class Person {
name = 'xfy';
sayName() {
return this.name;
}
}
let xfy = new Person();
console.log(xfy.sayName());
console.log(xfy.name);
```
### private
private 与 public 相对立。通过 private 声明的属性只能在当前类的内部被访问到,即使是继承的子类也无法直接访问。
```ts
class Person {
private name = 'xfy';
sayName() {
return this.name;
}
}
let xfy = new Person();
console.log(xfy.sayName());
console.log(xfy.name); // Property 'name' is private and only accessible within class 'Person'.
class Teacher extends Person {
say() {
return this.name; // Property 'name' is private and only accessible within class 'Person'.
}
}
```
### protected
与 private 类型protected 的属性也无法在外部被访问。但是可以在继承的子类中被访问到。
```ts
class Person {
private name = 'xfy';
sayName() {
return this.name;
}
}
let xfy = new Person();
console.log(xfy.sayName());
console.log(xfy.name); // Property 'name' is private and only accessible within class 'Person'.
class Teacher extends Person {
say() {
return this.name; // ok
}
}
```
### constructor
与 JavaScript 的 constructor 不同的是,在 TypeScript 中 constrcutor 需要先在类中定义对应的 public 属性。
```ts
class Person {
name: string;
constructor(name: string) {
this.name = name;
}
}
let xfy = new Person('xfy');
console.log(xfy.name);
```
为了方便起见TypeScript 也有简写 constructor 参数的方法。并且不需要再在内部添加`this.name`了。编译器会帮我们自动生成。
```ts
class Person {
// name: string;
constructor(public name: string) {
// this.name = name;
}
}
let xfy = new Person('xfy');
console.log(xfy.name);
```
constructor 继承时的用法与传统 JavaScript 类似。
```ts
class Person {
// name: string;
constructor(public name: string) {
// this.name = name;
}
}
let xfy = new Person('xfy');
console.log(xfy.name);
class Teacher extends Person {
constructor(name: string, public age: number) {
super(name);
}
}
let t = new Teacher('xfy', 18);
```
> 即使父类没有 constructor子类继承时也需要调用`super()`
### 抽象类
在定义多个有相似方法的类时,可以定义一个抽象类来为同样的方法注解类型。抽象类中也可以包含实际的内容。
```ts
abstract class Geo {
width: number;
abstract getAare(): number;
}
class Circle extends Geo {
// width = '123';
width = 123;
getAare() {
return 123;
}
}
class Square extends Geo {
getAare() {
return 123;
}
}
class Triangle extends Geo {
getAare() {
return 123;
}
}
```
## 单例模式
单例模式Singleton Pattern是多数编程软件中常用的设计模式。通过 TypeScript 就可以为 JavaScript 创建一个单例模式的类。
这里通过 private 将 constructor 隐藏在类的内部。在类体上暴露一个方法`getInstance()`,通过这个方法来获取唯一的实例。同时在类体上还定义一个 private 属性 instance它的类型注解就是该类。每次调用`getInstance()`方法时,通过检查 instance 是否有值,没有就创建一个新的实例,并缓存在 instance 内。后续直接返回 instance。这样就能够保证后续创建的实例都是同一个实例。
```ts
class Demo {
private static instance: Demo;
private constructor(public name: string) {}
static getInstance(name: string) {
if (!Demo.instance) {
Demo.instance = new Demo(name);
}
return Demo.instance;
}
}
let t1 = Demo.getInstance('xfy');
let t2 = Demo.getInstance('dfy');
console.log(t1.name);
console.log(t2.name);
console.log(t1 === t2);
```
## .d.ts
传统的 js 在被引入到 ts 中无法正确的被推断出类型。需要使用`.d.ts`已经注解好类型的文件来转译。
通常在 @types`https://www.npmjs.com/package/@types`
### 定义全局
```ts
$(function () {
$('body').html('<h1>Hi, there</h1>')
})
```
```ts
// 全局变量
declare var $: (param: () => void) => void;
```
```ts
interface JqueryInstance {
html: (content: string) => {}
}
// 函数重载
declare function $(param: () => void): void;
declare function $(patam: string): JqueryInstance;
```
## 函数重载
使用 interface 的语法,实现函数重载
```ts
interface JQuery {
(param: () => void): void;
(patam: string): JqueryInstance;
}
declare var $: JQuery;
```
## tsconfig
使用`tsc --init`初始化一个项目时,会自动生成一个带有注释的`tsconfig.json`配置文件。这个文件就是对 TypeScript 编译的一些配置文件。
一个默认的配置文件可能是这样的:
```json
{
"compilerOptions": {
/* Visit https://aka.ms/tsconfig.json to read more about this file */
/* Basic Options */
// "incremental": true, /* Enable incremental compilation */
"target": "ESNEXT", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */
"module": "commonjs", /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */
// "lib": [], /* Specify library files to be included in the compilation. */
// "allowJs": true, /* Allow javascript files to be compiled. */
// "checkJs": true, /* Report errors in .js files. */
// "jsx": "preserve", /* Specify JSX code generation: 'preserve', 'react-native', 'react', 'react-jsx' or 'react-jsxdev'. */
// "declaration": true, /* Generates corresponding '.d.ts' file. */
// "declarationMap": true, /* Generates a sourcemap for each corresponding '.d.ts' file. */
// "sourceMap": true, /* Generates corresponding '.map' file. */
// "outFile": "./", /* Concatenate and emit output to single file. */
// "outDir": "./", /* Redirect output structure to the directory. */
// "rootDir": "./", /* Specify the root directory of input files. Use to control the output directory structure with --outDir. */
// "composite": true, /* Enable project compilation */
// "tsBuildInfoFile": "./", /* Specify file to store incremental compilation information */
// "removeComments": true, /* Do not emit comments to output. */
// "noEmit": true, /* Do not emit outputs. */
// "importHelpers": true, /* Import emit helpers from 'tslib'. */
// "downlevelIteration": true, /* Provide full support for iterables in 'for-of', spread, and destructuring when targeting 'ES5' or 'ES3'. */
// "isolatedModules": true, /* Transpile each file as a separate module (similar to 'ts.transpileModule'). */
/* Strict Type-Checking Options */
"strict": true, /* Enable all strict type-checking options. */
// "noImplicitAny": true, /* Raise error on expressions and declarations with an implied 'any' type. */
// "strictNullChecks": true, /* Enable strict null checks. */
// "strictFunctionTypes": true, /* Enable strict checking of function types. */
// "strictBindCallApply": true, /* Enable strict 'bind', 'call', and 'apply' methods on functions. */
// "strictPropertyInitialization": true, /* Enable strict checking of property initialization in classes. */
// "noImplicitThis": true, /* Raise error on 'this' expressions with an implied 'any' type. */
// "alwaysStrict": true, /* Parse in strict mode and emit "use strict" for each source file. */
/* Additional Checks */
// "noUnusedLocals": true, /* Report errors on unused locals. */
// "noUnusedParameters": true, /* Report errors on unused parameters. */
// "noImplicitReturns": true, /* Report error when not all code paths in function return a value. */
// "noFallthroughCasesInSwitch": true, /* Report errors for fallthrough cases in switch statement. */
// "noUncheckedIndexedAccess": true, /* Include 'undefined' in index signature results */
// "noPropertyAccessFromIndexSignature": true, /* Require undeclared properties from index signatures to use element accesses. */
/* Module Resolution Options */
// "moduleResolution": "node", /* Specify module resolution strategy: 'node' (Node.js) or 'classic' (TypeScript pre-1.6). */
// "baseUrl": "./", /* Base directory to resolve non-absolute module names. */
// "paths": {}, /* A series of entries which re-map imports to lookup locations relative to the 'baseUrl'. */
// "rootDirs": [], /* List of root folders whose combined content represents the structure of the project at runtime. */
// "typeRoots": [], /* List of folders to include type definitions from. */
// "types": [], /* Type declaration files to be included in compilation. */
// "allowSyntheticDefaultImports": true, /* Allow default imports from modules with no default export. This does not affect code emit, just typechecking. */
"esModuleInterop": true, /* Enables emit interoperability between CommonJS and ES Modules via creation of namespace objects for all imports. Implies 'allowSyntheticDefaultImports'. */
// "preserveSymlinks": true, /* Do not resolve the real path of symlinks. */
// "allowUmdGlobalAccess": true, /* Allow accessing UMD globals from modules. */
/* Source Map Options */
// "sourceRoot": "", /* Specify the location where debugger should locate TypeScript files instead of source locations. */
// "mapRoot": "", /* Specify the location where debugger should locate map files instead of generated locations. */
// "inlineSourceMap": true, /* Emit a single file with source maps instead of having a separate file. */
// "inlineSources": true, /* Emit the source alongside the sourcemaps within a single file; requires '--inlineSourceMap' or '--sourceMap' to be set. */
/* Experimental Options */
// "experimentalDecorators": true, /* Enables experimental support for ES7 decorators. */
// "emitDecoratorMetadata": true, /* Enables experimental support for emitting type metadata for decorators. */
/* Advanced Options */
"skipLibCheck": true, /* Skip type checking of declaration files. */
"forceConsistentCasingInFileNames": true /* Disallow inconsistently-cased references to the same file. */
}
}
```
仔细看的话,配置文件内主要包含一个大的字段`"compilerOptions"`,这是针对编译时的配置。对文件的配置还有`include``exclude`
```json
{
"exclude": ["./src/config.ts"],
"compilerOptions": {
// ...
}
}
```
## 联合类型与类型保护
当定义了多个 interface 需要同时使用时,可以使用`|`运算符来同时使用。但是这样也会遇到一个小问题,同时使用两个 interface 时,语法提示只会提示二者共有的类型注解。
因为不能保证传入的参数一定会拥有独有的属性
```ts
interface Bird {
fly: boolean;
sing: () => {};
}
interface Dog {
fly: boolean;
bark: () => {};
}
function trainAnimal(animal: Bird | Dog) {
console.log(animal);
}
```
![image-20210329172943170](images/TypeScript%E4%B8%B4%E7%A2%8E%E7%AC%94%E8%AE%B0/image-20210329172943170.png)
### 类型保护
类型保护有多个方法,作用就是在特定情况下访问独有的属性。
#### 类型断言
断言的目的就是在当前情况下,我非常清楚指定传进来的参数有指定的参数。
假设在当前例子里,参数中的`fly`属性只要为`true`时,就一定能确定是`Bird`接口的类型。那么就可以断言为:
```ts
interface Bird {
fly: boolean;
sing: () => {};
}
interface Dog {
fly: boolean;
bark: () => {};
}
function trainAnimal(animal: Bird | Dog) {
if (animal.fly) {
(animal as Bird).sing();
}
}
```
#### `in`语法
可以直接判断属性是否存在于当前实例中TypeScript 会直接推断出对应的接口。
```ts
function trainAnimalSecond(animal: Bird | Dog) {
if ("sing" in animal) {
animal.sing();
}
}
```
#### `typeof`语法
和使用`in`语法类型,`typeof`语法也能让 TypeScript 做出正确的类型推断。
```ts
function addSomething(firstNum: string | number, secondNum: string | number) {
if (typeof firstNum === "string" || typeof secondNum === "string") {
return `${firstNum}${secondNum}`;
}
return firstNum + secondNum;
}
```
## 枚举类型
```ts
enum Status {
ONLINE,
OFFLINE,
DELETED,
}
function getDetail(status: Status) {
switch (status) {
case Status.ONLINE:
console.log("online!");
break;
case Status.OFFLINE:
console.log("offline!");
break;
case Status.DELETED:
console.log("deleted!");
break;
}
}
getDetail(0);
```
## 函数泛型
泛指的类型generic。通俗的说就是不专门注解函数的参数为指定的某一个类型函数可以接受多个类型但参数的类型必须统一。
```ts
function join<T>(first: T, second: T): string {
return `${first}${second}`;
}
join<string>("1", "2");
```
也可以为指定数组内的属性指定泛型
```ts
// function map<T>(params: Array<T>) {
// return params;
// }
function map<T>(params: T[]) {
return params;
}
map<number>([1, 2, 3]);
```
泛型还支持多个类型
```ts
function join<T, Y>(first: T, second: Y): string {
return `${first}${second}`;
}
join<string, number>("1", 2);
```
函数的返回类型也可以使用泛型。
### 类中的泛型
类也是同样的可以定义泛型
```ts
class DataManager<T> {
constructor(private data: T[]) {}
getItem(index: number) {
return this.data[index];
}
}
const myData = new DataManager<number>([1, 2, 3]);
console.log(myData.getItem(2));
```
### 泛型的继承
泛型可以继承自接口
```ts
interface Item {
name: string;
}
class DataManager<T extends Item> {
constructor(private data: T[]) {}
getItem(index: number): string {
return this.data[index].name;
}
}
const myData = new DataManager([
{
name: "xfy",
},
]);
console.log(myData.getItem(0));
```
### 作为类型注解
泛型也可以作为一个具体的类型注解
```ts
const xfy = <T>(params: T): T => {
return params;
};
```
## namespace
命名空间,可以直接为指定的代码生成作用域。并导出需要的代码。
```ts
namespace Home {
class Header {
constructor() {
const header = document.createElement("header");
header.textContent = `Here is head.`;
document.body.append(header);
}
}
class Content {
constructor() {
const div = document.createElement("div");
div.textContent = `Here is content.`;
document.body.append(div);
}
}
class Footer {
constructor() {
const footer = document.createElement("footer");
footer.textContent = `© 2021 xfy`;
document.body.append(footer);
}
}
export class Page {
constructor() {
new Header();
new Content();
new Footer();
}
}
}
```
命名空间也可以在多个文件之间相互导入导出,就和模块系统类似。但使用了命名空间之间的互相导入之后,需要在`tsconfig.json`中修改模块系统为`amd``system`
使用依赖注释:
```ts
///<reference path='./test.ts' />
```

View File

@ -0,0 +1,120 @@
## 函数
### 重载
重载函数:有多个调用签名的函数。
在多数编程语言中,声明函数时一旦指定了特定的参数和返回类型,就只能使用相应的参数调用参数。但 JavaScript 是一门动态语言,势必需要以多种方式调用一个函数的方法。不仅如此,而且有时输出的类型取决于参数的类型。
TypeScript 也支持动态重载函数声明,而且函数的输出类型却决于输入类型。
一个普通的函数类型注解:
```ts
type Reserve = {
(from: Date, to: Date, destination: string): string;
};
const reserve: Reserve = (from,toOrDest, destination) => {
const cost = Math.floor(Math.random() * (998 - 199) + 198);
return `To ${destination} need ${cost} ${from.toLocaleString()}`
};
console.log(reserve(new Date(), new Date(), 'bali'));
```
函数的重载需要在注解时定义多个类型,在函数声明时需要手动组合两个签名:
```ts
type Reserve = {
(from: Date, to: Date, destination: string): string;
(fr om: Date, destination: string): string;
};
const reserve: Reserve = (
// 参数需要手动在注解并组合两个签名
from: Date,
toOrDest: Date | string,
destination?: string
) => {
const cost = Math.floor(Math.random() * (998 - 199) + 198);
if (toOrDest instanceof Date && destination !== undefined) {
return `To ${destination} need ${cost} ${from.toLocaleString()} ${toOrDest.toLocaleString()}`;
} else {
return `To ${toOrDest} need ${cost} ${from.toLocaleString()}`;
}
};
console.log(reserve(new Date(), new Date(), 'bali'));
console.log(reserve(new Date(), 'bali'));
```
### 多态
使用具体类型的前提是明确知道需要什么类型,并且想确认传入的确实是那个类型。但是,有时事先并不知道需要什么类型,不想限制函数只能接受某个类型。
这种情况可以使用函数泛型generic type参数。
> 在类型层面施加约束的占位类型,也称多态类型参数。
例如我们重写一个简单的数组 filter 方法,在我们老朋友 JavaScript 中,这是一个很基本的函数。
```js
const filter = (arr, fn) => {
let result = [];
for (const i of arr) {
if (fn(i)) {
result.push(i);
}
}
return result;
};
```
但在 TypeScript 中,为了类型保护我们就需要为其添加类型注解。而这个函数的特点就是他可以(需要)接受多种类型的参数,且函数的返回值也是跟着参数的类型变化的。
也许利用重载为其注解所有类型也是可以的:
```ts
type Filter = {
(arr: number[], fn: (item: number) => boolean): number[];
(arr: string[], fn: (item: string) => boolean): string[];
};
```
但是如果遇到了对象数组呢:
```ts
type Filter = {
(arr: number[], fn: (item: number) => boolean): number[];
(arr: string[], fn: (item: string) => boolean): string[];
(arr: Object[], fn: (item: Object) => boolean): Object[];
};
```
Object 无法描述对象结构,它可以代表所有类似对象的结构。
这时候就需要使用泛型了:
```ts
type Filter = {
<T>(arr: T[], fn: (item: T) => boolean): T[];
};
```
这里泛型的意思是filter 函数使用一个泛型参数 T在事先我们不知道其具体的类型。TypeScript 从传入的 arr 参数种推导出 T 的类型。调用 filter 时T 的类型被推导出后,将把 T 出现的每一处替换为推导出的类型。T 就像是一个占位类型类型检查器会根据上下文填充具体的类型。T 把 Filter 的类型参数化了,因此才称其为泛型参数。
#### 泛型作用域
泛型声明的位置不仅限定了泛型的作用域,还决定了 TypeScript 什么时候为泛型绑定具体的类型。
例如之前 Filter 函数的类型:
```ts
type Filter = {
<T>(arr: T[], fn: (item: T) => boolean): T[];
};
const filter:Filter = (arr, fn) // ...
```
`<T>`在调用签名中声明位于签名开始的括号前TypeScript 将在调用 Filter 类型的函数时为 T 绑定具体类型。
而如果把 T 的作用域

255
source/_md/Vue3!.md Normal file
View File

@ -0,0 +1,255 @@
# 61
## setup
setup 方法在实例被创建created之前。
### ref
直接在 setup 中定义变量无法自动成为响应式,需要使用 ref 将其通过 proxy 代理为响应式变量。
```js
const name = ref('xfy')
```
上述是`xfy`变为`Proxy({value: 'xfy'})`这样一个响应式引用。
### reactive
reactive 与 ref 类似,它直接将对象设置为响应式变量。
```js
const state = reactive({
name: 'xfy'
})
```
解构会使其失去响应性,需要使用 toRefs。
### toRef
使用 toRefs 解构时,如果解构的属性是可选的属性。那么 toRefs 不会自动创建默认值,这种情况下需要使用 toRef 来代替它。
```js
props: {
msg: String,
},
setup(props) {
const name = toRef(props, "name");
console.log(name.value);
return {
name,
};
},
```
toRef 如果对应的属性不存在,那么 toRef 会为其创建一个响应式的默认值。
### 解构 reactive
roRefs 可以解构响应式的变量,使其依然保持响应式。对于 reactive 创建的响应式变量也能使用 toRefs 来解构。
```js
setup() {
const state = reactive({
name: "xfy",
});
const { name } = toRefs(state);
return {
name,
};
},
```
## Non-Props
在 Vue3 中,在子组件中可以定义不 Props 属性。在父组件中传递 Props 给子组件时,有多种情况:
* 单根,`inheritAttrs: false`
在默认情况下,子组件中不定义 Props 属性时,在父组件中传递的 Attribute 会直接传递给单根的子组件元素上。当定义了`inheritAttrs: false`时,将不默认转递 Attribute。
* 多根,`inheritAttrs: false`
在子组件中有多个根元素的情况下,可以指定某个根元素继承 Attribute。使用`v-bind`方法。也可以直接访问传递的 Props
```html
<template>
<div>test</div>
<div v-bind="$attrs">{{ $attrs.msg }}</div>
<div>test</div>
</template>
```
## Context
Setup 方法接受两个参数,分别是传递的 Props 和 Context。Context 里分别有三个有用的属性:
```js
setup(props, context) {
// Attribute (非响应式对象)
console.log(context.attrs)
// 插槽 (非响应式对象)
console.log(context.slots)
// 触发事件 (方法)
console.log(context.emit)
}
```
### attrs
attrs 是父组件传递给子组件的 Non-Props可以直接在 attrs 中进行访问。attrs 和 Props 类型,它是有状态对象。会随组件本身的更新而更新,这意味着应该避免对它们进行解构,并始终以 `attrs.x` 或 `slots.x` 的方式引用 property。
与 `props` 不同的是,`attrs` 和 `slots` 是**非**响应式的。如果打算根据 `attrs` 或 `slots` 更改应用副作用,那么应该在 `onUpdated` 生命周期钩子中执行此操作。
### slots
slots 是父组件传递给子组件的插槽内容,可以直接访问具名插槽。
访问的插槽是一个渲染函数,会直接渲染成虚拟 DOM。还可以直接使用 render 函数来渲染出插槽内容。
```html
<!-- 父组件 -->
<HelloWorld msg="Hello Vue 3 in CodeSandbox!"
>this is a test.
<template #test> oh,test </template>
</HelloWorld>
```
```js
// 子组件内
import { h } from "vue";
export default {
name: "HelloWorld",
setup(props, { attrs, slots }) {
console.log(slots.default());
console.log(slots);
console.log(attrs);
return () => h("div", {}, [slots.default(), slots.test()]);
},
};
```
相当于`this.$slots`
### emit
相当于`this.$emit`
## watch
watch 是惰性的。
对于使用 ref 创建的响应式对象watch 可以直接进行监听。而对于 reactive 的响应式对象,需要返回一个函数才能正常监听。
```js
setup() {
const nameObj = reactive({ name: "" });
const nameHistory = reactive([]);
const { name } = toRefs(nameObj);
watch(
() => nameObj.name,
(cur, pre) => {
nameHistory.push(pre);
}
);
return {
name,
nameHistory,
};
},
```
watch 还支持同时监听多个数据的变化,它的两个参数分别都接受数组。不同的是,在回调函数中,参数的顺序是`([第一个当前值, 第二个当前值], [第一个上次值, 第二个上次值])`
```js
watch(
[() => nameObj.name, () => nameObj.engName],
([curN, curEn], [preN, preEn]) => {
console.log([curN, curEn], [preN, preEn]);
}
);
```
### watchEffect
为了根据响应式状态*自动应用*和*重新应用*副作用,我们可以使用 `watchEffect` 方法。它立即执行传入的一个函数,同时响应式追踪其依赖,并在其依赖变更时重新运行该函数。
watchEffect 是非惰性的
```js
watchEffect(() => {
console.log(nameObj.name);
});
```
### 停止所有的 watch
两个 watch 方法都返回一个方法,通过调用返回的方法就能够取消监听。
```js
const stopWacth = watchEffect(() => {
console.log(nameObj.name);
setTimeout(() => {
stopWacth();
}, 5000);
});
```
## 生命周期函数
`setup` 是围绕 `beforeCreate` 和 `created` 生命周期钩子运行的,所以不需要显式地定义它们。换句话说,在这些钩子中编写的任何代码都应该直接在 `setup` 函数中编写。
| 选项式 API | Hook inside `setup` |
| ----------------- | ------------------- |
| `beforeCreate` | Not needed* |
| `created` | Not needed* |
| `beforeMount` | `onBeforeMount` |
| `mounted` | `onMounted` |
| `beforeUpdate` | `onBeforeUpdate` |
| `updated` | `onUpdated` |
| `beforeUnmount` | `onBeforeUnmount` |
| `unmounted` | `onUnmounted` |
| `errorCaptured` | `onErrorCaptured` |
| `renderTracked` | `onRenderTracked` |
| `renderTriggered` | `onRenderTriggered` |
`renderTracked`:每次渲染之后重新手机响应式依赖;
`renderTriggered`:每次触发页面重新渲染时自动执行;
## Composition API 获取 DOM
首先先在 DOM 节点上赋予对应的 ref attr
```html
<template>
<div ref="test"></div>
</template>
```
然后在 setup 中使用 ref 方法创建一个空的响应式变量null变量名需要与获取的 DOM ref 相同。随后直接 return 该变量。
之后在例如 onMounted 这样的生命周期函数中就能访问到对应的 DOM 元素。
```js
setup() {
const test = ref(null);
onMounted(() => {
console.log(test.value);
});
return {
test,
};
},
```
[Composition API 获取 DOM](https://codesandbox.io/s/composition-api-huoqu-dom-dgvro)
## 一些练习
* [composition-api-provide-inject](https://codesandbox.io/s/composition-api-provide-inject-kbows)
* [Composition API 获取 DOM](https://codesandbox.io/s/composition-api-huoqu-dom-dgvro)
* [composition-api ToDoList](https://codesandbox.io/s/composition-api-todolist-f1fv4)

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,376 @@
### 初始化环境
```bash
yarn init
yarn add webpack webpack-cli -D
```
## webpack
模块 loader 可以链式调用。链中的每个 loader 都将对资源进行转换。链会逆序执行。第一个 loader 将其结果(被转换后的资源)传递给下一个 loader依此类推。最后webpack 期望链中的最后的 loader 返回 JavaScript。
### 配置文件
配置文件中需要一个入口文件,即为被打包的 js 文件。同时需要一个输出的目录,与打包后的文件名。
这是最基本的配置,其他的文件需要使用对应的 loader。
```js
const path = require('path');
module.exports = {
entry: './src/index.js',
output: {
filename: 'main.js',
path: path.resolve(__dirname, 'dist'),
},
};
```
而在`index.html`中就只需要写打包后的路径
```html
<script src="main.js"></script>
```
### typescript
```
yarn add typescript ts-loader -D
```
webpack.config.js
```js
const path = require('path');
module.exports = {
entry: './src/index.ts',
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
],
},
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: 'bundle.js',
path: path.resolve(__dirname, 'dist'),
},
};
```
### html-webpack-plugin
```js
const HtmlWebpackPlugin = require('html-webpack-plugin');
plugins: [
new HtmlWebpackPlugin({
title: 'test',
}),
],
```
使用模板时,需要使用 ejs 语法来获取配置文件中的 title。
```html
<title><%= htmlWebpackPlugin.options.title %></title>
```
#### ejs 语法与 html-loader 冲突
`html-loader``html-webpack-plugin`是冲突的。使用了`html-loader`之后,`html-webpack-plugin``<%= %>`功能就全部失效了。
### CSS loader
```js
yarn add sass-loader sass style-loader css-loader -D
```
```js
{
test: /\.css$/i,
use: ['style-loader', 'css-loader'],
},
{
test: /\.s[ac]ss$/i,
use: [
// 将 JS 字符串生成为 style 节点
'style-loader',
// 将 CSS 转化成 CommonJS 模块
'css-loader',
// 将 Sass 编译成 CSS
'sass-loader',
],
},
```
#### 使用 sass 等
webpack 的 loader 是从下到上,以及从右到左来进行加载的。当使用了 sass、postcss 等,需要保证其顺序的正确性。
```js
// CSS, PostCSS, and Sass
{
test: /\.(scss|css)$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
},
```
### 管理图片
webpack 有资源模块 (asset module),它是一种模块类型,它允许使用资源文件(字体,图标等)而无需配置额外 loader。
在处理图片时使用资源模块。
在 webpack 5 之前,通常使用:
- [`raw-loader`](https://webpack.docschina.org/loaders/raw-loader/) 将文件导入为字符串
- [`url-loader`](https://webpack.docschina.org/loaders/url-loader/) 将文件作为 data URI 内联到 bundle 中
- [`file-loader`](https://webpack.docschina.org/loaders/file-loader/) 将文件发送到输出目录
资源模块类型(asset module type),通过添加 4 种新的模块类型,来替换所有这些 loader
- `asset/resource` 发送一个单独的文件并导出 URL。之前通过使用 `file-loader` 实现。
- `asset/inline` 导出一个资源的 data URI。之前通过使用 `url-loader` 实现。
- `asset/source` 导出资源的源代码。之前通过使用 `raw-loader` 实现。
- `asset` 在导出一个 data URI 和发送一个单独的文件之间自动选择。之前通过使用 `url-loader`,并且配置资源体积限制实现。
```js
{
test: /\.(png|svg|jpg|jpeg|gif|webp)$/i,
type: 'asset/resource',
},
```
如果需要在 css 或 html 中处理图片,需要安装对应的 css loader 和 html-loader。
在使用 [css-loader](https://webpack.docschina.org/loaders/css-loader) 时,如前所示,会使用类似过程处理你的 CSS 中的 `url('./my-image.png')`。loader 会识别这是一个本地文件,并将 `'./my-image.png'` 路径,替换为 `output` 目录中图像的最终路径。而 [html-loader](https://webpack.docschina.org/loaders/html-loader) 以相同的方式处理 `<img src="./my-image.png" />`
### 管理字体
字体与图片同理,也是使用资源模块来管理
```js
{
test: /\.(woff|woff2|eot|ttf|otf)$/i,
type: 'asset/resource',
},
```
## 开发环境
### 使用 source map
当 webpack 打包源代码时,可能会很难追踪到 error(错误) 和 warning(警告) 在源代码中的原始位置。
为了更容易地追踪 error 和 warningJavaScript 提供了 [source maps](http://blog.teamtreehouse.com/introduction-source-maps) 功能,可以将编译后的代码映射回原始源代码。如果一个错误来自于 `b.js`source map 就会明确的告诉你。
source map 使用 devtool 来进行配置。如下,会在打包时生成单独的`.map`文件:
```js
devtool: 'source-map',
```
> source map 有许多 [可用选项](https://webpack.docschina.org/configuration/devtool),请务必仔细阅读它们
### 开发工具
webpack 提供几种可选方式,帮助我们在代码发生变化后自动编译代码:
1. webpack's [Watch Mode](https://webpack.docschina.org/configuration/watch/#watch)
2. [webpack-dev-server](https://github.com/webpack/webpack-dev-server)
3. [webpack-dev-middleware](https://github.com/webpack/webpack-dev-middleware)
### watch mode(观察模式)
观察模式就是在保存文件时webpack 监听文件的变化,从而立即进行打包。
```js
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1",
"watch": "webpack --watch",
"build": "webpack"
},
```
### webpack-dev-server
webpack-dev-server 为我们直接提供了一个简易的 web server并且具有 live reloading(实时重新加载) 功能。
```js
yarn add webpack-dev-server -D
```
```js
// webpack.config.js
devServer: {
contentBase: './dist',
},
```
webpack-dev-server 在编译之后不会写入到任何输出文件。而是将 bundle 文件保留在内存中,然后将它们 serve 到 server 中,就好像它们是挂载在 server 根路径上的真实文件一样。如果你的页面希望在其他不同路径中找到 bundle 文件,则可以通过 dev server 配置中的 [`publicPath`](https://webpack.docschina.org/configuration/dev-server/#devserverpublicpath-) 选项进行修改。
> `webpack-dev-server` 会从 `output.path` 中定义的目录为服务提供 bundle 文件,即,文件将可以通过 `http://[devServer.host]:[devServer.port]/[output.publicPath]/[output.filename]` 进行访问
### webpack-dev-middleware
webpack-dev-middleware 是使用第三方的 web server express、koa等作为中间件来提供服务。它可以把 webpack 处理过的文件发送到一个 server。 `webpack-dev-server` 在内部使用了它,然而它也可以作为一个单独的 package 来使用,以便根据需求进行更多自定义设置。
```
yarn add express webpack-dev-middleware -D
```
```js
// webpack.config.js
output: {
filename: '[name].bundle.js',
path: path.resolve(__dirname, 'dist'),
clean: true,
publicPath: '/',
},
```
```js
// server.js
const express = require('express');
const webpack = require('webpack');
const webpackDevMiddleware = require('webpack-dev-middleware');
const app = express();
const config = require('./webpack.config.js');
const compiler = webpack(config);
// 告知 express 使用 webpack-dev-middleware
// 以及将 webpack.config.js 配置文件作为基础配置。
app.use(
webpackDevMiddleware(compiler, {
publicPath: config.output.publicPath,
})
);
// 将文件 serve 到 port 3000。
app.listen(3000, function () {
console.log('Example app listening on port 3000!\n');
});
```
## 缓存
### 输出文件名
我们可以通过替换 `output.filename` 中的 [substitutions](https://webpack.docschina.org/configuration/output/#outputfilename) 设置来定义输出文件的名称。webpack 提供了一种使用称为 **substitution(可替换模板字符串)** 的方式,通过带括号字符串来模板化文件名。其中,`[contenthash]` substitution 将根据资源内容创建出唯一 hash。当资源内容发生变化时`[contenthash]` 也会发生变化。
```js
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
```
### 提取引导模板
webpack 还提供了一个优化功能,可使用 [`optimization.runtimeChunk`](https://webpack.docschina.org/configuration/optimization/#optimizationruntimechunk) 选项将 runtime 代码拆分为一个单独的 chunk。将其设置为 `single` 来为所有 chunk 创建一个 runtime bundle.
将第三方库(library)(例如 `lodash``react`)提取到单独的 `vendor` chunk 文件中,是比较推荐的做法,这是因为,它们很少像本地的源代码那样频繁修改。因此通过实现以上步骤,利用 client 的长效缓存机制,命中缓存来消除请求,并减少向 server 获取资源,同时还能保证 client 代码和 server 代码版本一致。
```js
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
```
## 完整配置文件
```js
const path = require('path');
const HtmlWebpackPlugin = require('html-webpack-plugin');
module.exports = {
entry: './src/index.ts',
mode: 'production',
devtool: 'source-map',
devServer: {
contentBase: './dist',
},
module: {
rules: [
{
test: /\.tsx?$/,
use: 'ts-loader',
exclude: /node_modules/,
},
// CSS, PostCSS, and Sass
{
test: /\.(scss|css)$/,
use: ['style-loader', 'css-loader', 'postcss-loader', 'sass-loader'],
},
// {
// test: /\.css$/i,
// use: ['style-loader', 'css-loader'],
// },
// {
// test: /\.s[ac]ss$/i,
// use: [
// // 将 JS 字符串生成为 style 节点
// 'style-loader',
// // 将 CSS 转化成 CommonJS 模块
// 'css-loader',
// // 将 Sass 编译成 CSS
// 'sass-loader',
// ],
// },
{
test: /\.html$/i,
loader: 'html-loader',
},
{
test: /\.(png|svg|jpg|jpeg|gif|webp)$/i,
type: 'asset/resource',
},
],
},
plugins: [
new HtmlWebpackPlugin({
// title: '这是一个测试页面',
template: 'index.html',
}),
],
resolve: {
extensions: ['.tsx', '.ts', '.js'],
},
output: {
filename: '[name].[contenthash].js',
path: path.resolve(__dirname, 'dist'),
clean: true,
},
optimization: {
runtimeChunk: 'single',
splitChunks: {
cacheGroups: {
vendor: {
test: /[\\/]node_modules[\\/]/,
name: 'vendors',
chunks: 'all',
},
},
},
},
};
```

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,269 @@
最近想使用 koa 与 mongodb 做一个简单的后端。
## 监听文件更改
* [How to watch and reload ts-node when TypeScript files change](https://stackoverflow.com/questions/37979489/how-to-watch-and-reload-ts-node-when-typescript-files-change)
## 参数
参数`ctx`是由koa传入的封装了request和response的变量我们可以通过它访问request和response`next`是koa传入的将要处理的下一个异步函数。
```ts
// 对于任何请求app将调用该异步函数处理请求
app.use(async (ctx, next) => {
await next();
ctx.response.type = 'text/html';
ctx.response.body = '<h1>Hello, koa2!</h1>';
});
```
## middleware
每收到一个 http 请求koa 就会调用通过`app.use()`注册的 async 函数,并传入`ctx``next`参数。koa 允许有多个异步函数,并且每个函数都可以用来处理对应部分的事情。在异步函数内使用`await next()`来调用下一个 async 函数。
我们将一个异步函数称之为 middleware。
我们可以将多个 middleware 串联在一起工作,组成处理链。并且由于`awit`的特性,我们可以手动控制下个 middleware 的执行时机。这样就可以非常简单的做一个记录处理时间的 middleware。
我们都是知道 JavaScript 代码是自上往下执行的,所以在前面的 middleware 如果没有调用`next()`方法,则后面的 middleware 就不会执行。
同理,最后一个 middleware 是不需要额外调用`next()`方法的。
```ts
import Koa from 'koa';
const app = new Koa();
app.use(async (ctx, next) => {
// 记录时间
const start = new Date().getTime();
// 处理下个异步函数
await next();
// 处理结束后,记录处理的耗时
const ms = new Date().getTime() - start;
console.log(`${ctx.request.method} ${ctx.request.url} Time: ${ms}ms`);
});
app.use(async (ctx, next) => {
ctx.response.type = 'text/html';
ctx.response.body = '<h1>Hello, koa2!</h1>';
});
app.listen(3000);
console.log('⚡[server]: running on 3000!');
```
### koa-router
新的 koa router 使用的是 class。所以引入后使用`const router = new Router();`来初始化路由。
router 是直接定义了路径的访问规则`router.routes`,它最后被`app.use(router.routes)`所调用。它是一个 middleware所以一般情况下在它内部不需要额外的调用`next()`
```ts
import Koa from 'koa';
import Router from 'koa-router';
const app = new Koa();
const router = new Router();
router.get('/hello/:name', async (ctx, next) => {
// 获取 params
const name: string = ctx.params.name;
ctx.body = `<h1>hello! ${name}</h1>`;
});
router.get('/', async (ctx, next) => {
ctx.body = `<h1>Index!</h1>`;
});
app.use(async (ctx, next) => {
// 记录时间
const start = new Date().getTime();
// 处理下个异步函数
await next();
// 处理结束后,记录处理的耗时
const ms = new Date().getTime() - start;
console.log(`${ctx.request.method} ${ctx.request.url} Time: ${ms}ms`);
});
app.use(router.routes());
app.listen(3000);
console.log('⚡[server]: running on 3000!');
```
#### allowedMethods
当所有路由中间件执行完成之后,若`ctx.status`为空或者404的时候,丰富`response`对象的`header`头。
```js
var Koa = require('koa');
var Router = require('koa-router');
var app = new Koa();
var router = new Router();
app.use(router.routes());
app.use(router.allowedMethods());
```
### koa-bodyparser
默认情况下 koa 处理 post 请求时,无法处理其 JSON 等 body。可以再使用一个中间件`koa-bodyparser`来处理post body 中携带的 JSON 请求。
```ts
import Koa from 'koa';
import Router from 'koa-router';
import bodyParser from 'koa-bodyparser';
const app = new Koa();
const router = new Router();
app.use(bodyParser());
router.get('/hello/:name', async (ctx, next) => {
const name: string = ctx.params.name;
ctx.body = `<h1>hello! ${name}</h1>`;
});
router.get('/', async (ctx, next) => {
ctx.body = `<h1>Index</h1>
<form action="/signin" method="post">
<p>Name: <input name="name" value="xfy" required></p>
<p>Password: <input name="password" type="password"></p>
<p><input type="submit" value="Submit"></p>
</form>`;
});
router.post('/signin', async (ctx, next) => {
ctx.body = ctx.request.body;
});
app.use(async (ctx, next) => {
// 记录时间
const start = new Date().getTime();
// 处理下个异步函数
await next();
// 处理结束后,记录处理的耗时
const ms = new Date().getTime() - start;
console.log(`${ctx.request.method} ${ctx.request.url} Time: ${ms}ms`);
});
app.use(router.routes());
app.listen(3000);
console.log('⚡[server]: running on 3000!');
```
### koa-static
koa-static 的目的是方便直接使用 koa 创建一个静态资源的 web 服务器。
```ts
import Koa from 'koa';
import Router from 'koa-router';
import bodyParser from 'koa-bodyparser';
import path from 'path';
import staticServer from 'koa-static';
import duration from './middleware/duration';
const app = new Koa();
const router = new Router();
const staticPath = './static';
app.use(bodyParser());
router.post('/signin', async (ctx, next) => {
ctx.body = ctx.request.body;
});
app.use(duration);
app.use(staticServer(path.join(__dirname, staticPath)));
app.listen(3000);
console.log('⚡[server]: running on 3000!');
```
## 路由设计
目录
```
├── nodemon.json
├── package.json
├── server
| ├── app.ts
| ├── controllers // 控制页面
| | └── test.ts // test 路由等
| ├── interface
| | └── index.ts
| ├── middleware
| | └── duration.ts
| └── routers
| └── index.ts // 路由集合
├── static
```
这里将单独的路由都拆分到`controllers`目录内,并和其他单独页面逻辑放一起。然后由`routers/index.ts`将所有路由整合到一起,最后交由`app.ts`注册路由。
```ts
// test.ts
import { Context } from 'koa';
const test = async (ctx: Context) => {
ctx.body = 'test!';
};
export default test;
```
```ts
// index.ts
import Router from 'koa-router';
import test from '../controllers/test';
const router = new Router();
router.get('/test', test);
export default router;
```
```ts
// app.ts
import router from './routers/index';
app.use(router.routes());
app.use(router.allowedMethods());
app.listen(3000);
console.log('⚡[server]: running on 3000!');
```
### 处理 404
在访问没有指定的路由或路径时,会遇到 404 的错误。默认情况下 koa 会自己返回一个 Not Found 的页面,并一起发送一个 404 的状态码。
```ts
ctx.throw(404);
```
当然我们也可以手动接管这个处理,一个简单的中间件可以使其在 404 时返回指定的页面:
```ts
app.use(async (ctx, next) => {
try {
await next();
if (ctx.status == 404) {
ctx.throw(404);
}
} catch (err) {
ctx.body = `<h1>404´дゞ</h1>`;
}
});
```
## mongodb

View File

@ -1,24 +1,95 @@
---
title: 第一个SPA的踩坑总结
date: 2021-05-13 14:18:24
tags: [JavaScript, Vue, TypeScript]
categories: 踩坑
url: first-one-SPA
index_img: /images/第一个SPA的总结/logo.webp
---
## 重制版
在没有写完的情况下弃坑了,后来在写另一个 Vue3 的练手项目时想起来这个曾经入手 Vue2 的入门项目。
所以打算使用 Vue3 + TypeScript 重构一下。
目前进度:
- [x] 首页
- [x] 详情页
- [ ] 添加到购物车
- [ ] 收藏
- [x] 分类
- [x] 标签滚动
- [ ] 购物车
- [ ] 我的
[仓库地址](https://github.com/DefectingCat/gugu-mall)
## TypeScript
### Vuex
在 Vuex 中正确的使用了 TypeScript 可以直接静态提示 state 的类型以及属性。而在 Vuex 中为 state 注解需要用到官方的泛型。
第一步,为 state 做注解:
```ts
// types/state.ts
type CartObj = {
iid: string | string[];
imgURL: string;
title: string | undefined;
desc: string | undefined;
newPrice: string | undefined;
};
export type State = {
cartList: CartObj[];
};
```
在 store 中,使用`createStore()`方法创建 store 时,在泛型中传入刚刚定义好的类型:
```ts
// types
import { State } from '@/types/store';
export default createStore<State>({
state: {
cartList: [],
},
mutations,
actions,
getters,
// modules: {},
});
```
这时state 中的数据就已经被注解类型了。
在官方类型注解文件中可以看到`createStore()`方法中参数使用的接口,其中 state 直接被注解为泛型 S。而 mutations 等,需要使用各自的接口。
```ts
export interface StoreOptions<S> {
state?: S | (() => S);
getters?: GetterTree<S, S>;
actions?: ActionTree<S, S>;
mutations?: MutationTree<S>;
modules?: ModuleTree<S>;
plugins?: Plugin<S>[];
strict?: boolean;
devtools?: boolean;
}
```
到这里仅仅只是注解完了 state接着就是 mutations。这里的 mutations 使用接口 MutationTree 并传递一个泛型,将刚刚注解的 state 传递过去。
```ts
// mutations.ts
import { MutationTree } from 'vuex';
// types
import { CartObj } from '@/types/detail';
import { State } from '@/types/store';
const mutations: MutationTree<State> = {
addCart(state, info: CartObj): void {
console.log(state);
},
};
export default mutations;
```
### 索引签名
使用下标访问对象时会要求接口中声明了索引签名,否则不允许直接使用下标的方式访问对象属性。
@ -112,7 +183,7 @@ props: {
## v-for
### 控制`v-for`
### 控制 v-for
```html
<span v-for="index of goods.services.length - 2" :key="index">
@ -525,7 +596,7 @@ module.exports = {
style="width: 48%; margin-top: 10px"
```
![](../images/第一个SPA的总结/2021-03-01-12-15-31.png)
![](../images/第一个SPA的总结/2021-03-01-12-15-31.webp)
当然也可以使用 space-evently
@ -565,7 +636,123 @@ style="width: 48%; margin-top: 10px"
}
```
![](../images/第一个SPA的总结/2021-03-12-10-48-27.png)
![](../images/第一个SPA的总结/2021-03-12-10-48-27.webp)
### 动画
在尾期的时候,觉得有些地方过渡的不是很自然,于是想添加一些动画。
#### 滑动缓入动画
在商品列表被滑动进入视口时,想添加一个缓入的动画,这样看上去会显得自然一点(应该吧)。既然是进入视口时发生的动画,第一个想到的自然是使用 IntersectionObserver API 来检测是否与视口相交。如果检测到相交之后,则添加对应的行内样式。
```ts
// 使用 Intersection Observer API 来监听项目是否和视口相交
const observer = new IntersectionObserver((entries, observer) => {
entries.forEach((entry) => {
if (entry.isIntersecting) {
// 断言为 HTMLElement 才可操作 style
const target = entry.target as HTMLElement;
setTimeout(() => {
target.style.transform = `translateY(0px)`;
target.style.opacity = `1`;
}, 300);
// 动画完成后取消监听
observer.unobserve(entry.target);
}
});
});
// vfor 循环中使用两个方法添加列表监听
const setList1Ref = (el: { $el: HTMLElement }) => {
el ? observer.observe(el.$el) : void 0;
};
const setList2Ref = (el: { $el: HTMLElement }) => {
el ? observer.observe(el.$el) : void 0;
};
```
元素本身的样式则提前准备好过渡:
```css
// 视口相交动画
transform: translateY(35px);
opacity: 0;
transition: all 0.2s ease;
```
这里也顺便提一下Vue3 中使用 ref 拿取`v-for`循环中的节点需要在节点上绑定一个方法,之后会在更新时自动触发方法。这里就是使用方法来为每个节点添加监视的。
```html
<GoodsListItem
class="goods-list__col__item"
v-for="item of goods[currentTab].list1"
:key="item"
:item="item"
:ref="setList1Ref"
/>
```
```ts
const setList1Ref = (el: { $el: HTMLElement }) => {
el ? observer.observe(el.$el) : void 0;
};
```
#### 列表动画
在个人的 Profile 页面有几个无序列表用来展示对应的选项,由于关于页做了个卡片的效果,所以给它写了个简单的 CSS 动画,在每次进入页面时都会执行一次。
```css
@keyframes slidein {
from {
transform: translateY(10px);
}
to {
transform: translateY(-20px);
}
}
@keyframes spin {
from {
transform: translateY(5px);
}
to {
transform: translateY(-25px);
}
}
```
但总感觉还少点什么,于是就给列表也加了一些小过渡。但所有列表同时过渡也不是很自然,于是做了点小操作让它们并不是同一时间开始动画,持续时间也略有不同,这样看上去更和谐一点。
具体的实现方式是使用同样的方式拿到`v-for`循环中的所有元素节点,然后再`onMounted`之后触发动画。
第一个列表的动画持续时间是 200 ms后面每个的持续时间都增加 100 ms。同时开始也设置了个延迟为 100 ms 后执行,后续每个也递增 100 ms。这样就有了种阶梯的感觉。
```ts
const setListItem = (el: HTMLElement) => {
content.list?.push(el);
};
const listAnimat = () => {
// 手搓动画
// 每个动画间隔增加100ms持续实际增加100ms
let time = 0.2;
let timeout = 0;
for (const i of content.list) {
setTimeout(() => {
i.style.transform = `translateY(0px)`;
i.style.transition = `all ${time}s`;
i.style.opacity = `1`;
}, timeout);
time += 0.1;
timeout += 100;
}
};
// 组件内使用
onMounted(async () => {
await nextTick();
listAnimat();
});
```
## 后端
@ -599,12 +786,46 @@ docker cp 979534a50979:/guguMall.tar.gz /
> windows PowerShell环境下`/`也就是 C 盘
### 恢复
```bash
mongorestore -h 127.0.0.1 -d guguMall ./guguMall
```
### CORS
## ToDo
跨域是经典的问题了,主要是用来保护客户端的。这里使用 CORS 来解决,做了个简单的中间件:
- [x] 分类页面滚动
- [x] 分类页面 list 小圆角
- [ ] 首页子组件切换保留滚动位置
- [ ] 每周推荐使用 Grid 布局
- [ ] 整体 UI 美化
```ts
import { Context } from 'koa';
export async function cors(ctx: Context, next: () => Promise<unknown>) {
// 允许来自所有域名请求
ctx.set('Access-Control-Allow-Origin', '*');
// 这样就能只允许 http://localhost:8080 这个域名的请求了
// ctx.set("Access-Control-Allow-Origin", "http://localhost:8080");
// 设置所允许的HTTP请求方法
ctx.set('Access-Control-Allow-Methods', 'OPTIONS, GET, PUT, POST, DELETE');
// 字段是必需的。它也是一个逗号分隔的字符串,表明服务器支持的所有头信息字段.
ctx.set(
'Access-Control-Allow-Headers',
'x-requested-with, accept, origin, content-type'
);
// 服务器收到请求以后检查了Origin、Access-Control-Request-Method和Access-Control-Request-Headers字段以后确认允许跨源请求就可以做出回应。
// Content-Type表示具体请求中的媒体类型信息
ctx.set('Content-Type', 'application/json;charset=utf-8');
/*
CORS请求时XMLHttpRequest对象的getResponseHeader()方法只能拿到6个基本字段
Cache-Control、
Content-Language、
Content-Type、
Expires、
Last-Modified、
Pragma。
*/
// 需要获取其他字段时使用Access-Control-Expose-Headers
// getResponseHeader('myData')可以返回我们所需的值
// ctx.set('Access-Control-Expose-Headers', 'myData');
await next();
}
```

Binary file not shown.

Before

Width:  |  Height:  |  Size: 314 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 579 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 44 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.3 KiB

490
yarn.lock
View File

@ -9,7 +9,7 @@
dependencies:
"@babel/highlight" "^7.12.13"
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.13.12", "@babel/compat-data@^7.13.15":
"@babel/compat-data@^7.13.11", "@babel/compat-data@^7.13.15":
version "7.13.15"
resolved "https://registry.npm.taobao.org/@babel/compat-data/download/@babel/compat-data-7.13.15.tgz?cache=0&sync_timestamp=1617897171596&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcompat-data%2Fdownload%2F%40babel%2Fcompat-data-7.13.15.tgz#7e8eea42d0b64fda2b375b22d06c605222e848f4"
integrity sha1-fo7qQtC2T9orN1si0GxgUiLoSPQ=
@ -19,20 +19,25 @@
resolved "https://registry.npm.taobao.org/@babel/compat-data/download/@babel/compat-data-7.13.8.tgz?cache=0&sync_timestamp=1614382893545&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fcompat-data%2Fdownload%2F%40babel%2Fcompat-data-7.13.8.tgz#5b783b9808f15cef71547f1b691f34f8ff6003a6"
integrity sha1-W3g7mAjxXO9xVH8baR80+P9gA6Y=
"@babel/core@^7.13.15":
version "7.13.15"
resolved "https://registry.npm.taobao.org/@babel/core/download/@babel/core-7.13.15.tgz#a6d40917df027487b54312202a06812c4f7792d0"
integrity sha1-ptQJF98CdIe1QxIgKgaBLE93ktA=
"@babel/compat-data@^7.14.0":
version "7.14.0"
resolved "https://registry.nlark.com/@babel/compat-data/download/@babel/compat-data-7.14.0.tgz?cache=0&sync_timestamp=1619727430608&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fcompat-data%2Fdownload%2F%40babel%2Fcompat-data-7.14.0.tgz#a901128bce2ad02565df95e6ecbf195cf9465919"
integrity sha1-qQESi84q0CVl35Xm7L8ZXPlGWRk=
"@babel/core@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/core/download/@babel/core-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fcore%2Fdownload%2F%40babel%2Fcore-7.14.2.tgz#54e45334ffc0172048e5c93ded36461d3ad4c417"
integrity sha1-VORTNP/AFyBI5ck97TZGHTrUxBc=
dependencies:
"@babel/code-frame" "^7.12.13"
"@babel/generator" "^7.13.9"
"@babel/helper-compilation-targets" "^7.13.13"
"@babel/helper-module-transforms" "^7.13.14"
"@babel/helpers" "^7.13.10"
"@babel/parser" "^7.13.15"
"@babel/generator" "^7.14.2"
"@babel/helper-compilation-targets" "^7.13.16"
"@babel/helper-module-transforms" "^7.14.2"
"@babel/helpers" "^7.14.0"
"@babel/parser" "^7.14.2"
"@babel/template" "^7.12.13"
"@babel/traverse" "^7.13.15"
"@babel/types" "^7.13.14"
"@babel/traverse" "^7.14.2"
"@babel/types" "^7.14.2"
convert-source-map "^1.7.0"
debug "^4.1.0"
gensync "^1.0.0-beta.2"
@ -40,7 +45,7 @@
semver "^6.3.0"
source-map "^0.5.0"
"@babel/generator@^7.13.0", "@babel/generator@^7.13.9":
"@babel/generator@^7.13.0":
version "7.13.9"
resolved "https://registry.npm.taobao.org/@babel/generator/download/@babel/generator-7.13.9.tgz#3a7aa96f9efb8e2be42d38d80e2ceb4c64d8de39"
integrity sha1-Onqpb577jivkLTjYDizrTGTY3jk=
@ -49,6 +54,15 @@
jsesc "^2.5.1"
source-map "^0.5.0"
"@babel/generator@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/generator/download/@babel/generator-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fgenerator%2Fdownload%2F%40babel%2Fgenerator-7.14.2.tgz#d5773e8b557d421fd6ce0d5efa5fd7fc22567c30"
integrity sha1-1Xc+i1V9Qh/Wzg1e+l/X/CJWfDA=
dependencies:
"@babel/types" "^7.14.2"
jsesc "^2.5.1"
source-map "^0.5.0"
"@babel/helper-annotate-as-pure@^7.12.13":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/helper-annotate-as-pure/download/@babel/helper-annotate-as-pure-7.12.13.tgz#0f58e86dfc4bb3b1fcd7db806570e177d439b6ab"
@ -64,7 +78,7 @@
"@babel/helper-explode-assignable-expression" "^7.12.13"
"@babel/types" "^7.12.13"
"@babel/helper-compilation-targets@^7.13.0", "@babel/helper-compilation-targets@^7.13.8":
"@babel/helper-compilation-targets@^7.13.0":
version "7.13.10"
resolved "https://registry.npm.taobao.org/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.13.10.tgz#1310a1678cb8427c07a753750da4f8ce442bdd0c"
integrity sha1-ExChZ4y4QnwHp1N1DaT4zkQr3Qw=
@ -74,12 +88,12 @@
browserslist "^4.14.5"
semver "^6.3.0"
"@babel/helper-compilation-targets@^7.13.13":
version "7.13.13"
resolved "https://registry.npm.taobao.org/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.13.13.tgz#2b2972a0926474853f41e4adbc69338f520600e5"
integrity sha1-KylyoJJkdIU/QeStvGkzj1IGAOU=
"@babel/helper-compilation-targets@^7.13.16":
version "7.13.16"
resolved "https://registry.nlark.com/@babel/helper-compilation-targets/download/@babel/helper-compilation-targets-7.13.16.tgz#6e91dccf15e3f43e5556dffe32d860109887563c"
integrity sha1-bpHczxXj9D5VVt/+MthgEJiHVjw=
dependencies:
"@babel/compat-data" "^7.13.12"
"@babel/compat-data" "^7.13.15"
"@babel/helper-validator-option" "^7.12.17"
browserslist "^4.14.5"
semver "^6.3.0"
@ -95,6 +109,18 @@
"@babel/helper-replace-supers" "^7.13.0"
"@babel/helper-split-export-declaration" "^7.12.13"
"@babel/helper-create-class-features-plugin@^7.14.0":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/helper-create-class-features-plugin/download/@babel/helper-create-class-features-plugin-7.14.2.tgz?cache=0&sync_timestamp=1620840286087&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-create-class-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-class-features-plugin-7.14.2.tgz#4e455b0329af29c2d3ad254b5dd5aed34595385d"
integrity sha1-TkVbAymvKcLTrSVLXdWu00WVOF0=
dependencies:
"@babel/helper-annotate-as-pure" "^7.12.13"
"@babel/helper-function-name" "^7.14.2"
"@babel/helper-member-expression-to-functions" "^7.13.12"
"@babel/helper-optimise-call-expression" "^7.12.13"
"@babel/helper-replace-supers" "^7.13.12"
"@babel/helper-split-export-declaration" "^7.12.13"
"@babel/helper-create-regexp-features-plugin@^7.12.13":
version "7.12.17"
resolved "https://registry.npm.taobao.org/@babel/helper-create-regexp-features-plugin/download/@babel/helper-create-regexp-features-plugin-7.12.17.tgz?cache=0&sync_timestamp=1613661220666&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-create-regexp-features-plugin%2Fdownload%2F%40babel%2Fhelper-create-regexp-features-plugin-7.12.17.tgz#a2ac87e9e319269ac655b8d4415e94d38d663cb7"
@ -133,6 +159,15 @@
"@babel/template" "^7.12.13"
"@babel/types" "^7.12.13"
"@babel/helper-function-name@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/helper-function-name/download/@babel/helper-function-name-7.14.2.tgz?cache=0&sync_timestamp=1620839929144&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-function-name%2Fdownload%2F%40babel%2Fhelper-function-name-7.14.2.tgz#397688b590760b6ef7725b5f0860c82427ebaac2"
integrity sha1-OXaItZB2C273cltfCGDIJCfrqsI=
dependencies:
"@babel/helper-get-function-arity" "^7.12.13"
"@babel/template" "^7.12.13"
"@babel/types" "^7.14.2"
"@babel/helper-get-function-arity@^7.12.13":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/helper-get-function-arity/download/@babel/helper-get-function-arity-7.12.13.tgz#bc63451d403a3b3082b97e1d8b3fe5bd4091e583"
@ -191,19 +226,19 @@
"@babel/types" "^7.13.0"
lodash "^4.17.19"
"@babel/helper-module-transforms@^7.13.14":
version "7.13.14"
resolved "https://registry.npm.taobao.org/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.13.14.tgz?cache=0&sync_timestamp=1617027384265&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-module-transforms%2Fdownload%2F%40babel%2Fhelper-module-transforms-7.13.14.tgz#e600652ba48ccb1641775413cb32cfa4e8b495ef"
integrity sha1-5gBlK6SMyxZBd1QTyzLPpOi0le8=
"@babel/helper-module-transforms@^7.14.0", "@babel/helper-module-transforms@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/helper-module-transforms/download/@babel/helper-module-transforms-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-module-transforms%2Fdownload%2F%40babel%2Fhelper-module-transforms-7.14.2.tgz#ac1cc30ee47b945e3e0c4db12fa0c5389509dfe5"
integrity sha1-rBzDDuR7lF4+DE2xL6DFOJUJ3+U=
dependencies:
"@babel/helper-module-imports" "^7.13.12"
"@babel/helper-replace-supers" "^7.13.12"
"@babel/helper-simple-access" "^7.13.12"
"@babel/helper-split-export-declaration" "^7.12.13"
"@babel/helper-validator-identifier" "^7.12.11"
"@babel/helper-validator-identifier" "^7.14.0"
"@babel/template" "^7.12.13"
"@babel/traverse" "^7.13.13"
"@babel/types" "^7.13.14"
"@babel/traverse" "^7.14.2"
"@babel/types" "^7.14.2"
"@babel/helper-optimise-call-expression@^7.12.13":
version "7.12.13"
@ -279,6 +314,11 @@
resolved "https://registry.npm.taobao.org/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.12.11.tgz#c9a1f021917dcb5ccf0d4e453e399022981fc9ed"
integrity sha1-yaHwIZF9y1zPDU5FPjmQIpgfye0=
"@babel/helper-validator-identifier@^7.14.0":
version "7.14.0"
resolved "https://registry.nlark.com/@babel/helper-validator-identifier/download/@babel/helper-validator-identifier-7.14.0.tgz?cache=0&sync_timestamp=1619727388937&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelper-validator-identifier%2Fdownload%2F%40babel%2Fhelper-validator-identifier-7.14.0.tgz#d26cad8a47c65286b15df1547319a5d0bcf27288"
integrity sha1-0mytikfGUoaxXfFUcxml0Lzycog=
"@babel/helper-validator-option@^7.12.17":
version "7.12.17"
resolved "https://registry.npm.taobao.org/@babel/helper-validator-option/download/@babel/helper-validator-option-7.12.17.tgz?cache=0&sync_timestamp=1613661224272&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fhelper-validator-option%2Fdownload%2F%40babel%2Fhelper-validator-option-7.12.17.tgz#d1fbf012e1a79b7eebbfdc6d270baaf8d9eb9831"
@ -294,14 +334,14 @@
"@babel/traverse" "^7.13.0"
"@babel/types" "^7.13.0"
"@babel/helpers@^7.13.10":
version "7.13.10"
resolved "https://registry.npm.taobao.org/@babel/helpers/download/@babel/helpers-7.13.10.tgz#fd8e2ba7488533cdeac45cc158e9ebca5e3c7df8"
integrity sha1-/Y4rp0iFM83qxFzBWOnryl48ffg=
"@babel/helpers@^7.14.0":
version "7.14.0"
resolved "https://registry.nlark.com/@babel/helpers/download/@babel/helpers-7.14.0.tgz?cache=0&sync_timestamp=1619727432208&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fhelpers%2Fdownload%2F%40babel%2Fhelpers-7.14.0.tgz#ea9b6be9478a13d6f961dbb5f36bf75e2f3b8f62"
integrity sha1-6ptr6UeKE9b5Ydu182v3Xi87j2I=
dependencies:
"@babel/template" "^7.12.13"
"@babel/traverse" "^7.13.0"
"@babel/types" "^7.13.0"
"@babel/traverse" "^7.14.0"
"@babel/types" "^7.14.0"
"@babel/highlight@^7.12.13":
version "7.13.10"
@ -317,10 +357,10 @@
resolved "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.13.10.tgz#8f8f9bf7b3afa3eabd061f7a5bcdf4fec3c48409"
integrity sha1-j4+b97Ovo+q9Bh96W830/sPEhAk=
"@babel/parser@^7.13.15":
version "7.13.15"
resolved "https://registry.npm.taobao.org/@babel/parser/download/@babel/parser-7.13.15.tgz#8e66775fb523599acb6a289e12929fa5ab0954d8"
integrity sha1-jmZ3X7UjWZrLaiieEpKfpasJVNg=
"@babel/parser@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/parser/download/@babel/parser-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fparser%2Fdownload%2F%40babel%2Fparser-7.14.2.tgz#0c1680aa44ad4605b16cbdcc5c341a61bde9c746"
integrity sha1-DBaAqkStRgWxbL3MXDQaYb3px0Y=
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining@^7.13.12":
version "7.13.12"
@ -331,10 +371,10 @@
"@babel/helper-skip-transparent-expression-wrappers" "^7.12.1"
"@babel/plugin-proposal-optional-chaining" "^7.13.12"
"@babel/plugin-proposal-async-generator-functions@^7.13.15":
version "7.13.15"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.13.15.tgz?cache=0&sync_timestamp=1617897172399&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-async-generator-functions%2Fdownload%2F%40babel%2Fplugin-proposal-async-generator-functions-7.13.15.tgz#80e549df273a3b3050431b148c892491df1bcc5b"
integrity sha1-gOVJ3yc6OzBQQxsUjIkkkd8bzFs=
"@babel/plugin-proposal-async-generator-functions@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-async-generator-functions/download/@babel/plugin-proposal-async-generator-functions-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-async-generator-functions%2Fdownload%2F%40babel%2Fplugin-proposal-async-generator-functions-7.14.2.tgz#3a2085abbf5d5f962d480dbc81347385ed62eb1e"
integrity sha1-OiCFq79dX5YtSA28gTRzhe1i6x4=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/helper-remap-async-to-generator" "^7.13.0"
@ -348,69 +388,77 @@
"@babel/helper-create-class-features-plugin" "^7.13.0"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-proposal-dynamic-import@^7.13.8":
version "7.13.8"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-dynamic-import/download/@babel/plugin-proposal-dynamic-import-7.13.8.tgz?cache=0&sync_timestamp=1614382919309&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-dynamic-import%2Fdownload%2F%40babel%2Fplugin-proposal-dynamic-import-7.13.8.tgz#876a1f6966e1dec332e8c9451afda3bebcdf2e1d"
integrity sha1-h2ofaWbh3sMy6MlFGv2jvrzfLh0=
"@babel/plugin-proposal-class-static-block@^7.13.11":
version "7.13.11"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-class-static-block/download/@babel/plugin-proposal-class-static-block-7.13.11.tgz#6fcbba4a962702c17e5371a0c7b39afde186d703"
integrity sha1-b8u6SpYnAsF+U3Ggx7Oa/eGG1wM=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-class-static-block" "^7.12.13"
"@babel/plugin-proposal-dynamic-import@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-dynamic-import/download/@babel/plugin-proposal-dynamic-import-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-dynamic-import%2Fdownload%2F%40babel%2Fplugin-proposal-dynamic-import-7.14.2.tgz#01ebabd7c381cff231fa43e302939a9de5be9d9f"
integrity sha1-Aeur18OBz/Ix+kPjApOaneW+nZ8=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-dynamic-import" "^7.8.3"
"@babel/plugin-proposal-export-namespace-from@^7.12.13":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-export-namespace-from/download/@babel/plugin-proposal-export-namespace-from-7.12.13.tgz?cache=0&sync_timestamp=1612314774011&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-export-namespace-from%2Fdownload%2F%40babel%2Fplugin-proposal-export-namespace-from-7.12.13.tgz#393be47a4acd03fa2af6e3cde9b06e33de1b446d"
integrity sha1-OTvkekrNA/oq9uPN6bBuM94bRG0=
"@babel/plugin-proposal-export-namespace-from@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-export-namespace-from/download/@babel/plugin-proposal-export-namespace-from-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-export-namespace-from%2Fdownload%2F%40babel%2Fplugin-proposal-export-namespace-from-7.14.2.tgz#62542f94aa9ce8f6dba79eec698af22112253791"
integrity sha1-YlQvlKqc6Pbbp57saYryIRIlN5E=
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
"@babel/plugin-proposal-json-strings@^7.13.8":
version "7.13.8"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.13.8.tgz?cache=0&sync_timestamp=1614382894206&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-json-strings%2Fdownload%2F%40babel%2Fplugin-proposal-json-strings-7.13.8.tgz#bf1fb362547075afda3634ed31571c5901afef7b"
integrity sha1-vx+zYlRwda/aNjTtMVccWQGv73s=
"@babel/plugin-proposal-json-strings@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-json-strings/download/@babel/plugin-proposal-json-strings-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-json-strings%2Fdownload%2F%40babel%2Fplugin-proposal-json-strings-7.14.2.tgz#830b4e2426a782e8b2878fbfe2cba85b70cbf98c"
integrity sha1-gwtOJCanguiyh4+/4suoW3DL+Yw=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-json-strings" "^7.8.3"
"@babel/plugin-proposal-logical-assignment-operators@^7.13.8":
version "7.13.8"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-logical-assignment-operators/download/@babel/plugin-proposal-logical-assignment-operators-7.13.8.tgz?cache=0&sync_timestamp=1614383099367&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-logical-assignment-operators%2Fdownload%2F%40babel%2Fplugin-proposal-logical-assignment-operators-7.13.8.tgz#93fa78d63857c40ce3c8c3315220fd00bfbb4e1a"
integrity sha1-k/p41jhXxAzjyMMxUiD9AL+7Tho=
"@babel/plugin-proposal-logical-assignment-operators@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-logical-assignment-operators/download/@babel/plugin-proposal-logical-assignment-operators-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-logical-assignment-operators%2Fdownload%2F%40babel%2Fplugin-proposal-logical-assignment-operators-7.14.2.tgz#222348c080a1678e0e74ea63fe76f275882d1fd7"
integrity sha1-IiNIwIChZ44OdOpj/nbydYgtH9c=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-logical-assignment-operators" "^7.10.4"
"@babel/plugin-proposal-nullish-coalescing-operator@^7.13.8":
version "7.13.8"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.13.8.tgz?cache=0&sync_timestamp=1614382839100&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator%2Fdownload%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator-7.13.8.tgz#3730a31dafd3c10d8ccd10648ed80a2ac5472ef3"
integrity sha1-NzCjHa/TwQ2MzRBkjtgKKsVHLvM=
"@babel/plugin-proposal-nullish-coalescing-operator@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-nullish-coalescing-operator/download/@babel/plugin-proposal-nullish-coalescing-operator-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator%2Fdownload%2F%40babel%2Fplugin-proposal-nullish-coalescing-operator-7.14.2.tgz#425b11dc62fc26939a2ab42cbba680bdf5734546"
integrity sha1-QlsR3GL8JpOaKrQsu6aAvfVzRUY=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-nullish-coalescing-operator" "^7.8.3"
"@babel/plugin-proposal-numeric-separator@^7.12.13":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.12.13.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-numeric-separator%2Fdownload%2F%40babel%2Fplugin-proposal-numeric-separator-7.12.13.tgz#bd9da3188e787b5120b4f9d465a8261ce67ed1db"
integrity sha1-vZ2jGI54e1EgtPnUZagmHOZ+0ds=
"@babel/plugin-proposal-numeric-separator@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-numeric-separator/download/@babel/plugin-proposal-numeric-separator-7.14.2.tgz?cache=0&sync_timestamp=1620839926359&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-numeric-separator%2Fdownload%2F%40babel%2Fplugin-proposal-numeric-separator-7.14.2.tgz#82b4cc06571143faf50626104b335dd71baa4f9e"
integrity sha1-grTMBlcRQ/r1BiYQSzNd1xuqT54=
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-numeric-separator" "^7.10.4"
"@babel/plugin-proposal-object-rest-spread@^7.13.8":
version "7.13.8"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.13.8.tgz?cache=0&sync_timestamp=1614382897959&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-object-rest-spread%2Fdownload%2F%40babel%2Fplugin-proposal-object-rest-spread-7.13.8.tgz#5d210a4d727d6ce3b18f9de82cc99a3964eed60a"
integrity sha1-XSEKTXJ9bOOxj53oLMmaOWTu1go=
"@babel/plugin-proposal-object-rest-spread@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-object-rest-spread/download/@babel/plugin-proposal-object-rest-spread-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-object-rest-spread%2Fdownload%2F%40babel%2Fplugin-proposal-object-rest-spread-7.14.2.tgz#e17d418f81cc103fedd4ce037e181c8056225abc"
integrity sha1-4X1Bj4HMED/t1M4DfhgcgFYiWrw=
dependencies:
"@babel/compat-data" "^7.13.8"
"@babel/helper-compilation-targets" "^7.13.8"
"@babel/compat-data" "^7.14.0"
"@babel/helper-compilation-targets" "^7.13.16"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-object-rest-spread" "^7.8.3"
"@babel/plugin-transform-parameters" "^7.13.0"
"@babel/plugin-transform-parameters" "^7.14.2"
"@babel/plugin-proposal-optional-catch-binding@^7.13.8":
version "7.13.8"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.13.8.tgz?cache=0&sync_timestamp=1614383097188&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-optional-catch-binding%2Fdownload%2F%40babel%2Fplugin-proposal-optional-catch-binding-7.13.8.tgz#3ad6bd5901506ea996fc31bdcf3ccfa2bed71107"
integrity sha1-Ota9WQFQbqmW/DG9zzzPor7XEQc=
"@babel/plugin-proposal-optional-catch-binding@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-optional-catch-binding/download/@babel/plugin-proposal-optional-catch-binding-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-optional-catch-binding%2Fdownload%2F%40babel%2Fplugin-proposal-optional-catch-binding-7.14.2.tgz#150d4e58e525b16a9a1431bd5326c4eed870d717"
integrity sha1-FQ1OWOUlsWqaFDG9UybE7thw1xc=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
@ -424,6 +472,15 @@
"@babel/helper-skip-transparent-expression-wrappers" "^7.12.1"
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
"@babel/plugin-proposal-optional-chaining@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-proposal-optional-chaining/download/@babel/plugin-proposal-optional-chaining-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-optional-chaining%2Fdownload%2F%40babel%2Fplugin-proposal-optional-chaining-7.14.2.tgz#df8171a8b9c43ebf4c1dabe6311b432d83e1b34e"
integrity sha1-34FxqLnEPr9MHavmMRtDLYPhs04=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/helper-skip-transparent-expression-wrappers" "^7.12.1"
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
"@babel/plugin-proposal-private-methods@^7.13.0":
version "7.13.0"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-private-methods/download/@babel/plugin-proposal-private-methods-7.13.0.tgz?cache=0&sync_timestamp=1614034842648&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-private-methods%2Fdownload%2F%40babel%2Fplugin-proposal-private-methods-7.13.0.tgz#04bd4c6d40f6e6bbfa2f57e2d8094bad900ef787"
@ -432,6 +489,16 @@
"@babel/helper-create-class-features-plugin" "^7.13.0"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-proposal-private-property-in-object@^7.14.0":
version "7.14.0"
resolved "https://registry.nlark.com/@babel/plugin-proposal-private-property-in-object/download/@babel/plugin-proposal-private-property-in-object-7.14.0.tgz?cache=0&sync_timestamp=1619727403108&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-proposal-private-property-in-object%2Fdownload%2F%40babel%2Fplugin-proposal-private-property-in-object-7.14.0.tgz#b1a1f2030586b9d3489cc26179d2eb5883277636"
integrity sha1-saHyAwWGudNInMJhedLrWIMndjY=
dependencies:
"@babel/helper-annotate-as-pure" "^7.12.13"
"@babel/helper-create-class-features-plugin" "^7.14.0"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-private-property-in-object" "^7.14.0"
"@babel/plugin-proposal-unicode-property-regex@^7.12.13", "@babel/plugin-proposal-unicode-property-regex@^7.4.4":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/plugin-proposal-unicode-property-regex/download/@babel/plugin-proposal-unicode-property-regex-7.12.13.tgz?cache=0&sync_timestamp=1612315369895&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-proposal-unicode-property-regex%2Fdownload%2F%40babel%2Fplugin-proposal-unicode-property-regex-7.12.13.tgz#bebde51339be829c17aaaaced18641deb62b39ba"
@ -454,6 +521,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/plugin-syntax-class-static-block@^7.12.13":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-class-static-block/download/@babel/plugin-syntax-class-static-block-7.12.13.tgz#8e3d674b0613e67975ceac2776c97b60cafc5c9c"
integrity sha1-jj1nSwYT5nl1zqwndsl7YMr8XJw=
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/plugin-syntax-dynamic-import@^7.8.3":
version "7.8.3"
resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-dynamic-import/download/@babel/plugin-syntax-dynamic-import-7.8.3.tgz?cache=0&sync_timestamp=1599827954750&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-syntax-dynamic-import%2Fdownload%2F%40babel%2Fplugin-syntax-dynamic-import-7.8.3.tgz#62bf98b2da3cd21d626154fc96ee5b3cb68eacb3"
@ -517,6 +591,13 @@
dependencies:
"@babel/helper-plugin-utils" "^7.8.0"
"@babel/plugin-syntax-private-property-in-object@^7.14.0":
version "7.14.0"
resolved "https://registry.nlark.com/@babel/plugin-syntax-private-property-in-object/download/@babel/plugin-syntax-private-property-in-object-7.14.0.tgz#762a4babec61176fec6c88480dec40372b140c0b"
integrity sha1-dipLq+xhF2/sbIhIDexANysUDAs=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-syntax-top-level-await@^7.12.13":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/plugin-syntax-top-level-await/download/@babel/plugin-syntax-top-level-await-7.12.13.tgz#c5f0fa6e249f5b739727f923540cf7a806130178"
@ -547,23 +628,23 @@
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/plugin-transform-block-scoping@^7.12.13":
version "7.12.13"
resolved "https://registry.npm.taobao.org/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.12.13.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-block-scoping%2Fdownload%2F%40babel%2Fplugin-transform-block-scoping-7.12.13.tgz#f36e55076d06f41dfd78557ea039c1b581642e61"
integrity sha1-825VB20G9B39eFV+oDnBtYFkLmE=
"@babel/plugin-transform-block-scoping@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-transform-block-scoping/download/@babel/plugin-transform-block-scoping-7.14.2.tgz?cache=0&sync_timestamp=1620840275890&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-block-scoping%2Fdownload%2F%40babel%2Fplugin-transform-block-scoping-7.14.2.tgz#761cb12ab5a88d640ad4af4aa81f820e6b5fdf5c"
integrity sha1-dhyxKrWojWQK1K9KqB+CDmtf31w=
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-transform-classes@^7.13.0":
version "7.13.0"
resolved "https://registry.npm.taobao.org/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.13.0.tgz?cache=0&sync_timestamp=1614034503988&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-classes%2Fdownload%2F%40babel%2Fplugin-transform-classes-7.13.0.tgz#0265155075c42918bf4d3a4053134176ad9b533b"
integrity sha1-AmUVUHXEKRi/TTpAUxNBdq2bUzs=
"@babel/plugin-transform-classes@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-transform-classes/download/@babel/plugin-transform-classes-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-classes%2Fdownload%2F%40babel%2Fplugin-transform-classes-7.14.2.tgz#3f1196c5709f064c252ad056207d87b7aeb2d03d"
integrity sha1-PxGWxXCfBkwlKtBWIH2Ht66y0D0=
dependencies:
"@babel/helper-annotate-as-pure" "^7.12.13"
"@babel/helper-function-name" "^7.12.13"
"@babel/helper-function-name" "^7.14.2"
"@babel/helper-optimise-call-expression" "^7.12.13"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/helper-replace-supers" "^7.13.0"
"@babel/helper-replace-supers" "^7.13.12"
"@babel/helper-split-export-declaration" "^7.12.13"
globals "^11.1.0"
@ -574,10 +655,10 @@
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-transform-destructuring@^7.13.0":
version "7.13.0"
resolved "https://registry.npm.taobao.org/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.13.0.tgz?cache=0&sync_timestamp=1614034500254&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-destructuring%2Fdownload%2F%40babel%2Fplugin-transform-destructuring-7.13.0.tgz#c5dce270014d4e1ebb1d806116694c12b7028963"
integrity sha1-xdzicAFNTh67HYBhFmlMErcCiWM=
"@babel/plugin-transform-destructuring@^7.13.17":
version "7.13.17"
resolved "https://registry.nlark.com/@babel/plugin-transform-destructuring/download/@babel/plugin-transform-destructuring-7.13.17.tgz?cache=0&sync_timestamp=1618960864725&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-destructuring%2Fdownload%2F%40babel%2Fplugin-transform-destructuring-7.13.17.tgz#678d96576638c19d5b36b332504d3fd6e06dea27"
integrity sha1-Z42WV2Y4wZ1bNrMyUE0/1uBt6ic=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
@ -633,23 +714,23 @@
dependencies:
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/plugin-transform-modules-amd@^7.13.0":
version "7.13.0"
resolved "https://registry.npm.taobao.org/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.13.0.tgz#19f511d60e3d8753cc5a6d4e775d3a5184866cc3"
integrity sha1-GfUR1g49h1PMWm1Od106UYSGbMM=
"@babel/plugin-transform-modules-amd@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-transform-modules-amd/download/@babel/plugin-transform-modules-amd-7.14.2.tgz?cache=0&sync_timestamp=1620839930209&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-modules-amd%2Fdownload%2F%40babel%2Fplugin-transform-modules-amd-7.14.2.tgz#6622806fe1a7c07a1388444222ef9535f2ca17b0"
integrity sha1-ZiKAb+GnwHoTiERCIu+VNfLKF7A=
dependencies:
"@babel/helper-module-transforms" "^7.13.0"
"@babel/helper-module-transforms" "^7.14.2"
"@babel/helper-plugin-utils" "^7.13.0"
babel-plugin-dynamic-import-node "^2.3.3"
"@babel/plugin-transform-modules-commonjs@^7.13.8":
version "7.13.8"
resolved "https://registry.npm.taobao.org/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.13.8.tgz?cache=0&sync_timestamp=1614382840057&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Fplugin-transform-modules-commonjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-commonjs-7.13.8.tgz#7b01ad7c2dcf2275b06fa1781e00d13d420b3e1b"
integrity sha1-ewGtfC3PInWwb6F4HgDRPUILPhs=
"@babel/plugin-transform-modules-commonjs@^7.14.0":
version "7.14.0"
resolved "https://registry.nlark.com/@babel/plugin-transform-modules-commonjs/download/@babel/plugin-transform-modules-commonjs-7.14.0.tgz?cache=0&sync_timestamp=1619727429752&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-modules-commonjs%2Fdownload%2F%40babel%2Fplugin-transform-modules-commonjs-7.14.0.tgz#52bc199cb581e0992edba0f0f80356467587f161"
integrity sha1-UrwZnLWB4Jku26Dw+ANWRnWH8WE=
dependencies:
"@babel/helper-module-transforms" "^7.13.0"
"@babel/helper-module-transforms" "^7.14.0"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/helper-simple-access" "^7.12.13"
"@babel/helper-simple-access" "^7.13.12"
babel-plugin-dynamic-import-node "^2.3.3"
"@babel/plugin-transform-modules-systemjs@^7.13.8":
@ -663,12 +744,12 @@
"@babel/helper-validator-identifier" "^7.12.11"
babel-plugin-dynamic-import-node "^2.3.3"
"@babel/plugin-transform-modules-umd@^7.13.0":
version "7.13.0"
resolved "https://registry.npm.taobao.org/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.13.0.tgz#8a3d96a97d199705b9fd021580082af81c06e70b"
integrity sha1-ij2WqX0ZlwW5/QIVgAgq+BwG5ws=
"@babel/plugin-transform-modules-umd@^7.14.0":
version "7.14.0"
resolved "https://registry.nlark.com/@babel/plugin-transform-modules-umd/download/@babel/plugin-transform-modules-umd-7.14.0.tgz#2f8179d1bbc9263665ce4a65f305526b2ea8ac34"
integrity sha1-L4F50bvJJjZlzkpl8wVSay6orDQ=
dependencies:
"@babel/helper-module-transforms" "^7.13.0"
"@babel/helper-module-transforms" "^7.14.0"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/plugin-transform-named-capturing-groups-regex@^7.12.13":
@ -693,10 +774,10 @@
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/helper-replace-supers" "^7.12.13"
"@babel/plugin-transform-parameters@^7.13.0":
version "7.13.0"
resolved "https://registry.npm.taobao.org/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.13.0.tgz#8fa7603e3097f9c0b7ca1a4821bc2fb52e9e5007"
integrity sha1-j6dgPjCX+cC3yhpIIbwvtS6eUAc=
"@babel/plugin-transform-parameters@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/plugin-transform-parameters/download/@babel/plugin-transform-parameters-7.14.2.tgz?cache=0&sync_timestamp=1620840276681&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fplugin-transform-parameters%2Fdownload%2F%40babel%2Fplugin-transform-parameters-7.14.2.tgz#e4290f72e0e9e831000d066427c4667098decc31"
integrity sha1-5CkPcuDp6DEADQZkJ8RmcJjezDE=
dependencies:
"@babel/helper-plugin-utils" "^7.13.0"
@ -772,31 +853,34 @@
"@babel/helper-create-regexp-features-plugin" "^7.12.13"
"@babel/helper-plugin-utils" "^7.12.13"
"@babel/preset-env@^7.13.15":
version "7.13.15"
resolved "https://registry.npm.taobao.org/@babel/preset-env/download/@babel/preset-env-7.13.15.tgz#c8a6eb584f96ecba183d3d414a83553a599f478f"
integrity sha1-yKbrWE+W7LoYPT1BSoNVOlmfR48=
"@babel/preset-env@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/preset-env/download/@babel/preset-env-7.14.2.tgz?cache=0&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Fpreset-env%2Fdownload%2F%40babel%2Fpreset-env-7.14.2.tgz#e80612965da73579c84ad2f963c2359c71524ed5"
integrity sha1-6AYSll2nNXnIStL5Y8I1nHFSTtU=
dependencies:
"@babel/compat-data" "^7.13.15"
"@babel/helper-compilation-targets" "^7.13.13"
"@babel/compat-data" "^7.14.0"
"@babel/helper-compilation-targets" "^7.13.16"
"@babel/helper-plugin-utils" "^7.13.0"
"@babel/helper-validator-option" "^7.12.17"
"@babel/plugin-bugfix-v8-spread-parameters-in-optional-chaining" "^7.13.12"
"@babel/plugin-proposal-async-generator-functions" "^7.13.15"
"@babel/plugin-proposal-async-generator-functions" "^7.14.2"
"@babel/plugin-proposal-class-properties" "^7.13.0"
"@babel/plugin-proposal-dynamic-import" "^7.13.8"
"@babel/plugin-proposal-export-namespace-from" "^7.12.13"
"@babel/plugin-proposal-json-strings" "^7.13.8"
"@babel/plugin-proposal-logical-assignment-operators" "^7.13.8"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.13.8"
"@babel/plugin-proposal-numeric-separator" "^7.12.13"
"@babel/plugin-proposal-object-rest-spread" "^7.13.8"
"@babel/plugin-proposal-optional-catch-binding" "^7.13.8"
"@babel/plugin-proposal-optional-chaining" "^7.13.12"
"@babel/plugin-proposal-class-static-block" "^7.13.11"
"@babel/plugin-proposal-dynamic-import" "^7.14.2"
"@babel/plugin-proposal-export-namespace-from" "^7.14.2"
"@babel/plugin-proposal-json-strings" "^7.14.2"
"@babel/plugin-proposal-logical-assignment-operators" "^7.14.2"
"@babel/plugin-proposal-nullish-coalescing-operator" "^7.14.2"
"@babel/plugin-proposal-numeric-separator" "^7.14.2"
"@babel/plugin-proposal-object-rest-spread" "^7.14.2"
"@babel/plugin-proposal-optional-catch-binding" "^7.14.2"
"@babel/plugin-proposal-optional-chaining" "^7.14.2"
"@babel/plugin-proposal-private-methods" "^7.13.0"
"@babel/plugin-proposal-private-property-in-object" "^7.14.0"
"@babel/plugin-proposal-unicode-property-regex" "^7.12.13"
"@babel/plugin-syntax-async-generators" "^7.8.4"
"@babel/plugin-syntax-class-properties" "^7.12.13"
"@babel/plugin-syntax-class-static-block" "^7.12.13"
"@babel/plugin-syntax-dynamic-import" "^7.8.3"
"@babel/plugin-syntax-export-namespace-from" "^7.8.3"
"@babel/plugin-syntax-json-strings" "^7.8.3"
@ -806,14 +890,15 @@
"@babel/plugin-syntax-object-rest-spread" "^7.8.3"
"@babel/plugin-syntax-optional-catch-binding" "^7.8.3"
"@babel/plugin-syntax-optional-chaining" "^7.8.3"
"@babel/plugin-syntax-private-property-in-object" "^7.14.0"
"@babel/plugin-syntax-top-level-await" "^7.12.13"
"@babel/plugin-transform-arrow-functions" "^7.13.0"
"@babel/plugin-transform-async-to-generator" "^7.13.0"
"@babel/plugin-transform-block-scoped-functions" "^7.12.13"
"@babel/plugin-transform-block-scoping" "^7.12.13"
"@babel/plugin-transform-classes" "^7.13.0"
"@babel/plugin-transform-block-scoping" "^7.14.2"
"@babel/plugin-transform-classes" "^7.14.2"
"@babel/plugin-transform-computed-properties" "^7.13.0"
"@babel/plugin-transform-destructuring" "^7.13.0"
"@babel/plugin-transform-destructuring" "^7.13.17"
"@babel/plugin-transform-dotall-regex" "^7.12.13"
"@babel/plugin-transform-duplicate-keys" "^7.12.13"
"@babel/plugin-transform-exponentiation-operator" "^7.12.13"
@ -821,14 +906,14 @@
"@babel/plugin-transform-function-name" "^7.12.13"
"@babel/plugin-transform-literals" "^7.12.13"
"@babel/plugin-transform-member-expression-literals" "^7.12.13"
"@babel/plugin-transform-modules-amd" "^7.13.0"
"@babel/plugin-transform-modules-commonjs" "^7.13.8"
"@babel/plugin-transform-modules-amd" "^7.14.2"
"@babel/plugin-transform-modules-commonjs" "^7.14.0"
"@babel/plugin-transform-modules-systemjs" "^7.13.8"
"@babel/plugin-transform-modules-umd" "^7.13.0"
"@babel/plugin-transform-modules-umd" "^7.14.0"
"@babel/plugin-transform-named-capturing-groups-regex" "^7.12.13"
"@babel/plugin-transform-new-target" "^7.12.13"
"@babel/plugin-transform-object-super" "^7.12.13"
"@babel/plugin-transform-parameters" "^7.13.0"
"@babel/plugin-transform-parameters" "^7.14.2"
"@babel/plugin-transform-property-literals" "^7.12.13"
"@babel/plugin-transform-regenerator" "^7.13.15"
"@babel/plugin-transform-reserved-words" "^7.12.13"
@ -840,7 +925,7 @@
"@babel/plugin-transform-unicode-escapes" "^7.12.13"
"@babel/plugin-transform-unicode-regex" "^7.12.13"
"@babel/preset-modules" "^0.1.4"
"@babel/types" "^7.13.14"
"@babel/types" "^7.14.2"
babel-plugin-polyfill-corejs2 "^0.2.0"
babel-plugin-polyfill-corejs3 "^0.2.0"
babel-plugin-polyfill-regenerator "^0.2.0"
@ -889,17 +974,17 @@
globals "^11.1.0"
lodash "^4.17.19"
"@babel/traverse@^7.13.13", "@babel/traverse@^7.13.15":
version "7.13.15"
resolved "https://registry.npm.taobao.org/@babel/traverse/download/@babel/traverse-7.13.15.tgz?cache=0&sync_timestamp=1617897649375&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftraverse%2Fdownload%2F%40babel%2Ftraverse-7.13.15.tgz#c38bf7679334ddd4028e8e1f7b3aa5019f0dada7"
integrity sha1-w4v3Z5M03dQCjo4fezqlAZ8Nrac=
"@babel/traverse@^7.14.0", "@babel/traverse@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/traverse/download/@babel/traverse-7.14.2.tgz?cache=0&sync_timestamp=1620839929860&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Ftraverse%2Fdownload%2F%40babel%2Ftraverse-7.14.2.tgz#9201a8d912723a831c2679c7ebbf2fe1416d765b"
integrity sha1-kgGo2RJyOoMcJnnH678v4UFtdls=
dependencies:
"@babel/code-frame" "^7.12.13"
"@babel/generator" "^7.13.9"
"@babel/helper-function-name" "^7.12.13"
"@babel/generator" "^7.14.2"
"@babel/helper-function-name" "^7.14.2"
"@babel/helper-split-export-declaration" "^7.12.13"
"@babel/parser" "^7.13.15"
"@babel/types" "^7.13.14"
"@babel/parser" "^7.14.2"
"@babel/types" "^7.14.2"
debug "^4.1.0"
globals "^11.1.0"
@ -912,7 +997,7 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
"@babel/types@^7.13.12", "@babel/types@^7.13.14":
"@babel/types@^7.13.12":
version "7.13.14"
resolved "https://registry.npm.taobao.org/@babel/types/download/@babel/types-7.13.14.tgz?cache=0&sync_timestamp=1617027467959&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.13.14.tgz#c35a4abb15c7cd45a2746d78ab328e362cbace0d"
integrity sha1-w1pKuxXHzUWidG14qzKONiy6zg0=
@ -921,6 +1006,14 @@
lodash "^4.17.19"
to-fast-properties "^2.0.0"
"@babel/types@^7.14.0", "@babel/types@^7.14.2":
version "7.14.2"
resolved "https://registry.nlark.com/@babel/types/download/@babel/types-7.14.2.tgz?cache=0&sync_timestamp=1620840277996&other_urls=https%3A%2F%2Fregistry.nlark.com%2F%40babel%2Ftypes%2Fdownload%2F%40babel%2Ftypes-7.14.2.tgz#4208ae003107ef8a057ea8333e56eb64d2f6a2c3"
integrity sha1-QgiuADEH74oFfqgzPlbrZNL2osM=
dependencies:
"@babel/helper-validator-identifier" "^7.14.0"
to-fast-properties "^2.0.0"
"@commitlint/execute-rule@^12.0.1":
version "12.0.1"
resolved "https://registry.npm.taobao.org/@commitlint/execute-rule/download/@commitlint/execute-rule-12.0.1.tgz?cache=0&sync_timestamp=1614412738373&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2F%40commitlint%2Fexecute-rule%2Fdownload%2F%40commitlint%2Fexecute-rule-12.0.1.tgz#5bb2eba929270cafb2bd8191799d8b451de7fb7e"
@ -977,11 +1070,6 @@
"@nodelib/fs.scandir" "2.1.4"
fastq "^1.6.0"
"@npmcli/ci-detect@^1.0.0":
version "1.3.0"
resolved "https://registry.npm.taobao.org/@npmcli/ci-detect/download/@npmcli/ci-detect-1.3.0.tgz#6c1d2c625fb6ef1b9dea85ad0a5afcbef85ef22a"
integrity sha1-bB0sYl+27xud6oWtClr8vvhe8io=
"@npmcli/git@^2.0.1":
version "2.0.6"
resolved "https://registry.npm.taobao.org/@npmcli/git/download/@npmcli/git-2.0.6.tgz#47b97e96b2eede3f38379262fa3bdfa6eae57bf2"
@ -1739,6 +1827,14 @@ chalk@^4.0.0, chalk@^4.1.0:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chalk@^4.1.1:
version "4.1.1"
resolved "https://registry.nlark.com/chalk/download/chalk-4.1.1.tgz?cache=0&sync_timestamp=1618995384030&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fchalk%2Fdownload%2Fchalk-4.1.1.tgz#c80b3fab28bf6371e6863325eee67e618b77e6ad"
integrity sha1-yAs/qyi/Y3HmhjMl7uZ+YYt35q0=
dependencies:
ansi-styles "^4.1.0"
supports-color "^7.1.0"
chardet@^0.7.0:
version "0.7.0"
resolved "https://registry.npm.taobao.org/chardet/download/chardet-0.7.0.tgz#90094849f0937f2eedc2425d0d28a9e5f0cbad9e"
@ -1986,7 +2082,7 @@ commander@~2.19.0:
resolved "https://registry.npm.taobao.org/commander/download/commander-2.19.0.tgz?cache=0&sync_timestamp=1613374024216&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fcommander%2Fdownload%2Fcommander-2.19.0.tgz#f6198aa84e5b83c46054b94ddedbfed5ee9ff12a"
integrity sha1-9hmKqE5bg8RgVLlN3tv+1e6f8So=
commitizen@^4.0.3, commitizen@^4.2.3:
commitizen@^4.0.3:
version "4.2.3"
resolved "https://registry.npm.taobao.org/commitizen/download/commitizen-4.2.3.tgz#088d0ef72500240d331b11e02e288223667c1475"
integrity sha1-CI0O9yUAJA0zGxHgLiiCI2Z8FHU=
@ -2006,6 +2102,26 @@ commitizen@^4.0.3, commitizen@^4.2.3:
strip-bom "4.0.0"
strip-json-comments "3.0.1"
commitizen@^4.2.4:
version "4.2.4"
resolved "https://registry.nlark.com/commitizen/download/commitizen-4.2.4.tgz#a3e5b36bd7575f6bf6e7aa19dbbf06b0d8f37165"
integrity sha1-o+Wza9dXX2v256oZ278GsNjzcWU=
dependencies:
cachedir "2.2.0"
cz-conventional-changelog "3.2.0"
dedent "0.7.0"
detect-indent "6.0.0"
find-node-modules "^2.1.2"
find-root "1.1.0"
fs-extra "8.1.0"
glob "7.1.4"
inquirer "6.5.2"
is-utf8 "^0.2.1"
lodash "^4.17.20"
minimist "1.2.5"
strip-bom "4.0.0"
strip-json-comments "3.0.1"
compare-func@^2.0.0:
version "2.0.0"
resolved "https://registry.npm.taobao.org/compare-func/download/compare-func-2.0.0.tgz#fb65e75edbddfd2e568554e8b5b05fff7a51fcb3"
@ -2928,6 +3044,14 @@ find-node-modules@2.0.0:
findup-sync "^3.0.0"
merge "^1.2.1"
find-node-modules@^2.1.2:
version "2.1.2"
resolved "https://registry.npm.taobao.org/find-node-modules/download/find-node-modules-2.1.2.tgz#57565a3455baf671b835bc6b2134a9b938b9c53c"
integrity sha1-V1ZaNFW69nG4NbxrITSpuTi5xTw=
dependencies:
findup-sync "^4.0.0"
merge "^2.1.0"
find-root@1.1.0:
version "1.1.0"
resolved "https://registry.npm.taobao.org/find-root/download/find-root-1.1.0.tgz#abcfc8ba76f708c42a97b3d685b7e9450bfb9ce4"
@ -2991,6 +3115,16 @@ findup-sync@^3.0.0:
micromatch "^3.0.4"
resolve-dir "^1.0.1"
findup-sync@^4.0.0:
version "4.0.0"
resolved "https://registry.npm.taobao.org/findup-sync/download/findup-sync-4.0.0.tgz#956c9cdde804052b881b428512905c4a5f2cdef0"
integrity sha1-lWyc3egEBSuIG0KFEpBcSl8s3vA=
dependencies:
detect-file "^1.0.0"
is-glob "^4.0.0"
micromatch "^4.0.2"
resolve-dir "^1.0.1"
fined@^1.0.1:
version "1.2.0"
resolved "https://registry.npm.taobao.org/fined/download/fined-1.2.0.tgz#d00beccf1aa2b475d16d423b0238b713a2c4a37b"
@ -3734,10 +3868,10 @@ hexo-server@^2.0.0:
open "^7.0.0"
serve-static "^1.14.1"
hexo-theme-fluid@^1.8.9:
version "1.8.9"
resolved "https://registry.npm.taobao.org/hexo-theme-fluid/download/hexo-theme-fluid-1.8.9.tgz#7e5d008f5301aff4c660a29b0589bb725aea81ba"
integrity sha1-fl0Aj1MBr/TGYKKbBYm7clrqgbo=
hexo-theme-fluid@^1.8.10:
version "1.8.10"
resolved "https://registry.nlark.com/hexo-theme-fluid/download/hexo-theme-fluid-1.8.10.tgz#1d9dec5d1400c4b201f56142d6d2843352883a08"
integrity sha1-HZ3sXRQAxLIB9WFC1tKEM1KIOgg=
hexo-util@^2.0.0, hexo-util@^2.1.0, hexo-util@^2.4.0:
version "2.4.0"
@ -4730,10 +4864,10 @@ matchdep@^2.0.0:
resolve "^1.4.0"
stack-trace "0.0.10"
mem@^8.1.0:
version "8.1.0"
resolved "https://registry.npm.taobao.org/mem/download/mem-8.1.0.tgz?cache=0&sync_timestamp=1616075310850&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmem%2Fdownload%2Fmem-8.1.0.tgz#445e47827fb757a4e5f35b0a6a62743cbfdc0a0d"
integrity sha1-RF5Hgn+3V6Tl81sKamJ0PL/cCg0=
mem@^8.1.1:
version "8.1.1"
resolved "https://registry.nlark.com/mem/download/mem-8.1.1.tgz?cache=0&sync_timestamp=1618933765288&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fmem%2Fdownload%2Fmem-8.1.1.tgz#cf118b357c65ab7b7e0817bdf00c8062297c0122"
integrity sha1-zxGLNXxlq3t+CBe98AyAYil8ASI=
dependencies:
map-age-cleaner "^0.1.3"
mimic-fn "^3.1.0"
@ -4781,6 +4915,11 @@ merge@^1.2.1:
resolved "https://registry.npm.taobao.org/merge/download/merge-1.2.1.tgz?cache=0&sync_timestamp=1614028201184&other_urls=https%3A%2F%2Fregistry.npm.taobao.org%2Fmerge%2Fdownload%2Fmerge-1.2.1.tgz#38bebf80c3220a8a487b6fcfb3941bb11720c145"
integrity sha1-OL6/gMMiCopIe2/Ps5QbsRcgwUU=
merge@^2.1.0:
version "2.1.1"
resolved "https://registry.npm.taobao.org/merge/download/merge-2.1.1.tgz#59ef4bf7e0b3e879186436e8481c06a6c162ca98"
integrity sha1-We9L9+Cz6HkYZDboSBwGpsFiypg=
micromatch@^3.0.4, micromatch@^3.1.10, micromatch@^3.1.4:
version "3.1.10"
resolved "https://registry.npm.taobao.org/micromatch/download/micromatch-3.1.10.tgz#70859bc95c9840952f359a068a3fc49f9ecfac23"
@ -5149,12 +5288,12 @@ npm-bundled@^1.1.1:
dependencies:
npm-normalize-package-bin "^1.0.1"
npm-check-updates@^11.4.1:
version "11.4.1"
resolved "https://registry.npm.taobao.org/npm-check-updates/download/npm-check-updates-11.4.1.tgz#6079a1a9c84b3d611fabb02c8332a698df9ce249"
integrity sha1-YHmhqchLPWEfq7AsgzKmmN+c4kk=
npm-check-updates@^11.5.11:
version "11.5.11"
resolved "https://registry.nlark.com/npm-check-updates/download/npm-check-updates-11.5.11.tgz#02f5402f0f79a1b5b8027bf74869dddda6439bc5"
integrity sha1-AvVALw95obW4Anv3SGnd3aZDm8U=
dependencies:
chalk "^4.1.0"
chalk "^4.1.1"
cint "^8.2.1"
cli-table "^0.3.6"
commander "^6.2.1"
@ -5167,10 +5306,10 @@ npm-check-updates@^11.4.1:
jsonlines "^0.1.1"
libnpmconfig "^1.2.1"
lodash "^4.17.21"
mem "^8.1.0"
mem "^8.1.1"
minimatch "^3.0.4"
p-map "^4.0.0"
pacote "^11.3.1"
pacote "^11.3.3"
parse-github-url "^1.0.2"
progress "^2.0.3"
prompts "^2.4.1"
@ -5222,12 +5361,11 @@ npm-pick-manifest@^6.0.0:
npm-package-arg "^8.0.0"
semver "^7.0.0"
npm-registry-fetch@^9.0.0:
version "9.0.0"
resolved "https://registry.npm.taobao.org/npm-registry-fetch/download/npm-registry-fetch-9.0.0.tgz#86f3feb4ce00313bc0b8f1f8f69daae6face1661"
integrity sha1-hvP+tM4AMTvAuPH49p2q5vrOFmE=
npm-registry-fetch@^10.0.0:
version "10.1.1"
resolved "https://registry.nlark.com/npm-registry-fetch/download/npm-registry-fetch-10.1.1.tgz#97bc7a0fca5e8f76cc5162185b8de8caa8bea639"
integrity sha1-l7x6D8pej3bMUWIYW43oyqi+pjk=
dependencies:
"@npmcli/ci-detect" "^1.0.0"
lru-cache "^6.0.0"
make-fetch-happen "^8.0.9"
minipass "^3.1.3"
@ -5478,10 +5616,10 @@ package-json@^6.3.0:
registry-url "^5.0.0"
semver "^6.2.0"
pacote@^11.3.1:
version "11.3.1"
resolved "https://registry.npm.taobao.org/pacote/download/pacote-11.3.1.tgz#6ce95dd230db475cbd8789fd1f986bec51b4bf7c"
integrity sha1-bOld0jDbR1y9h4n9H5hr7FG0v3w=
pacote@^11.3.3:
version "11.3.3"
resolved "https://registry.nlark.com/pacote/download/pacote-11.3.3.tgz?cache=0&sync_timestamp=1619198232988&other_urls=https%3A%2F%2Fregistry.nlark.com%2Fpacote%2Fdownload%2Fpacote-11.3.3.tgz#d7d6091464f77c09691699df2ded13ab906b3e68"
integrity sha1-19YJFGT3fAlpFpnfLe0Tq5BrPmg=
dependencies:
"@npmcli/git" "^2.0.1"
"@npmcli/installed-package-contents" "^1.0.6"
@ -5496,7 +5634,7 @@ pacote@^11.3.1:
npm-package-arg "^8.0.1"
npm-packlist "^2.1.4"
npm-pick-manifest "^6.0.0"
npm-registry-fetch "^9.0.0"
npm-registry-fetch "^10.0.0"
promise-retry "^2.0.1"
read-package-json-fast "^2.0.1"
rimraf "^3.0.2"