2022-01

每天给你推荐一个新奇,好玩,高品质的开源库,好文,观点或言论等。
项目主页维护当前月份的内容,想看往期内容,可以翻到下方历史汇总部分,然后选择自己感兴趣的月份点进去即可。
一个制作非常精美,我个人非常喜欢的画风的网站。内容是关于 mono repo 工具的。
如果你还不知道什么是 mono repo,或者对 mono repo 管理工具感兴趣,那么请一定花一点时间看看这个文章。
我个人还是很推荐大家尝试一下 nx 的,看了下文章的对比更加加深了我的想法。
地址:https://monorepo.tools
有人不知道 NFT 是什么。
其实我也不是很了解,但是 NFT 有一个重要作用值得大家注意。 NFT 将原本网络中很容易实现的复制功能,变得可识别。
比如用户 A 创作了一段代码,然后用户 B 可以将其复制。作为用户 C 很难知道 A 的代码是复制品还是 B 的代码是复制品。而如果 A 将代码发布到了 NFT,那么 C 就可以很容易知道 B 的代码是复制品。这也是为啥一些 NFT 作品被拍出了天价的重要原因。
前端经常碰到跨域安全问题。之前我的解决方式是通过本地代理(node 或 nginx 等服务)解决。
基本思路就是给请求响应头增加大概如下内容:
Access-Control-Allow-Origin: https://foo.example
Access-Control-Allow-Methods: POST, GET, OPTIONS
Access-Control-Allow-Headers: X-PINGOTHER, Content-Type
Access-Control-Max-Age: 86400
后来我使用了更方便的工具: 浏览器扩展。刚开始的时候用的是一个专门给请求加跨域头的插件。后来发现有些头不会加上,比如 access-control-expose-headers 。
因此一个通用的给请求增加头信息的插件就有必要了。于是我选择了
requestly

美中不足是每个规则只能免费改一个头。不过好消息是你可以新建多个规则,每个规则改一个头就可以白嫖了。
地址:https://app.requestly.io
Web 上传文件,我们可以使用 input 标签 + form 表单来做。而现在更多是使用 js + formData 实现。
参考代码:
const formData = new FormData();
const file = new File([buffer], filename);
formData.append("file", file, filename);
这样会更加自由,我们可以控制上传的文件内容。 接下来, 浏览器会给我们添加
multipart/form-data
以及 WebKitFormBoundary
等,这样文件就可以上传了。如果是在 Node 端,FormData 是不存在的。因此前面提 到的
multipart/form-data
以及 WebKitFormBoundary
等 都需要自己来完成了。这样有点麻烦,不过大家可以使用 form-data 来完成。如果是浏览器,form-data 会使用浏览器原生的 FormData,否则会自己实现一个“几乎等价” 的 FormData。Tauri 是一个让用户使用 JS 开发跨平台桌面程序的类库,核心是 Rust 写的(如今 web 基础工具很多都是 Rust 写的),是大名鼎鼎的 Electron 的竞品。
地址:https://tauri.studio/docs/architecture
fuite 是一个 cli 工具,帮助你一键检测网页是否可能有潜在的内存泄漏。
最简单的用法:
npx fuite https://example.com
地址:https://github.com/nolanlawson/fuite
低代码已经发展了好多年了,也火了很多年。我本人也做了低代码好多年。我实在是不建议大家现在从零开始做低代码,很耗费时间,回报也不高。
目前社区有不少现成工具可以使用或者参考,比如 mometa。
地址:https://github.com/imcuttle/mometa
使用 mono repo 的其中一个挑战就是版本管理更加复杂。原先是仅控制其中一个 package 版本就 ok 了,而现在 mono 仓库有多少 package 就需要管理多少,复杂度就增大了。
于是使用高效的版本管理工具就有必要了,这次推荐两个工具给大家。
这两个工作方式不太一样,大家可以看文档详细了解一下。另外推荐一篇文章,这个文章列举了很多 mono tool,地址:https://turborepo.org/docs/guides/complimentary-tools
feiker.js 作者故意添加无限死循环逻辑到代码中,这究竟是人性的扭曲还是道德的沦丧?欢迎收看本期的社会与法节目。
地址:
- Dev corrupts NPM libs 'colors' and 'faker' breaking thousands of appsdev-corrupts-npm-libs-colors-and-faker-breaking-thousands-of-apps/
Electron 的竞品,用来开发桌面客户端。

