cosyer's Blog

Blog


  • 首页

  • 友链

  • 留言板

  • 归档

  • 关于

  • 搜索
12月
10
更新于
12月10
2020
知识

实现一个网页终端

发表于 2020-12-08 | 热度 ℃
| 字数统计: 977 (字) | 阅读时长: 4 (分钟)

先简单说一下原理吧,在网页上和服务器上建立一个ws连接,然后网页获取用户输入传给服务端,服务端解析用户输入,在服务端shell执行命令并将执行输出通过ws传给网页渲染到页面上。

以上原理说起来简单,但是完全自己实现是不太现实的。下面我把实现用到的库和插件以及使用方式简单说一下。


阅读全文 »
12月
02
更新于
12月02
2020
JS

高逼格的JS代码

发表于 2018-10-30 | 热度 ℃
| 字数统计: 1,551 (字) | 阅读时长: 8 (分钟)

黑科技JS代码整理 是不是很void 666

一行代码实现评级

1
"★★★★★☆☆☆☆☆".slice(5 - rate, 10 - rate);定义一个变量rate是1到5的值

SB、NB、Hello World

1
2
3
4
5
(!(~+[])+{})[--[~+""][+[]]*[~+[]] + ~~!+[]]+({}+[])[[~!+[]]*~+[]]

([][[]]+[])[+!![]]+([]+{})[!+[]+!![]]

