2021-08

每天给你推荐一个新奇,好玩,高品质的开源库,好文,观点或言论等。

项目主页维护当前月份的内容,想看往期内容,可以翻到下方历史汇总部分,然后选择自己感兴趣的月份点进去即可。

2021-08

2021-08-31[工具]

wavesurfer.js 是一个可视化声波的 js 库。

它可以将一个音频(比如 mp3)的声波以可视化的方式渲染到浏览器上。不仅如此,你也可以通过组合多种参数,响应事件,调用方法等实现更多的效果,具体可参考官方文档。

地址:https://wavesurfer-js.org/

2021-08-30[资讯]

91 天学算法是我和几个算法大佬一起组建的一个算法提高班。通过 91 天的集中化的学习,让你遇见更好的自己

如果你想提高算法能力进击大厂,不妨试一下。

地址:https://lucifer.ren/blog/2021/08/21/91algo-5/

官网:https://leetcode-solution.cn/91

2021-08-27[工具]

marked 是又一个将 markdown 转为 html 工具。这其实是我很早就 star 的一个仓库。

之前我一直用的是 markdown-it,原因很简单,就是因为它老牌用的人多,插件生态丰富。而 marked 主打的是性能。因此如果你对性能有要求,不妨可以调研一下 marked 是否更合适。

地址:https://github.com/markedjs/marked

2021-08-26[教程]

这算是我见过的唯一一个通俗易懂的 haskell 教程。目前已经更新了三篇:

如果你对函数式编程感兴趣,不妨学习一下 haskell,一定不会让你失望。几年前我在学习 fp(函数式编程)的时候,就借用了一些 haskell 的思想。比如使用 fn :: a -> a 的方式给函数添加签名。

地址:https://blog.kalvad.com/tag/haskell/

2021-08-25[工具]

有没有想象过:当你入职一家新公司,只需要下载一个 app 或者登录一个网站,然后所有软件都可以通过它来安装更新,包括常见的开发工具,编辑器插件,浏览器插件等等。

AppWorks Toolkit 就是这样一个工具。

可惜的是,现在功能还没有图上那么多。目前似乎只有可怜 node 管理,并且迟迟不更新,因此我的建议是不妨再等等,等个一年半载等它完善或者参考这个思路自己开发一款类似的工具

仓库地址:https://github.com/appworks-lab/toolkit

2021-08-24[仓库]

如果你想开发 vscode 插件,并且想用 webview 承载 vscode 插件的内容。不妨可以参考下这个 demo 程序。

使用 webview 开发好处是可以使用 web 技术栈,这使得将以往 web 内容无缝迁移到 vscode 插件变得可能。比如公司内部已经有一套基于 web 的系统,使用 webview 几乎可以不用多大改动就可以做成一个运行在 vscode 的插件。

上面说不用多大改动,其实这里的改动主要就是vscode 插件和 webview 的通信。比如 webview 不能发送网络请求,而需要 vscode 进行转发等等。因此如果你的应用又很多网络或者需要借助于 vscode 核心 api 的功能,而展示内容不多,就不适合用 webview 来做 vscode 插件

仓库地址:https://github.com/youngjuning/juejin-me

2021-08-23[技巧]

测试驱动开发(TDD)要求大家先写测试用例。很多时候,我们第一时间想到的是功能点,即我要测试的几个功能是什么,但具体如何断言还没想好。

这个时候,我们可以先写下一个空的测试用例。类似这样:

