My Personal Blog

Published on

开拓视野-技术周刊

Authors
  • avatar
    Name
    Tian Haipeng

1.Bun 1.0 正式发布

9 月 8 日,前端运行时 Bun 1.0 正式发布,如今,Bun 已经稳定并且适用于生产环境。Bun 不仅是一个专注性能与开发者体验的全新 JavaScript 运行时,还是一个快速的、全能的工具包,可用于运行、构建、测试和调试 JavaScript 和 TypeScript 代码,无论是从单个文件还是完整的全栈应用。

2022 年,Bun 发布,随即爆火,成为年度最火的前端项目:

Bun 不仅仅是一个运行时。它也是:

一个包管理器 (类似 Yarn、 NPM、 PNPM) 一个构建工具 (类似 Webpack、 ESBuild、 Parcel) 一个测试运行器 ...

所以 Bun 可以通过读取 package.json 来安装依赖项。Bun 还可以运行脚本。不管它做什么都比其他工具更快。Bun 在 JavaScript 生态系统的许多方面都有新的尝试,其中的重点是性能。它优先支持标准的 Web API,如 Fetch。它也支持许多 Node.js APIs,使其能与大多数 NPM 包兼容。

与 Node.js 兼容

Bun 是可以直接替代 Node.js 的。这意味着现有的 Node.js 应用和 npm 包可以在 Bun 中正常工作。Bun 内置了对 Node.js API 的支持,包括:

  • 内置模块,如fspathnet
  • 全局对象,如__dirnameprocess
  • Node.js 模块解析算法(例如node_modules

尽管与 Node.js 完全兼容是不可能的,特别是一些依赖于 v8 版本的特性,但 Bun 几乎可以运行任何现有的 Node.js 应用。

Bun 经过了与最受欢迎的 Node.js 包的兼容性测试,支持与 Express、Koa、Hapi 等服务端框架以及其他流行的全栈框架的无缝集成。开发者可以放心地在 Bun 中使用这些库和框架,并享受到更好的开发体验。

速度

Bun 的速度非常快,启动速度比 Node.js 快 4 倍。当运行 TypeScript 文件时,这种差异会更加明显,因为在 Node.js 中运行 TypeScript 文件需要先进行转译才能运行。

Bun 使用的是 Apple 的 WebKit 引擎,而不是像 Node.js 和其他运行时一样使用 Google 的 V8 引擎。WebKit 引擎是 Safari 浏览器的核心引擎,每天被数十亿的设备使用。它经过了长时间的实际应用和测试,具备快速和高效的特性。

TypeScript 和 JSX 支持

Bun 内置了 JavaScript 转译器,因此可以运行 JavaScript、TypeScript 甚至 JSX/TSX 文件,无需任何依赖。

// 运行 TS 文件
bun index.ts

// 运行 JSX/TSX 文件
bun index.tsx

ESM 和 CommonJS 兼容

从 CommonJS 到 ES 模块的过渡一直是缓慢而充满挑战的。在引入 ESM 之后,Node.js 花了 5 年时间才在没有--experimental-modules标志的情况下支持它。尽管如此,生态系统仍然充斥着 CommonJS。

Bun 同时支持这两种模块系统。无论是使用 CommonJS 的.js扩展名、.cjs扩展名,还是使用 ES 模块的.mjs扩展名,Bun 都会进行正确的解析和执行,而无需额外的配置。

甚至可以在同一个文件中同时使用importrequire()

import lodash from 'lodash'
const _ = require('underscore')

热重载

Bun 提供了热重载功能,可以在开发过程中实现文件的自动重新加载。只需在运行 Bun 时加上--hot参数,当文件发生变化时,Bun 就会自动重新加载你的应用,从而提高开发效率。

bun --hot server.tsbun --hot server.ts

与像nodemon这样完全重新启动整个进程的工具不同,Bun 在重新加载代码时不会终止旧进程。这意味着 HTTP 和 WebSocket 连接不会断开,并且状态不会丢失。

安装速度

Bun 的安装速度比 npm、yarn 和 pnpm 快好几个数量级。它利用全局模块缓存来避免从 npm 注册表中重复下载,并使用每个操作系统上最快速的系统调用。

Bun:可以做更多事

Bun 在 macOS 和 Linux 上提供了原生构建支持,但 Windows 一直是一个明显的缺失。以前,在 Windows 上运行 Bun 需要安装 Windows 子系统来运行 Linux 系统,但现在不再需要。

Bun 首次发布了一个实验性的、专为 Windows 平台的本地版本的 Bun。这意味着 Windows 用户现在可以直接在其操作系统上使用 Bun,而无需额外的配置。

2.Node.js 16 EOL

EOL(end of life)

2023 年 9 月 11 日,Node.js 16 将停止维护,推荐大家切换到 Node.js 18 使用(EOL 2025-04-30)

官推下面很多都在推荐 Bun 了 😄

3.New in Chrome 117

添加了Local overrides 功能,支持直接修改请求的响应内容(前段时间发布了支持修改响应头的功能)

要覆盖 Web 内容,请打开**“网络”面板,右键单击请求,然后选择“覆盖内容”**。

如果您设置了本地覆盖但被禁用,DevTools 会启用它们。如果您尚未设置它们,DevTools 会在顶部的操作栏中提示您。选择一个文件夹来存储覆盖并允许 DevTools 访问它。

被覆盖的资源已保存。在**“网络”**面板中用 指示。将鼠标悬停在图标上可查看被覆盖的内容。

一些简单场景的修改,可以直接在浏览器中完成,不需要借助插件和代理工具了 🎉

不过如果请求带类似时间戳的动态参数的话,这个就不太用了

4.lodash 从 Node 迁移至 Bun

沉寂 2 年准备重新开始发力了,作者准备 3 步重构 lodash,V5 版本

  1. 仓库关闭原来所有的 issue 和 PR
  2. 切换到 TypeScript
  3. 切换到 Bun

5.有意思的网格下落渐次加载效果

还原布局结构

首先,我们需要大致还原布局结构,这个并非整个动画的核心。

整个动画的核心在于元素按顺序(又带点随机的效果)从高处下落渐次进行下落加载填充动画

当然,还原这个布局也非常简单,这里我们借助 flex 布局快速实现,几个关键点:

  1. 每个 flex-item 宽度不固定:这一点可以使用 SASS 函数进行模拟,随机生成不同宽度的 flex-item
  2. 每个 flex-item 背景色随机:这一点同样也可以借助 SASS 函数 实现
  3. 整体水平居中:这个也简单,父容器添加 justify-content: center; 即可

这样,整个布局的大致代码如下:

<ul>
  <li></li>
  <li></li>
   // ... 假设一共 50 个 li
  <li></li>
</ul>
$count: 51;
@function randomNum($max, $min: 0, $u: 1) {
    @return ($min + random($max)) * $u;
}
@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}