([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[+[]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[])+(!+[]+!![]+!![]+!![]+!![]+!![]+!![]+[]))+([]+{})[+!![]]+(!![]+[])[+!![]]+(![]+[])[!+[]+!![]]+([][[]]+[])[!+[]+!![]]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[+[]]+([][[]]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()([][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(![]+[])[!+[]+!![]+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+([]+[][(![]+[])[!+[]+!![]+!![]]+([]+{})[+!![]]+(!![]+[])[+!![]]+(!![]+[])[+[]]][([]+{})[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]]+(![]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+[]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(!![]+[])[+[]]+([]+{})[+!![]]+(!![]+[])[+!![]]]((!![]+[])[+!![]]+([][[]]+[])[!+[]+!![]+!![]]+(!![]+[])[+[]]+([][[]]+[])[+[]]+(!![]+[])[+!![]]+([][[]]+[])[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]+!![]+!![]]+(![]+[])[!+[]+!![]]+([]+{})[+!![]]+([]+{})[!+[]+!![]+!![]+!![]+!![]]+(+{}+[])[+!![]]+(!![]+[])[+[]]+([][[]]+[])[!+[]+!![]+!![]+!![]+!![]]+([]+{})[+!![]]+([][[]]+[])[+!![]])())[!+[]+!![]+!![]]+([][[]]+[])[!+[]+!![]+!![]])()(([]+{})[+[]])[+[]]+(!+[]+!![]+[])+(+!![]+[]))

错误处理的正确方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
try {
something
} catch (e) {
window.location.href =
"http://stackoverflow.com/search?q=[js]+" +
e.message;
}
// 百度版
try {
something
} catch (e) {
window.location.href =
"https://www.baidu.com/s?wd=" +
e.message;
}

阅读全文 »
12月
02
更新于
12月02
2020
工具

elasticsearch、redis部署

发表于 2020-09-18 | 热度 ℃
| 字数统计: 885 (字) | 阅读时长: 5 (分钟)

skywalking

预安装JDK

Linux系统(Centos yum)下安装Java环境

elasticsearch

官网下载 https://www.elastic.co/cn/downloads/elasticsearch

解压

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
# 解压
tar -zxvf elasticsearch-6.1.0.tar.gz

# 配置 config/elasticsearch.yml
cluster.name: myskywalking
path.data: /opt/data/es/data
path.logs: /opt/data/es/logs
bootstrap.memory_lock: false
network.host: 193.160.59.45

# 单机运行
./bin/elasticsearch -V

# 后台运行
./bin/elasticsearch -d

# 访问
http://127.0.0.1:9200

常见问题

  1. 需要非root用户启动

  2. 【报错】max virtual memory areas vm.max_map_count [65530] is too low, increase to at least [262144] 内存过小 解决:

    1
    2
    3
    4
    # 1.sudo vi /etc/sysctl.conf 文件最后添加一行
    # vm.max_map_count=262144
    # 2.加载设置好的系统参数
    # sudo sysctl -p

阅读全文 »
12月
02
更新于
12月02
2020
JS

Nest概述

发表于 2020-11-30 | 热度 ℃
| 字数统计: 5,154 (字) | 阅读时长: 24 (分钟)

先决条件

一分钟安装nodejs,版本(>=10.13.0)

创建项目

1
2
3
npm i -g @nestjs/cli

nest new project

初始项目结构

1
2
3
4
5
# 将创建 project 目录, 安装node模块和一些其他样板文件,并将创建一个 src 目录,目录中包含几个核心文件。
src
├── app.controller.ts # 带有单个路由的基本控制器示例。
├── app.module.ts # 应用程序的根模块
└── main.ts # 应用程序入口文件。它使用 NestFactory 用来创建 Nest 应用实例。
1
2
3
4
5
6
7
8
9
// main.ts
import { NestFactory } from '@nestjs/core';
import { AppModule } from './app.module';

async function bootstrap() {
const app = await NestFactory.create(AppModule);
await app.listen(3000);
}
bootstrap();

平台

Nest 旨在成为一个与平台无关的框架。 通过平台,可以创建可重用的逻辑部件,开发人员可以利用这些部件来跨越多种不同类型的应用程序。 从技术 上讲,Nest 可以在创建适配器后使用任何 Node HTTP 框架。 有两个支持开箱即用的 HTTP 平台:express 和 fastify。 您可以选择最适合您 需求的产品。

平台 描述
express Express 是一个众所周知的 node.js 简约 Web 框架。 这是一个经过实战考验,适用于生产的库,拥有大量社区资源。 默认情况下使

用 @nestjs/platform-express 包。 许多用户都可以使用 Express ,并且无需采取任何操作即可启用它。| |fastify|Fastify 是一个高性能,低开销的框架,专注于提供最高的效率和速度。 在这里阅读如何使用它。|

无论使用哪种平台,它都会暴露自己的 API。 它们分别是 NestExpressApplication 和 NestFastifyApplication。

将类型传递给 NestFactory.create() 函数时,如下例所示,app 对象将具有专用于该特定平台的函数。 但是,请注意,除非您确实要访问底层平 台API,否则无需指定类型。

1
const app = await NestFactory.create<NestExpressApplication>(AppModule);

运行应用程序

1
2
3
npm run start

// http://localhost:3000 Hello World

阅读全文 »
11月
24
更新于
11月24
2020
JS

前端性能优化

发表于 2018-08-30 | 热度 ℃
| 字数统计: 1,271 (字) | 阅读时长: 5 (分钟)

前端性能优化主要是为了提高页面的加载速度,优化用户的访问体验。

阅读全文 »
11月
23
更新于
11月23
2020
React

react源码解析系列三(React Fiber)

发表于 2020-11-23 | 热度 ℃
| 字数统计: 1,206 (字) | 阅读时长: 7 (分钟)

Fiber

每一个ReactElement对应一个Fiber对象

记录节点的各种状态

串联整个应用形成的结构

例如:FiberRoot的current指向RootFiber 的 child —->App 的child —> div 的child—->input 的sibling

属性:

1
2
3
4
5
return // 指向父节点(每个节点只会有一个父节点)

child // 子节点

sibling // 兄弟节点

Update

用于记录组件状态的改变

存放于Fiber对象的UpdateQueue中:UpdateQue单项链表的结构

多个Update可以同时存在:例如一个事件里面存在三个setState,创建三个update放到UpdateQueue中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
// 创建或更新updatequeue
export function enqueueUpdate<State>(fiber: Fiber, update: Update<State>) {
// Update queues are created lazily.
const alternate = fiber.alternate;
let queue1;
let queue2;
if (alternate === null) {
// There's only one fiber.
queue1 = fiber.updateQueue;
queue2 = null;
if (queue1 === null) {
queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);
}
} else {
// There are two owners.
queue1 = fiber.updateQueue;
queue2 = alternate.updateQueue;
if (queue1 === null) {
if (queue2 === null) {
// Neither fiber has an update queue. Create new ones.
queue1 = fiber.updateQueue = createUpdateQueue(fiber.memoizedState);
queue2 = alternate.updateQueue = createUpdateQueue(
alternate.memoizedState,
);
} else {
// Only one fiber has an update queue. Clone to create a new one.
queue1 = fiber.updateQueue = cloneUpdateQueue(queue2);
}
} else {
if (queue2 === null) {
// Only one fiber has an update queue. Clone to create a new one.
queue2 = alternate.updateQueue = cloneUpdateQueue(queue1);
} else {
// Both owners have an update queue.
}
}
}
if (queue2 === null || queue1 === queue2) {
// There's only a single queue.
appendUpdateToQueue(queue1, update);
} else {
// There are two queues. We need to append the update to both queues,
// while accounting for the persistent structure of the list — we don't
// want the same update to be added multiple times.
if (queue1.lastUpdate === null || queue2.lastUpdate === null) {
// One of the queues is not empty. We must add the update to both queues.
appendUpdateToQueue(queue1, update);
appendUpdateToQueue(queue2, update);
} else {
// Both queues are non-empty. The last update is the same in both lists,
// because of structural sharing. So, only append to one of the lists.
appendUpdateToQueue(queue1, update);
// But we still need to update the `lastUpdate` pointer of queue2.
queue2.lastUpdate = update;
}
}

if (__DEV__) {
if (
fiber.tag === ClassComponent &&
(currentlyProcessingQueue === queue1 ||
(queue2 !== null && currentlyProcessingQueue === queue2)) &&
!didWarnUpdateInsideUpdate
) {
warningWithoutStack(
false,
'An update (setState, replaceState, or forceUpdate) was scheduled ' +
'from inside an update function. Update functions should be pure, ' +
'with zero side-effects. Consider using componentDidUpdate or a ' +
'callback.',
);
didWarnUpdateInsideUpdate = true;
}
}
}

expirationTime

详解见:https://react.jokcy.me/book/update/expiration-time.html

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
// ReactFiberReconciler.js中
export function updateContainer(
element: ReactNodeList,
container: OpaqueRoot,
parentComponent: ?React$Component<any, any>,
callback: ?Function,
): ExpirationTime {
const current = container.current; // Fiber对象
//!important
const currentTime = requestCurrentTime();
const expirationTime = computeExpirationForFiber(currentTime, current);

return updateContainerAtExpirationTime(
element,
container,
parentComponent,
expirationTime,
callback,
);
}

requestCurrentTime

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
// 目前粗略的理解目前为止到js加载完成的时间差
function requestCurrentTime() {
// 已经进入到渲染阶段了
if (isRendering) {
// We're already rendering. Return the most recently read time.
return currentSchedulerTime;
}
// Check if there's pending work.
findHighestPriorityRoot(); // 从调度队列找到权限最高的root
if (
nextFlushedExpirationTime === NoWork ||
nextFlushedExpirationTime === Never
) {
// If there's no pending work, or if the pending work is offscreen, we can
// read the current time without risk of tearing.
recomputeCurrentRendererTime(); // 如下
currentSchedulerTime = currentRendererTime;
return currentSchedulerTime;
}
// There's already pending work. We might be in the middle of a browser
// event. If we were to read the current time, it could cause multiple updates
// within the same event to receive different expiration times, leading to
// tearing. Return the last read time. During the next idle callback, the
// time will be updated.
return currentSchedulerTime;
}

recomputeCurrentRendererTime

1
2
3
4
5
function recomputeCurrentRendererTime() {
// 从js加载完成到现在为止的时间间隔
const currentTimeMs = now() - originalStartTimeMs; // originalStartTimeMs: 初始的now()
currentRendererTime = msToExpirationTime(currentTimeMs);
}

msToExpirationTime

1
2
3
4
5
const UNIT_SIZE = 10
export function msToExpirationTime(ms: number): ExpirationTime {
// Always add an offset so that we don't clash with the magic number for NoWork.
return ((ms / UNIT_SIZE) | 0) + MAGIC_NUMBER_OFFSET;
}

computeExpirationForFiber

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
function computeExpirationForFiber(currentTime: ExpirationTime, fiber: Fiber) {
let expirationTime;
if (expirationContext !== NoWork) {
// An explicit expiration context was set;
expirationTime = expirationContext;
} else if (isWorking) {
if (isCommitting) {
// Updates that occur during the commit phase should have sync priority
// by default.
expirationTime = Sync;
} else {
// Updates during the render phase should expire at the same time as
// the work that is being rendered.
expirationTime = nextRenderExpirationTime;
}
} else {
// No explicit expiration context was set, and we're not currently
// performing work. Calculate a new expiration time.
if (fiber.mode & ConcurrentMode) {
if (isBatchingInteractiveUpdates) {
// This is an interactive update
expirationTime = computeInteractiveExpiration(currentTime); // 如下
} else {
// This is an async update
expirationTime = computeAsyncExpiration(currentTime); // 如下
}
// If we're in the middle of rendering a tree, do not update at the same
// expiration time that is already rendering.
if (nextRoot !== null && expirationTime === nextRenderExpirationTime) {
expirationTime += 1;
}
} else {
// This is a sync update
expirationTime = Sync;
}
}
if (isBatchingInteractiveUpdates) {
// This is an interactive update. Keep track of the lowest pending
// interactive expiration time. This allows us to synchronously flush
// all interactive updates when needed.
if (expirationTime > lowestPriorityPendingInteractiveExpirationTime) {
lowestPriorityPendingInteractiveExpirationTime = expirationTime;
}
}
return expirationTime;
}

computeInteractiveExpiration

1
2
3
4
5
6
7
8
9
10
export const HIGH_PRIORITY_EXPIRATION = __DEV__ ? 500 : 150;
export const HIGH_PRIORITY_BATCH_SIZE = 100;

export function computeInteractiveExpiration(currentTime: ExpirationTime) {
return computeExpirationBucket(
currentTime,
HIGH_PRIORITY_EXPIRATION,
HIGH_PRIORITY_BATCH_SIZE,
);
}

computeAsyncExpiration

1
2
3
4
5
6
7
8
9
10
11
12
export const LOW_PRIORITY_EXPIRATION = 5000;
export const LOW_PRIORITY_BATCH_SIZE = 250;

export function computeAsyncExpiration(
currentTime: ExpirationTime,
): ExpirationTime {
return computeExpirationBucket(
currentTime,
LOW_PRIORITY_EXPIRATION,
LOW_PRIORITY_BATCH_SIZE,
);
}

computeExpirationBucket

1
2
3
4
5
6
7
8
9
10
11
12
13
function computeExpirationBucket(
currentTime,
expirationInMs,
bucketSizeMs,
): ExpirationTime {
return (
MAGIC_NUMBER_OFFSET +
ceiling(
currentTime - MAGIC_NUMBER_OFFSET + expirationInMs / UNIT_SIZE,
bucketSizeMs / UNIT_SIZE,
)
);
}

计算为了将固定时间间断的,多次setState数据的更新当成一次更新,在这个时间间断内优先级是一样的

11月
23
更新于
11月23
2020
React

react源码解析系列一(React相关API)

发表于 2020-11-03 | 热度 ℃
| 字数统计: 4,092 (字) | 阅读时长: 19 (分钟)

今天开始学习react源码相关的内容,源码基于版本v16.6.0。React16相较于之前的版本是核心上的一次重写,虽然主要的API都没有变化,但是增加了很多能力。并且首次引入了Fiber的概念,之后新的功能都是围绕Fiber进行实现,比如AsyncMode,Profiler等。

React与ReactDom的区别

问题:react仅仅1000多行代码,而react-dom却将近2w行

答: React主要定义基础的概念,比如节点定义和描述相关,真正的实现代码都是在ReactDom里面的,也就是“平台无关”概念,针对不同的平台有不同的实现,但 基本的概念都定义在React里。

React16.6.0使用FlowType做类型检查

Flow 是 facebook 出品的 JavaScript 静态类型检查⼯具。所谓类型检查,就是在编译期尽早发现(由类型错误引起的)bug,⼜不影响代码运⾏(不需要运⾏时动态检查类型),使编写 JavaScript 具有和编写 Java 等强类型语⾔相近的体验。

官方网站

简单示例🌰

1
2
3
npm install -g flow-bin
flow init
touch index.js

1
2
3
4
5
6
7
8
// index.js 进行类型注释
/*@flow*/
function add(x: number, y: number): number {
return x + y
}
add('Hello', 11)

// 报错

阅读全文 »
11月
22
更新于
11月22
2020
工具

webpack

发表于 2019-08-18 | 热度 ℃
| 字数统计: 4,266 (字) | 阅读时长: 18 (分钟)

谈谈你对webpack的看法

webpack是一个模块打包工具,可以使用它管理项目中的模块依赖,并编译输出模块所需的静态文件。它可以很好地管理、打包开发中所用到的HTML,CSS,JavaScript和静态文件(图片,字体)等,让开发更高效。对于不同类型的依赖,webpack有对应的模块加载器,而且会分析模块间的依赖关系,最后合并生成优化的静态资源。

webpack 最出色的功能之一就是,除了 JavaScript,还可以通过 loader 引入任何其他类型的文件。

webpack的基本功能和工作原理?

  • 代码转换:TypeScript 编译成 JavaScript、SCSS 编译成 CSS 等等
  • 文件优化:压缩 JavaScript、CSS、HTML 代码,压缩合并图片等
  • 代码分割:提取多个页面的公共代码、提取首屏不需要执行部分的代码让其异步加载
  • 模块合并:在采用模块化的项目有很多模块和文件,需要构建功能把模块分类合并成一个文件
  • 自动刷新:监听本地源代码的变化,自动构建,刷新浏览器
  • 代码校验:在代码被提交到仓库前需要检测代码是否符合规范,以及单元测试是否通过
  • 自动发布:更新完代码后,自动构建出线上发布代码并传输给发布系统。

  • Entry(入口):Webpack 执行构建的第一步将从 Entry 开始,可抽象成输入。

  • Output(出口):指示 webpack 如何去输出、以及在哪里输出
  • Module(模块):在 Webpack 里一切皆模块,一个模块对应着一个文件。Webpack 会从配置的 Entry 开始递归找出所有依赖的模块。
  • Chunk(代码块):一个 Chunk 由多个模块组合而成,用于代码合并与分割。
  • Loader(模块转换器):用于把模块原内容按照需求转换成新内容。
  • Plugin(扩展插件):在 Webpack 构建流程中的特定时机会广播出对应的事件,插件可以监听这些事件,并改变输出结果

webpack构建过程

  • 从entry里配置的module开始递归解析entry依赖的所有module
  • 每找到一个module,就会根据配置的loader去找对应的转换规则
  • 对module进行转换后,再解析出当前module依赖的module
  • 这些模块会以entry为单位分组,一个entry和其所有依赖的module被分到一个组Chunk
  • 最后webpack会把所有Chunk转换成文件输出
  • 在整个流程中webpack会在恰当的时机执行plugin里定义的逻辑
  1. 初始化:解析webpack配置参数,生成 Compiler 实例
  2. 注册插件:调用插件的apply方法,给插件传入compiler实例的引用,插件通过compiler调用Webpack提供的API,让插件可以监听后续的所有事件节点。
  3. 入口:读取入口文件
  4. 解析文件:使用loader将文件解析成抽象语法树 AST
  5. 生成依赖图谱:找出每个文件的依赖项(遍历)
  6. 输出:根据转换好的代码,生成 chunk
  7. 生成最后打包的文件

webpack打包原理

将所有依赖打包成一个bundle.js,通过代码分割成单元片段按需加载

阅读全文 »
11月
22
更新于
11月22
2020
JS

Vue中axios的封装

发表于 2020-07-21 | 热度 ℃
| 字数统计: 2,696 (字) | 阅读时长: 11 (分钟)

聊聊 Vue 中 axios 的封装

axios 是 Vue 官方推荐的一个 HTTP 库,用 axios 官方简介来介绍它,就是:

Axios 是一个基于 promise 的 HTTP 库,可以用在浏览器和 node.js 中。

作为一个优秀的 HTTP 库,axios 打败了曾经由 Vue 官方团队维护的 vue-resource,获得了 Vue 作者尤小右的大力推荐,成为了 Vue 项目中 HTTP 库的最佳选择。

虽然,axios 是个优秀的 HTTP 库,但是,直接在项目中使用并不是那么方便,所以,我们需要对其进行一定程度上的配置封装,减少重复代码,方便调用。下面,我们就来聊聊 Vue 中 axios 的封装。


阅读全文 »
11月
18
更新于
11月18
2020
JS

30分钟精通React Hooks

发表于 2020-05-12 | 热度 ℃
| 字数统计: 8,708 (字) | 阅读时长: 38 (分钟)

它来了,它来了,16.8版本hooks成功加入(^▽^)

你还在为该使用无状态组件(Function)还是有状态组件(Class)而烦恼吗? —— 拥有了hooks,你再也不需要写Class了,你的所有组件都将是Function。

你还在为搞不清使用哪个生命周期钩子函数而日夜难眠吗? —— 拥有了Hooks,生命周期钩子函数可以先丢一边了。

你在还在为组件中的this指向而晕头转向吗? —— 既然Class都丢掉了,哪里还有this?你的人生第一次不再需要面对this。


阅读全文 »
123…16
陈宇(cosyer)

陈宇(cosyer)

不去做的话永远也做不到。

159 日志
10 分类
51 标签
RSS
GitHub Twitter E-Mail FB Page
推荐阅读
  • Callmesoul
  • JsTips
  • Personal Site
  • Resume
© 2021 陈宇(cosyer)
终于等到你(UV):   |   欢迎再来(PV):
Blog总字数: 312.5k字
苏ICP备17005342号-1