describe("#1 do something", () => {
  test("#1.1  should work when ..."); //
  test("#1.2  should work when ...");
  test("#1.3  should work when ...);
  ...
});

而这样的话通常会报错(比如使用著名的 jest 测试框架)。

那为什么 jest 要设计成空的测试用例要报错呢?不报错不好么?这里有一个回答很中肯:

那既然空的测试用例报错是合理的,我们写空的测试用例这个事情也是合理的,那如何调节这个矛盾呢?

  • 一种方式是使用 test.skip 跳过测试用例。这个和使用 jest -t 'test case name' 有点像。都是跳过部分用例,仅执行一部分用例。

  • 另外一种方式是使用 test.todo。这个是新增的一个方法,功能类似。不过显示的方式有点变化,起到了前面那位小哥提到的提示用户有空的测试用例没有写的效果。

2021-08-20[工具]

bibi 是一个在线 epub 阅读器。

主要特点:

  • 符合 EPUB 3。除了日语竖写和 ruby 外,还显示了各种语言和布局。

  • 基于 MIT 许可开源软件。请放心使用。

  • 它由 100% JavaScript 制成,适用于各种设备浏览 ​ 器。支持的环境: Chrome / Safari / Opera / Firefox / Microsoft Edge / Internet Explorer 11

地址:https://bibi.epub.link/#demo

2021-08-19[工具]

txiki 是一个 JS Runtime,它的特点就是一个字:

什么是 JS Runtime?顾名思义,就是 JS 的运行环境。它和 JS 引擎是不一样的,JS 引擎对接的是 ECMA 规范。而运行时则可能会增加一些符合其他规范的内容。比如浏览器就是 JS Runtime,Node 也是 JS Runtime。

比如 DOM API,再比如 BOM API 都是运行时提供的,和 JS 引擎没有关系。node 的话还有一些系统 api,比如 fs 等,这些也是运行时提供的。

而 txiki 则对接的是浏览器 api。底层 JS 引擎用的是 quickjs,使用 libuv 跨平台(与 node 一样)。

地址:https://github.com/saghul/txiki.js

2021-08-18[技巧]

如果你想重命名一个项目中的某个变量,你会怎么做呢?

难道是 ctrl + f 搜索,然后 replace 么?这样不仅效率低,而且容易出错。

更聪明的做法是使用 rename symbol 功能,主流编辑器都有这个功能。比如 vscode 直接点击某个变量,选择 rename symbol,然后你就可以输出新的名字点确定,之后这个项目(可能有多个文件)都会被替换为新名字。由于其实基于 ast 去做的,因此准确率很高。使用这种方法几秒就可以替换完成这个项目。

2021-08-17[仓库]

本文介绍的是利用学生身份可以享受到的相关学生优惠权益,但也希望各位享受权利的同时不要忘记自己的义务,不要售卖、转手自己的学生优惠资格,使得其他同学无法受益。

https://github.com/ivmm/Student-resources

2021-08-14[新闻]

Github 出了一个新的功能,用来方便地在论文中引用 Github 资料。

如果你想让其他人正确引用你的仓库,你需要:

  1. Github 中的内容发表过论文,这样你会得到一个 doi

  2. 在 Github 仓库的根目录新建文件 CITATION.cff。文件类似:

cff-version: 1.2.0
message: "If you use this software, please cite it as below."
authors:
- family-names: "Lisa"
  given-names: "Mona"
  orcid: "https://orcid.org/0000-0000-0000-0000"
- family-names: "Bot"
  given-names: "Hew"
  orcid: "https://orcid.org/0000-0000-0000-0000"
title: "My Research Software"
version: 2.0.4
doi: 10.5281/zenodo.1234
date-released: 2017-12-18
url: "https://github.com/github/linguist"

这样你的 Github 主页就有这样一个按钮。其他人想要引用你的 Github 论文,就可以直接点击这里进行复制粘贴。

关于这个功能的详细介绍请参考:https://github.blog/2021-08-19-enhanced-support-citations-github/

2021-08-13[好文]

SSR(Server Side Rendering),CSR(Client Side Rendering),SSG(Static Site Generation),ISR(Incremental Static Regeneration) 分别是什么,基本原理如何你知道么?

next.js 支持这几种渲染模式。不仅如此, next.js 还支持这几种模式的混合模式,比如 SSR + CSR 模式 和 SSG + SSR 模式。这篇文章就详细介绍了 next.js 中的几种渲染模式。

地址:https://mp.weixin.qq.com/s/tDPkTwrR031CjsWbiVTVGw

2021-08-12[仓库]

mitosis 是一个遵循 write once,run everywhere 哲学的前端框架。你可以使用 mitosis 写代码,并最终编译为其他平台,比如 Vue, React, Solid, Angular, Svelte 等等。

如下是其目前对各个框架的支持情况:

它的基本原理很简单,就是将 mitosis 代码转义为 JSON,接下来 mitosis 通过解析这份 JSON 文件生成其他不同平台的代码。

个人认为想法很不错,但是学习价值大于实用价值。因为这种方案坑可能会有很多,不太建议大家直接在商业项目使用。如果非要使用,请做好详细的调研 ⚠️。

地址:https://github.com/BuilderIO/mitosis

2021-08-11[技巧]

有人好奇:逗号表达式有什么用?看下下面的代码就知道了。

// Input
"World" |> `Hello, ${#}!` |> alert(#);

// output
var _ref, _ref2;
(_ref2 = ((_ref = "World"), `Hello, ${_ref}!`)), alert(_ref2);

2021-08-05[类库]

在上一家公司工作的时候,我负责开发公司的 ab test 系统。说实话,我们的功能极其简单。尽管如此,这个功能也花费了我们大量的时间去设计,实现,调试,发布。

easy-abtest 正如它的名字一样,是一个使用极为简单的 abtest 框架。

有多简单呢?我们来看下。

首先是定义变量,以及权重等配置。

const abtest = require("easy-abtest");
let options = {
  enabled: true,
  name: "experiment-ID-here",
  buckets: [
    { variant: 0, weight: 0.4 },
    { variant: 1, weight: 0.6 },
  ],
};
app.use(abtest(options));

字段含义参考官方文档

接下来就是使用了。经过上面的配置,你就可以在业务代码拿到之前定义的变量。比如上面的配置,你就有 40% 的请求拿到 variant 为 1,60% 请求拿到 variant 为 2。

这个数据默认是挂在 req.session.test 上的。

if (req.session.test.bucket == 0) {
  return res.render("index"); // 40%
} else if (req.session.test.bucket == 1) {
  return res.render("index-new"); // 60%
}

这是一个刚刚发布不到一个月的产品,代码只有 100 行左右(加上测试用例代码差不多 200 行),不太建议直接在生产环境使用。

地址:https://github.com/darshanbib/easy-abtest

2021-08-04[技巧]

已知一个环,比如环的长度为 n,环的编号是 [0,n-1],那么 n - 1 的下一个位置 0。

给定起始位置 pos 和环长度 n,让你求走 x 步之后, pos 的位置。x 为正数表示编号增加,x 为负数,表示编号减少。

我们可以分情况讨论:

  • 如果 x 大于 0,那么下个坐标 nxt = (pos+x)%n

  • 如果 x 小于 0,那么下个坐标 nxt = pos+x+n*((pos+x)/n)

组合起来就是 nxt = ((pos + x)%n+n)%n。

2021-08-03[好文]

RPC 是什么?自己如何实现 RPC?实现 RPC 需要考虑什么内容?听字节跳动 web infra 团队大佬娓娓道来。

https://mp.weixin.qq.com/s/Ky6SoWJv85orqYioihTRqg

2021-08-02[类库]

folio 是微软出品的测试框架。它的 fixture 设计我很喜欢,通过这个功能可以实现很多其他测试框架不那么容易实现的功能,值得大家尝试。

比如测试的时候我依赖了 express 服务器,并且我想启动多个进程并发地进行测试。

大家知道 express 服务需要绑定端口提供服务,那么端口号怎么填呢?

基于 folio 的 fixture 设计,我们可以这面使用:

// express.spec.ts
import test from "./express-test";
import fetch from "node-fetch";

test("fetch 1", async ({ port }) => {
  const result = await fetch(`http://localhost:${port}/1`);
  test.expect(await result.text()).toBe("Hello World 1!");
});

test("fetch 2", async ({ port }) => {
  const result = await fetch(`http://localhost:${port}/2`);
  test.expect(await result.text()).toBe("Hello World 2!");
});

port 需要实现注册,关于如何注册可以查看官方文档。

地址:https://github.com/microsoft/folio

2021-08-01[仓库]

当你试图对一个 npm 库做修改,一个常见的方法是

  1. 新建一个不同的名字的库,在这个新的库里你复制原有的代码并做修改。

  2. 修改依赖,引用新的被修改的库的名字。

这很不方便,且不利于追踪(比如如何查看改了什么功能?)。

patch-package 就解决了这个问题。使用方式也非常简单:

# fix a bug in one of your dependencies
vim node_modules/some-package/brokenFile.js

# run patch-package to create a .patch file
npx patch-package some-package

# commit the patch file to share the fix with your team
git add patches/some-package+3.14.15.patch
git commit -m "fix brokenFile.js in some-package"

地址:https://github.com/ds300/patch-package#readme

关注我

我重新整理了下自己的公众号,并且我还给它换了一个名字脑洞前端,它是一个帮助你打开大前端新世界大门的钥匙 🔑,在这里你可以听到新奇的观点,看到一些技术尝新,还会收到系统性总结和思考。

在这里我会尽量通过图的形式来阐述一些概念和逻辑,帮助大家快速理解,图解是我的目标。

之后我的文章会同步到微信公众号 脑洞前端 ,你可以关注获取最新的文章,并和我进行交流。

另外你可以回复大前端进大前端微信交流群, 回复 leetcode 拉你进 leetcode 微信群,如果想加入 qq 群,请回复 qq。

Last updated