地址:https://github.com/tauri-apps/tauri
一个自动生成中国山水画的仓库, 效果真的惊艳,可见作者的数学功底。 仓库就是一个 html,代码全部在 html 中。
地址:https://github.com/LingDong-/shan-shui-inf
monorepo 越来越流行,相应的工具也在不断发展。
其中两个工具最近很是抢眼。这两个工具其实都算是构建工具(build tool)

一个是 TurboRepo,另外一个是 nx。其中 TurboRepo 借鉴了 nx 了一些内容。二者其实各有优劣。这里有一个对于二者的比较文章 Nx and Turborepo ,这篇文章是 nx 官方写的。
地址:https://www.builder.io/blog/how-we-cut-99-percent-js-with-qwik-and-partytown
CSS 出了一个新的媒体查询特性 prefers-color-scheme,它可用于检测用户是否有将系统的主题色设置为亮色或者暗色。
代码示例:
@media (prefers-color-scheme: dark) {
.day.dark-scheme {
background: #333;
color: white;
}
.night.dark-scheme {
background: black;
color: #ddd;
}
}
@media (prefers-color-scheme: light) {
.day.light-scheme {
background: white;
color: #555;
}
.night.light-scheme {
background: #eee;
color: black;
}
}
如上:
prefers-color-scheme: dark
内的样式代码会在用户的浏览器是暗黑主题下启用prefers-color-scheme: light
内的样式代码会在用户的浏览器是浅色主题下启用
基于此,我们可以给网站定制不同的主题样式以适配用户电脑上的主题设置(目前就是暗黑和浅色两种)。
yarn 支持一个特性叫做 resolutions。它主要解决了用户不能指定依赖的依赖(嵌套依赖)的版本问题。
比如你依赖了 react,而 react 依赖了一个包 A,这个包有安全问题,但是 react 迟迟不更新,你就可以通过 resolutions 来强行升级 A (前提是升级满足 package 中的兼容性定义)
yarn 官方给的一个使用例子:
{
"name": "project",
"version": "1.0.0",
"dependencies": {
"left-pad": "1.0.0",
"c": "file:../c-1",
"d2": "file:../d2-1"
},
"resolutions": {
"d2/left-pad": "1.1.1",
"c/**/left-pad": "^1.1.2"
}
}
我们通过 resolutions 指定了 d2 的依赖 left-pad 升级到 1.1.1。
更多内容参考:https://github.com/yarnpkg/rfcs/blob/master/implemented/0000-selective-versions-resolutions.md
vm 是 node 原生提供的一个模块, 提供了一个沙箱环境。
比如你想造一个测试框架的轮子,那么测试用例间的隔离如何做?比如一个测试用例修改了 Array.prototype.map,那么会不会因此影响其他测试用例呢? 使用 vm 就可以解决这个问题。
参考代码:
// replace this code in worker.js:
const context = { describe, it, expect, mock };
vm.createContext(context);
// with this:
const NodeEnvironment = require("jest-environment-node");
const environment = new NodeEnvironment({
testEnvironmentOptions: { describe, it, expect, mock },
});
vm.runInContext(code, environment.getVmContext());
如上代码的 jest-environment-node 是用来模拟 node 端的环境的(而不是浏览器),我们可以使用 testEnvironmentOptions 来定制一些全局变量。
import map 是 ESM 中的一个特性,允许你自定义引入模块的解析逻辑。
如果不使用 import maps,直接在浏览器上执行类似下面这种绝对路径就会有问题:
import moment from "moment";
import { partition } from "lodash";
我们可以使用 import maps 解决这个问题:
<script type="importmap">
{
"imports": {
"moment": "/node_modules/moment/src/moment.js",
"lodash": "/node_modules/lodash-es/lodash.js"
}
}
</script>
这样 moment 和 lodash 就会从网站根路径的 node_modules 查找模块了。
vue 的可视化模板编译工具 Template Explorer
如果你只是想看下 template 会被编译为怎么样的 ast 以及 render function,那么可以使用这个工具来帮你。
这个工具的源码在 Github 的 vue 仓库中,地址:https://github.com/vuejs/vue-next/tree/master/packages/template-explorer 如果你需要 debug 的话可以在仓库中启动运行,如果只是看下结果,使用在线版足够了。
地址:https://vue-next-template-explorer.netlify.com/
clinic.js 是一个诊断工具,可以帮助你发现潜在的性能和安全问题。

