🌸
357 subscribers
127 photos
17 videos
197 links
记录一些 学习笔记,工具,和其它奇怪的东西
Download Telegram
🌸
https://publicsuffix.org/list/public_suffix_list.dat JP 域名分得好细,粗略数了下,大概有1900多条 .jp 记录,应该是列表里最多的了。
对了, github.io、 gitlab.io、 glitch.me 这些也在里面,这表示像 github.io 也被当成“顶级域(TLD)”对待。

也就是说 a.github.iob.github.io 是两个完全独立的站点,并不共享资源。
想到两个 Service Worker 奇怪用法

1. 把一个页面(或数据)拆成 header、content、footer 三部分,在 Service Worker 缓存并自动拼上 header、footer,这样以后都只请求 content 就行了,相当是把 Service Worker 做成了一个简单的 rendering engine。

2. 在 Service Worker 维持一个 wss,并在会话建立后,把所有 HTTP Request 都 over wss,这样可以同时受益于 HTTP 的低会话成本、wss 的低延迟。

第二个打算近期找时间试一试,看看在小范围内能否获得性能提升。

#神奇海螺
Safari 16 将支持 Web Push API

Apple 将为 Safari 16 带来全平台的 Web Push Notifications 支持,它是最后一个提供 Web Push 支持的主流浏览器,届时 Web Push 将在所有主流平台可用。

此外,Safari on iOS 的 Web Notifications API 在此次更新后依旧不可用,它并没有被特别提到。

ref:
https://www.apple.com/ios/ios-16-preview/features/
https://www.apple.com/macos/macos-ventura-preview/features/
Forwarded from Zenithal Hourly Radio
用了这么多年 Chrome DevTools 才发现 resource type filter 是可以多选的,只需要按住 Cmd/Ctrl 选择。
👍1
好诶,原来浏览器已经有了 Compression/Decompression API,而且还是 Stream 形式。

看了一下支持 gzip、deflate,不过仅在高版本的 Chrome/Edge 可用。

