Skip to content

Commit

Permalink
Merge branch 'gitbutler/integration'
Browse files Browse the repository at this point in the history
  • Loading branch information
连远生 committed Mar 11, 2024
2 parents a3ae06b + e420db0 commit 25cf490
Show file tree
Hide file tree
Showing 131 changed files with 409 additions and 59 deletions.
12 changes: 12 additions & 0 deletions content/.other.md
Original file line number Diff line number Diff line change
Expand Up @@ -1833,7 +1833,10 @@ MVC 或类 MVC 框架

props 的数据流向是单向的,只能从父组件流向子组件

<<<<<<< HEAD
- 存储、计算、网络是计算机基本概念
=======
>>>>>>> gitbutler/integration

state 更新的异步性和自动批处理
声明这三种数据来设计 React 应用的数据流,进而控制应用的交互和逻辑。
Expand Down Expand Up @@ -1992,6 +1995,7 @@ state 更新的异步性和自动批处理
- tty
- React
- StrictMode
<<<<<<< HEAD
- Blog
- `nitroApp.hooks.hook("content:file:beforeParse", (file: ContentFile)` 类型问题
- TocJSX 组件更新问题
Expand All @@ -2015,6 +2019,8 @@ state 更新的异步性和自动批处理
- slot
- component
- teleport
=======
>>>>>>> gitbutler/integration
- 个人
- freedom2
- share-screen
Expand All @@ -2034,8 +2040,14 @@ state 更新的异步性和自动批处理
- 语言学习路线
- 基础
- 变量、值和类型
<<<<<<< HEAD
- 语句、表达式、运算
- 控制语句
=======
- 运算符、表达式、语句
- 表达式:计算
- 语句:控制流
>>>>>>> gitbutler/integration
- 函数
- 模块系统
- 模块路径
Expand Down
2 changes: 1 addition & 1 deletion content/Rust/.README.md
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ tags:
::tl
- Rust
- 设计理念
- 内存安全、并发安全、性能
- 安全(内存安全、并发安全、性能(零抽象)
- 多范式编程
- 划分 Safe rust 和 Unsafe Rust(方便与其他语言沟通)
- [Rust 编程基础](#rust-编程基础)
Expand Down
24 changes: 15 additions & 9 deletions content/Rust/所有权、借用及生命周期.md
Original file line number Diff line number Diff line change
Expand Up @@ -5,10 +5,12 @@ tags:
- rust
---

# 内存安全:所有权、借用及生命周期
# Rust 所有权、借用及生命周期

::tl
- 值的内存分配
- 内存安全
- 内存安全错误:悬空指针、双重释放、使用未初始化的内存等等
- 值在内存中如何分配
- 栈内存
- 在编译时已知的固定大小
- 栈上的操作比堆高效,因为栈上内存的分配和回收只需移动栈顶指针即刻
Expand All @@ -18,16 +20,20 @@ tags:
- 堆内存
- 数据具有动态大小
- 不固定生命周期
- 内存资源如何回收
- 手动回收
- 自动垃圾回收
- 单一所有权
- Rust 明确了所有权的概念,所有权就是拥有资源的管理权利这些资源可以是堆上的动态分配的内存资源,也可以是栈上的内存资源,或者是系统资源,比如 IO 资源
- Rust 明确了所有权的概念,所有权就是拥有资源的管理权利这些资源可以是堆上的动态分配的内存资源,也可以是栈上的内存资源,或者是系统资源,比如 IO 资源
- 在 Rust 中,值也是一种资源,每一个值都有一个被称为其所有者(owner)的变量;值在任何时候都只能有一个所有者;当所有者(变量)离开作用域,这个值将被丢弃(drop)
- **Rust 通过单一所有权来限制任意引用的行为**
- 所有权其实是内存结构之上的更上层概念,并不是说只有在堆中分配的资源才有所有权。实际上,栈上的资源也是有所有权的。所有权这个概念实际上屏蔽了底层内存结构的细节,让我们可以站在一个新的层次上更有效地对问题进行建模
- 赋值操作
- Move(默认行为):即**所有权转移**,将值的所有权转移给新的所有者
- [Clone vs Copy](#clone-trait-vs-copy-trait)
- Borrow:借用
- 借用
- Rust 中的赋值操作
- 转移(Move,默认行为):即**所有权转移**,将值的所有权转移给新的所有者
- 拷贝
- [Clone vs Copy](#clone-trait-vs-copy-trait)
- 借用(Borrow)
- 借用(Borrow)
- 在 Rust 中,“借用”本质上就是“引用”,只不过多了些规则,便提出了新概念“借用”
- 创建一个引用的行为称为**借用**
- `&T:不可变借用`
Expand All @@ -36,7 +42,7 @@ tags:
- 可存在多个不可变借用,但只能有一个可变借用
- 可变借用与不可变借用的作用域不能交叠,可变借用之间的作用域也不能交叠
- 借用只在所有权者的**生命周期内**才有效,防止悬空引用
- 所有权者不能在借用期内修改值
- 所有权者不能在借用期内修改值或者转移
- 生命周期注释
::tl

Expand Down
File renamed without changes.
File renamed without changes.
File renamed without changes.
102 changes: 102 additions & 0 deletions content/Web/.PWA.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
---
discussionID: 3k_7aC2ri9lgf-gcm7-7S
tags:
- web
- pwa
---

# PWA

- PWA:渐进式 Web 应用程序,是一系列技术集合
- [Manifest](https://developer.mozilla.org/zh-CN/docs/Web/Manifest)
- [Service Worker](#service-worker)
- CacheStorage
- Notification
- Push Message
- PWA 实践
- 设计标准
- 移动优先、响应式设计
- 渐进增强,功能检测
- 使用 `@supports` 检查浏览器是否支持 CSS 功能
- 发布现代 JavaScript,您可以使用 module/nomodule 模式
- 提供快速且良好的用户体验
- Web Vitals
- 加载中
- 交互的
- 视觉稳定性
- 应用分发与安装
- 分发
- 应用商城
- Web 搜素
- Manifest + 离线模式
- 图标
- 主题
- 主题颜色
- 背景颜色
- 强调色
- 应用更新
- 更新类型
- Manifest
- 应用程序数据
- [Service Worker 实践](#service-worker-实战)
- 版本管理
- 资源缓存
- 更新提醒
- 使用 DOM 或画布 API在屏幕上呈现通知
- Message push
- 图标提示:[Badging API](https://developer.mozilla.org/en-US/docs/Web/API/Badging_API)





### Service Worker 实战


- 资源缓存
- 原则
- 合理使用空间和带宽,在快速或离线体验之间找到平衡点
- 不要一次性缓存所有资产,在 PWA 的生命周期内合理得安排多次缓存资产
- 缓存时机
- 在安装 service worker 时缓存最少的资产集
- 网络空闲或者主线空闲的时候
- 当用户导航到某个部分或路线时按需缓存
- 激活时清除旧版本
- 响应式缓存
- 缓存策略
- 预缓存
- 按需缓存
- 运行时缓存:指在运行时从网络请求资源时的缓存策略([代码示例](https://web.dev/learn/pwa/serving/)
- 跨域资源
- 响应必须返回 2xx 状态代码,否则 `cache.add()``cache.addAll()` 会失败
- 将被当作**不透明响应**:意味着您的代码将无法查看或修改该响应的内容或标头,及其大小
- 更新及清除
- WorkBox
- 路由拦截
- Workbox 模块在不同的上下文中工作

## 学习参考

- [Progressive Web Apps](https://web.dev/progressive-web-apps/)
- [Learn PWA](https://web.dev/learn/pwa/)
- [The service worker lifecycle](https://web.dev/service-worker-lifecycle/)


- 字典
- 缓存优先
- swr
- 乐观UI


- PWA 应用
- 组织工程和代码
- 单元测试
- ServiceWorker 作用域冲突
- 远程控制我们的 ServiceWorker
- 最优的资源缓存方案
- 如何监控我们的 ServiceWorker,收集数据


- 知识
- 技能
- 人脉
File renamed without changes.
File renamed without changes.
File renamed without changes.
164 changes: 164 additions & 0 deletions content/Web/SW.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
# Service Worker

- Service Worker
- 安全限制:HTTPS/localhost
- 控制范围
- 默认下由 SW 文件路径决定其控制范围:比如 `//example.com/foo/sw.js` 它的默认范围是 `//example.com/foo/`
- 手动作用域设置
- `navigator.serviceWorker.register('sw.js', {scope: xxx})`
- HTTP 响应设置 Service-Worker-Allowed 头部
- `navigator.serviceWorker.controller` 获取当前作用域的 Service Worker 实例
- **作用域冲突**
- 只允许一个 ServiceWorker 实例
- 子域注册的服务会优先于父域的服务
- [生命周期](#sw-生命周期)
- [更新触发](#sw-更新触发)
- 事件同步
- 将任务派发到后台同步完成
- 页面发起的请求会随着页面的关闭而终止
- 在离线状态下,很难将用户的网络请求缓存起来,并在网络恢复正常后再次进行请求
- 重试机制
- 推送通知

## SW 生命周期

- 注册:下载、解析 Service Worker 脚本
```js
if ('serviceWorker' in navigator) {
navigator.serviceWorker.register("/serviceworker.js");
}
```
- 安装:激活 `install` 事件(首次安装、更新安装时触发)
- 安装阶段通常是实现处理缓存方案
```js
// /sw.js
self.addEventListener("install", (event) => {
const cacheKey = "MyFancyCacheName_v1";

// `installEvent.waitUntil()` 延迟安装完成
event.waitUntil(
caches.open(cacheKey).then((cache) => {
// Add all the assets in the array to the 'MyFancyCacheName_v1'
// `Cache` instance for later use.
return cache.addAll([
"/css/global.bc7b80b7.css",
"/css/home.fe5d0b23.css",
"/js/home.d3cc4ba4.js",
"/js/jquery.43ca4933.js",
]);
})
);
});
```
- 等待:安装成功后,如果已有旧版本在运行,则暂时没有控制页面的权力,需要等待从当前 worker 获得控制权
- 等待阶段时强制跳过等待 `self.skipWaiting()`
- 激活:触发 `activate` 事件
- 旧版本 Service Worker 控制下的页面全部关闭,重启页面
- 首次注册激活时,已打开的页面只有在刷新后才会受控,可以强制控制页面 `self.clients.claim()`
- 监听事件
- `message`
- `fetch`
```js
// fetch event handler in your service worker file
self.addEventListener("fetch", event => {
// 可以创建新的响应或者从缓存中响应
const response = .... // a response or a Promise of response
event.respondWith(response);
});
```
- `push`
- `sync`
- `notification`
- `periodic-sync`
- 终止与启动
- 废弃
- 安装失败
- 激活失败
- 用户执行了注销操作 `registration.unregister();`
- 新版本的 Service Worker 替换了旧版本

## SW 更新

- 检测原理
- 检测 SW 及 importScript 内容字节是否发生变化
- 在检查已注册的 Service Worker 脚本的更新时,可 `navigator.serviceWorker.register()` 时传入一个新选项:`updateViaCache` 对是否忽略脚本的 http 缓存
- 更新触发
- 自动
- 在 Scope 内页面导航
- `.register()`SWURL 或者 Scope 发生改变
-24 小时内检查一次
- 手动
```js
navigator.serviceWorker
.register("./update.js")
.then(function (registration) {
registration.addEventListener("updatefound", () => {
console.log("updatefound");
});
registration.update();
})
.catch(function (err) {
// do domething...
console.log(err);
console.log("register failure");
});
```
- 自定义更新处理逻辑
```js
navigator.serviceWorker.register('/sw.js').then(reg => {
reg.installing; // the installing worker, or undefined
reg.waiting; // the waiting worker, or undefined
reg.active; // the active worker, or undefined
// 检测服务工作者的变化
reg.addEventListener('updatefound', () => {
// A wild service worker has appeared in reg.installing!
const newWorker = reg.installing;
newWorker.state;
// "installing" - the install event has fired, but not yet complete
// "installed" - install complete
// "activating" - the activate event has fired, but not yet complete
// "activated" - fully active
// "redundant" - discarded. Either failed install, or it's been
// replaced by a newer version
newWorker.addEventListener('statechange', () => {
// newWorker.state has changed
});
});
});
navigator.serviceWorker.addEventListener('controllerchange', () => {
// This fires when the service worker controlling this page
// changes, eg a new worker has skipped waiting and become
// the new active worker.
});
```

## 最佳实践

- 作用域冲突
- 功能拆封,各个域的服务主动引入
- 功能提升:全部整合到根作用域,以插件机制动态注册功能
- SW 更新管理
- 避免更改你的 sw 脚本的 URL。在离线模式下 index 会被缓存,导致 sw 的脚本依旧是旧内容
- 避免缓存 sw 脚本
- 更新通知:慎用 skipWaiting 去直接控制页面,最好通知用户刷新更新
- 资源缓存
- 缓存时机
- 请求策略
- 仅缓存
- 仅限网络
- 缓存优先:首先从缓存中进行匹配,如果存在相关请求的响应,返回该响应,否则通过网络获取
- 网络优先:首先通过网络获取,如果请求异常,则从缓存中获取
- SWR(Stale-while-revalidate):先缓存后网络。如果在缓存中匹配到相关请求的响应,在返回该响应的同时依旧会发起网络请求,并更新相关缓存,否则直接请求
- 导航预加载

## 学习参考

- [The service worker lifecycle](https://web.dev/service-worker-lifecycle/)
- [Fresher service workers, by default](https://developer.chrome.com/blog/fresher-sw/#checks_for_updates_to_imported_scripts)

- [GlacierJS](https://github.com/JerryC8080/glacierjs)
File renamed without changes.
File renamed without changes.
File renamed without changes.
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes
File renamed without changes.
File renamed without changes.
Loading

0 comments on commit 25cf490

Please sign in to comment.