如上图, clinic 可以诊断包括 CPI,内存,事件循环延迟(卡顿)以及 handlers。
它还可以直接帮你定位到具体的可能存在的问题点。如下图:

clinic.js 就诊断 到了代码可能存在 IO 方面的问题。
地址:https://clinicjs.org/
类似于 apache 的 abtest, wrk 也是一个 http 压测工具,二者功能和用法都是类似的。你可以用它来测试你的代码能否满足业务要求的并发量。
地址:https://github.com/wg/wrk
两个问题看你有没有高并发经验。
- 1.如何避免项目的错误日志扎堆上报,导致服务器瞬间压力过大?
- 2.如何保证后端突然接受大量请求而不至于挂?
其实这两个问题是一个是客户端问题,一个是服务端问题,还是很有代表性的。
答案其实不唯一, 我这里简单分享个随机丢弃思路。
- 1.可以采取随机数舍弃的方法,比如随机舍弃 50% 的请求。
- 2.可以采取随机数舍弃的方法,比如在 cpu 大于 80% 的时候,随机舍弃 50% 的请求。专业一点这个叫熔断。
当然除了这个思路还可以采用异步上报,引入队列等众多方法, 这里就不多做介绍。这个随机丢弃的方式简单粗暴且有效,但是对于重要的业务,比如支付还是谨慎使用。
如果你需要做增量更新的功能,可以考虑使用这个工具集。
其中 bsdiff 用来 diff 两个二进制包 bspatch 用来将 diff 信息 patch 过去。
参考代码:
var assert = require("assert"),
bsdiff = require("bsdiff"),
crypto = require("crypto");
// cur 是当前的二进制包
// ref 是需要更新到的二进制包
var cur = crypto.randomBytes(1024),
ref = crypto.randomBytes(1024);
bsdiff.diff(cur, ref, function (err, ctrl, diff, xtra) {
if (err) throw err;
bsdiff.patch(cur.length, ref, ctrl, diff, xtra, function (err, out) {
if (err) throw err;
// 将 out 信息更新到当前的二进制包 cur 上
for (var i = 0; i < cur.length; i++) {
if (cur[i] !== out[i]) throw "Patch did not work";
}
console.log("Patch worked!");
});
});
地址:https://github.com/mikepb/node-bsdiff
adb 全称 Android Debug Bridge,是安卓上的调试工具。我们可以用它做一些自动化的事情。
比如我们可以用 adb 自动录制屏幕,并获取录制的详细数据信息。
代码参考:
adb shell screenrecord --time-limit 5 --verbose /path/to/save/a.mp4
这比手工录制效率高很多。
小技巧:
我们可以利用上面录制的视频测量应用的首屏时间。比如我们可以使用一些工具将上面的视频帧逐个提取出来,然后利用图像识别工具反向逐个检测相邻两个图片的相似度,找出最后一张发生相似度明显变化的图片。这样首屏时间可以记为
最后一张发生相似度明显变化的图片的时间 t1 - 页面开始加载的时间 t2
如果你有离线化的需求,那么可以试试这个 webpack 插件。它可以帮助你预渲染出静态 html, 使得用户在离线或者弱网情况下直接打开页面,提高用户体验。
基础用法:
const path = require("path");
const PrerenderSPAPlugin = require("prerender-spa-plugin");
module.exports = {
plugins: [
...new PrerenderSPAPlugin({
// Required - The path to the webpack-outputted app to prerender.
staticDir: path.join(__dirname, "dist"),
// Required - Routes to render.
routes: ["/", "/about", "/some/deep/nested/route"],
}),
],
};
如上图,你告诉插件你的打包资源位置以及你需要离线化的几个路由,插件就会自动帮你生成离线化资源。更多用法参考仓库文档。
地址:https://github.com/chrisvfritz/prerender-spa-plugin
我重新整理了下自己的公众号,并且我还给它换了一个名字
脑洞前端
,它是一个帮助你打开大前端新世界大门的钥匙 🔑,在这里你可以听到新奇的观点,看到一些技术尝新,还会收到系统性总结和思考。在这里我会尽量通过图的形式来阐述一些概念和逻辑,帮助大家快速理解,图解是我的目标。
之后我的文章会同步到微信公众号
脑洞前端
,你可以关注获取最新的文章,并和我进行交流。另外你可以回复大前端进大前端微信交流群, 回复 leetcode 拉你进 leetcode 微信群,如果想加入 qq 群,请回复 qq。

Last modified 8mo ago