ul {
    display: flex;
    gap: 4px;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    width: 640px;
    height: 420px;
}
li {
    flex-shrink: 0;
    height: 30px;
    border-radius: 30px;
}

@for $i from 1 to $count {
    li:nth-child(#{$i}) {
        width: #{randomNum(110, 90)}px;
        background: randomColor();
    }
}

简单解释一下:

  1. 利用了 SASS 的循环函数简化代码量
  2. 实现了两个 SASS 函数,利用这两个函数随机生成不同宽度不同颜色的 li
  • randomNum(): 用于生成范围内的随机数
  • randomColor(): 用于生成随机颜色值

下落动画

接下来,我们来实现元素的下落动画。

首先,我们撇开多元素的按顺序又带点随机的延迟下落,值聚焦于单个 item 的下落动画

整个动画的核心步骤大致是:

  1. 默认是状态下,元素是在最终的 flex 布局状态下,且是可见状态
  2. 动画开始时,元素将消失,然后从上方,在一个缩小状态下,有一个小幅度向上运动
  3. 接着元素向下运动到目标位置(终止状态)
  4. 元素从缩小状态,放大为正常状态
  5. 并且,动画结束后,需要维持在最后一帧,因此需要使用(animation-fill-mode: forwards

完成上面的拆解后,单个动画实现起来就非常轻松了:

li {
    opacity: 0;

    &hover {
            animation: falldown 1s forwards;
    }
}

@keyframes falldown {
    0% {
        transform: translateY(-180px) scaleX(.1) scaleY(.3);
        opacity: 1;
    }
    20% {
        transform: translateY(-200px) scaleX(.6) scaleY(.3);
    }
    75% {
        transform: translateY(0) scaleX(.6) scaleY(.3);
    }
    100% {
        transform: translateY(0)  scaleX(1) scaleY(1);
        opacity: 1;
    }
}

实现延迟随机下落

当然,到这里,整个动画都还是平平无奇的

我们需要最后的点睛之笔,实现按顺序又带点随机的延迟下落效果,以及让整体的动画更加自然。

这里的核心就在于:

  1. 利用 animation-delay 制造延迟效果,但是不能是顺序延迟,需要带点随机效果
  2. 利用 animation-timing-function 缓动函数,控制动画的速度曲线,使动画变化更为平滑
  3. 控制缩短每一个 item 的动画时长

方法明确了,剩下的就是调试动画效果了,最终,经过一番调试,完整的动画效果的代码就完成啦。

代码量真的不多:

$count: 51;
@function randomNum($max, $min: 0, $u: 1) {
    @return ($min + random($max)) * $u;
}
@function randomColor() {
    @return rgb(randomNum(255), randomNum(255), randomNum(255));
}

ul {
    display: flex;
    gap: 4px;
    flex-direction: row;
    flex-wrap: wrap;
    justify-content: center;
    width: 660px;
    height: 420px;
}
li {
    flex-shrink: 0;
    height: 30px;
    border-radius: 30px;
}

@for $i from 1 to $count {
    li:nth-child(#{$i}) {
        width: #{randomNum(110, 90)}px;
        background: randomColor();
    }
}

ul:hover {
    li {
        opacity: 0;
    }
    @for $i from 1 to $count {
        li:nth-child(#{$i}) {
            animation: falldown .3s cubic-bezier(.44,.02,.65,1.3) #{50 * ($count - $i) + (random(150) - random(300))}ms forwards;
        }
    }
}
@keyframes falldown {
    0% {
        transform: translateY(-180px) scaleX(.1) scaleY(.3);
        opacity: 1;
    }
    20% {
        transform: translateY(-200px) scaleX(.6) scaleY(.3);
    }
    75% {
        transform: translateY(0) scaleX(.6) scaleY(.3);
    }
    100% {
        transform: translateY(0)  scaleX(1) scaleY(1);
        opacity: 1;
    }
}

核心,就在于这一句,animation: falldown .3s cubic-bezier(.44,.02,.65,1.3) #{50 * ($count - $i) + (random(150) - random(300))}ms forwards,需要好好的消化理解。

完整的代码你可以戳这里:

CodePen Demo -- Flex Item Fall Down