可以接受,马上去把我 300KB 多的 wasm brotli 扬了,加个内容协商,不支持的浏览器就不压缩(
👍2
这写法太鬼畜了,既不想JS报错,又不想TS报错。既要又要了属于是
Vite 多入口踩坑

想给项目加多一个入口,并可以通过 /admin 请求(与前端的路由保持一致),按照 Vite 的目录结构,应该在 projectRoot 创建一个 admin 目录。

于是我创建了 projectRoot/admin/index.html 文件,并在浏览器中通过 /admin 测试,屡屡失败,但请求 /admin/index.html 却可以。

这一旦让我怀疑是自己配置的不对,因为 文档 确实是这么写的,我开始了在配置与配置之间反复调整,然后陷入不断的自我怀疑。

直到 ── 这时时间已经过去很久,我在偶然中发现,/admin 与 /admin/ 是不同的,请求 /admin/ 竟然可以!!这时我既喜悦,又气愤,这 TM 算什么 J8 设计??

此前我确实反复读了文档,文档也确实写的 `/nested/`,这没毛病,但却没写 /nested/ 和 /nested 是不同的,就连顺带一提 “注意最后的 /” 都没有,这让人下意识觉得只是书写风格的不同 ── 毕竟其它“常规”的 webserver 都应该默认认为这二者是等价的。

退一步说,如果 /nested/ 表示目录,/nested 表示文件,但是你能在同一个目录里建两个完全同名,但类型不同的东西?所以添加 “/” 的意义是什么,我是真的不理解。

---
补充内容:

写完这篇 post,我找到了 这个5个月前的 issue,它被标记为 bug,目前还是 open 状态。然而我并不确定这是不是 bug,因为 Vite 确实被实现为区分 “/”,而且文档也与这种行为保持了一致(最后带了 “/”),因此至少在写文档时,是很清楚 Vite 会有这种行为的。

所以我更倾向这是“先天性设计问题”,直到后来有像我这样的傻瓜踩到坑,被提出来,才被定性为“bug”。但是因为这个,我浪费了大量宝贵时间,实属不值!
😁1
Rollup plugin 可能会为 virtual module id 添加 \0

Rollup 约定如果一个插件使用了 virtual module,则它的 id 需要以 \0 开头。

我发现这个,是因为在配置 manualChunks 时,出现了一些莫名其妙的问题,比如本是 dynamic import 的 bundle,却被提前 import 了。

在我的项目里,这是由于 commonjs 插件的 commonjsHelpers.js 被打包在了这个毫不相关的 bundle 里。而根本原因是我使用 id === 'commonjsHelpers.js' 比较 id,但实际的 id 是 '\0commonjsHelpers.js'。

这意味着,最好使用 id.includes('commonjsHelpers.js') 比较,或至少是 id.endsWith('commonjsHelpers.js') 而不是 startsWith。

话虽如此,某些插件创建的,如以 react/ 或 vite/ 开头的 module,依旧可以使用 startsWith,因为它们并不包含 \0。

#experience
我懂了,元宇宙的尽头是飞机杯🤣
【广东省应急管理厅、水利厅、水文局】提醒您:据监测预报,6月22-23日,我省北江干流出现超百年一遇特大洪水,沿江多个水文站超警,芦苞涌、西南涌等支流也将迎来较高洪水位。请广大市民群众提高防灾避险意识,危险时段人不下河、船不过境,出外野炊露营不选择江河滩地,特别是加强学生、儿童安全教育和日常看护,不到危险、陌生的江河游泳,谨防溺水。(广东预警信息发布中心2022年6月22日发布)

#sms “超百年一遇特大洪水”,看这几个字就恐怖,又是百年一遇
重新续了 GitHub Copilot,需要重新授权下 GitHub 帐号,在 VSCode 找了半天 sign out 都没找到,Google 了一下才发现要通过 activity bar 的 icon 登出。

但是 activity bar 常年是被我隐藏的,因此我需要先把它显示出来,登出,然后再隐藏回去。

感觉这设计太蠢了,为什么不把登出这种操作集成到 Command Palette (Cmd-Shift-P),隔壁的 IDEA (Cmd-Shift-A) 我就是这么登出的。

#吐槽
Rollup 插件开发:让 Service Worker 中的 import 支持 Firefox

我有一个 packet module,它是一个实现了 binary communication protocol 的 common module,这意味着它不只在 SW 中使用,还会在通常的 browser context 中使用,因此可以将该 module 打包为独立的 bundle,以便能在这两个不同的地方分别 import 它。

但是,import statement in workers 在 Chrome、Edge、Safari 都得到了支持, Firefox 却不支持。要想让 SW 在 Firefox 也能正常工作,就必须考虑另外一个方案:将 packet module 分别为 SW 和 browser context 打包两份,也就是说 packet 一份代码抽象为两份存在,此时便不再需要 import。这没关系,因为它足够小且足够关键。

那么,问题是,在 Rollup 中每个 module 由一个 unique id 标识,这意味着 不可能让一份 id 产出两份代码。在这里,我选用更加灵活的 virtual module 实现这一目的。

操作步骤是,在 transform hook 中 parse SW entry 的 AST,traverse 里面所有的 import nodes,并分别将它们替换,如 import {pack, unpack} from '../utils/packet' 替换为 import {pack, unpack} from 'sw-import:../utils/packet'

替换后的模块名会进入 resolveId hook,在这里需要为其补全 extension,如 `sw-import:../utils/packet.ts`,并在随后的 load 中将其从 fs 加载即可。最后还需要在 manualChunks 中,检查 id 是否包含 `sw-import:`,如若包含,将其与 SW scripts 打包到一起,否则打包到 common bundle 并服务于常规的 browser context。

#experience
👍1
2202 年我的 React 搭配

状态管理:局部 jotai、全局 zustand
网络请求:swr
路由:React Router
CSS:emotion + Tailwind CSS
UI:MUI、Mantine
动画:react-spring
表单验证:React Hook Form + zod
日期:Day.js
汇总:强制创建 layer 的属性,及 side effects

will-change: transform:会创建新的 containing block,导致 position: fixed 或 position: absolute 异常

transform: translateZ(0):与 will-change: transform 有同样问题。早期的 Chrome、Safari 会引发闪烁,因此使用 backface-visibility: hidden 作为替代

backface-visibility: hidden:会把 backface 的内容隐藏,在 3D 空间旋转元素时会有问题

will-change: opacity:会创建新的 stacking context,影响元素的呈现顺序,但可以通过 z-index 恢复到预期状态

一般使用 backface-visibility 或 will-change: opacity,副作用相对最小。

See also: https://t.me/handrush/151
#learning
FPS 不是流畅动画的全部

今天测试 CSS 与 JS 动画的性能差异时,发现一个有趣的现象:使用 JS 创建的动画,虽然能持续跑满 60fps,但动画本身“看起来”并不流畅;而 CSS 动画很流畅,但它却并不总是保持在 60fps。

稍微研究了下,发现这跟一个叫 subpixel 的东西有关,具体来说,对于 sub-pixel animations,它会在像素与像素之间添加模糊,使人眼看起来更平滑。

由于并不存在“半个像素”,一些更细小的动画效果就需要通过 subpixel 达到,它让人看起来动画是在“动”,实际上物体并没有动,而只是像素之间的交替变换。

因此,动画应尽量使用 CSS,或 Animations API。CSS 动画不仅能更充分利用 GPU,还能为动画提供诸如 subpixel 的优化,以减少 paint/composite 次数,并让视觉感到流畅。此外,它还不会破坏现有文档结构,而招致的频繁 lay out。

#learning
👍1
CSS Pixel 与 Device Pixel

CSS Pixel 不与真实的 Device Pixel 一一对应。在具有高 Device Pixel Ratio (DPR) 的设备上,一个 CSS Pixel 可能由多个 Device Pixel 表示,如被排列为 2x2 的方格。

DPR 为方格的高度,或宽度,2x2 grid 的 DPR 是 2。对于图像,其宽高与 Device Pixel 相关,若 image 元素 width 为 200px,对应 Device Pixel 为 400px,则图像的清晰显示宽度应为 400px。

#learning