用 Proxy 和 WeakMap 实现一个类似 @vueuse 的 util 方法
在使用 Vueuse 时,我发现一个很好用的方法[util](https://vueuse.org/shared/until/)。 该方法的作用是监听某个响应式变量,阻塞当前方法直到该变量符合要求。 调用形式如下: ```ts // will be resolve until ref.value === true or 1000ms passed await until(ref).toBe(true, { timeout: 1000 }) ``` 这个方法可以解决许多工程难题,比如双 token 方案中,用户一次触发了多个请求,在第一个请求处执行 refreshToken 方
错误和异常
# 错误和异常 错误和异常是实践中诞生的概念,目的都是为了处理「程序无法正常运行的情况」。 ## 错误 从代码形式上讲,错误倾向于精确的手动处理。 比如 fnA 方法调用了 fnB 和 fnC。这两个方法都有可能发生错误,处理代码大概就是下面这样: ```js function fnA() { const { err: bErr, res: bRes } = fnB() if (bErr) { // ... // 错误处理 } const { err: cErr, res: cRes } = fnC() if (cErr) { // .
如何在 React 中使用 async-await
我一直是个 Vue 用户,最近才开始使用 React,希望下面的内容可以帮到和我一样对函数式组件感到困惑的人。 ## Suspanse 首先,在 React 中以下写法是无效的: ```tsx async function Child() { const data = await fetchData() return <div>{data}</div> } function Parent() { return ( <Suspanse fallback={<div>loading</div>}> <Child /> </Suspanse>
如何实现一个在线 mock 服务
有不少 SaaS 服务提供了在线 mock 服务,比如 Apifox、Insomnia,不过他们首先是一个 API 设计工具,其次才是 mock 服务。 如果你只是要为 demo 提供接口,或者在后端完成工作前创建假数据,那他们的工具太重了。 更重要的是他们只会为商务用户提供 self-host 服务,对于普通开发者并不是很友好。 接下来我会介绍如何使用 Node.js、MongoDB、Faker.js 实现一个自己的在线 mock 服务。 > 你可以在[https://github.com/Ray-D-Song/faker-server](https://github.c
TypeScript interface 隐式索引签名丢失问题
最近遇到一个奇怪的问题,interface 定义了一个符合要求的类型,却无法作为泛型参数。 ```ts type Foo = Record<string, unknown> type Test<K extends Foo> = K interface Bar { 'a': string } /** * error: * Type 'Bar' does not satisfy the constraint 'Foo'. * Index signature for type 'string' is missing in type 'Bar'. */ type Res = Te
使用Enigma Virtual Box将 exe 和 dll 打包成单个可执行文件
在 macOS 和 Linux 上,大多数工具都会以单个可执行文件的形式分发。Windows 平台有时会附带`.dll`文件。 ## dll 是什么 DLL文件是“动态链接库”(Dynamic Link Library)的缩写,主要用于Windows操作系统。 DLL文件包含了一些可以被多个程序共享的代码和数据。当一个程序需要使用这些代码和数据时,它会动态地加载相应的DLL文件,而不是将这些代码和数据复制到每个程序中。这样可以节省内存空间,并且可以确保多个程序使用的是同一份代码和数据,从而提高系统的稳定性和安全性。 可以将 DLL 简单理解为`库`或者`包`。 举个例子,
使用 Continue 部署免费的 AI 代码助手
过去的一年, 我一直在使用 GitHub Copilot 作为代码助手, 它提供了补全、问答等功能, 付费订阅 10 美元/月. 说实话这个价格并不算贵, 但最近 Copilot 对问答范围进行了限制, 导致很多与开发相关的问题无法得到解答. 后续我也尝试了 Codium AI, 响应速度不尽人意. 最近发现了一个开源的代码助手 [Continue](https://www.continue.dev/), 支持调用本地和云端的模型, 包括 Cloudflare 的 worker AI. ## 介绍 Continue 本质是个帮你向大模型发起请求的客户端. 当你编写
nginx 配置 https
self-host 系列文章, 讲述如何自己搭建服务. ## 什么是 HTTPS HTTPS 是 HTTP 的安全版本, 通过加密通信内容, 防止[中间人攻击](https://zh.wikipedia.org/wiki/%E4%B8%AD%E9%97%B4%E4%BA%BA%E6%94%BB%E5%87%BB), 保证数据传输的安全性. > 中间人攻击可以简单理解为, 有人篡改了服务端发送给你, 或者是你发送给服务端的数据. HTTPS 约定了使用 443 端口, 通过 SSL/TLS 协议进行通信. 最常见的应用部署方法是使用 Nginx 作为反向代理服务器, 监
使用 Docker 容器进行前端开发
最近要改一个老项目, vue2 和 node.js14. 我现在使用的 runtime 版本管理器是[asdf](https://asdf-vm.com/), m2 macOS 安装 v14 的 node.js 是从源码构建. 灾难开始了, 编译 node.js 12 需要 python2.7 或 3.9, macOS 系统自带的 python 版本是 3.12. 然后我又去用 asdf 编译 2.7.18 的 python. 正当我满心欢喜觉得可以使用的时候, 编译失败了! ![build fail](https://r2.ray-d-song.com/2024/0
Mac 关闭 SIP 并删除自带 ABC 输入法
Mac 装机自带 ABC 和中文输入, 但可用性不是很强, 例如很多开发者需要在编辑器的中文输入法下使用英文符号, 在 Mac 下只有搜狗输入法还行. 但 Mac 在开启`SIP(系统完整性保护)`时无法将系统自带全部移除, 输入法经常会从搜狗切到 ABC, 很麻烦. ## 关闭 SIP 终端输入 ```bash csrutil status # 如果已关闭会显示: System Integrity Protection status: disabled. # 未关闭显示: System Integrity Protection status: enabled. ``` 后续步骤:
npm 版本号和版本控制详解
## 语义化版本控制 最近在拆分公司的 MonoRepo 仓库, 分割一部分内容成为新的 npm package, 发现公司之前的发布版本控制并不是很规范. npm 遵循的是[语义化版本控制(semantic versioning)](https://semver.org/), 其结构为: `主版本号.次版本号.修订号` 三种版本号定义分别是: * 不兼容的更新 * 向下兼容的功能性更新 * 向下兼容的问题修正 除此以外还可以在修订号后面加上先行版本号(通过`-`连接)和版本编译信息(通过`+`连接). 例如 `1.0.3-rc.1+exp.sha.5114f85` 表示:
vscode 如何 debug 前端项目
## 基础 vscode 的 debug 使用项目根目录下的`.vscode/launch.json`文件进行配置. 首次运行 debug, vscode 会创建一个默认的配置文件. ```json { // For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387 "version": "0.2.0", "configurations": [ { // 调试器类型 "type": "chrome", // 请求类型, launch
用 Mitosis 同时构建 React 和 Vue 组件
上次写了个[UnoCSS icon 选择器](/zh-cn/blog/unocss-icon-viewer), 希望写个库可以同时在 React 和 Vue 中使用. 首先想到的是 Web Component. 但缺点是在核心逻辑之外需要针对 Vue 和 React 分别编写一套适配代码. 对于一些比较小的需求, 写适配代码的成本可能比人工适配还要高. 然后我就发现了`Mitosis`这邪门东西. Mitosis 的中文是`有丝分裂`, 顾名思义, 它可以将组件编译成多个框架的代码, 包括 React, Vue, Qwik, Solid, Angular, Svelte.
如何创建一个 UnoCSS icon 选择器
import UnoCSSIconViewer from '@/components/UnoCSSIconViewer.vue' export const iconName = 'iconName' 效果展示: <UnoCSSIconViewer /> UnoCSS Icon 的使用方法是在标签上添加`i-`开头的 icon 名, 例如 `<div class="i-mdi-access-point" />` 就会渲染 <div class="w-full flex justify-center"> <div class="i-mdi-access-point w-25px
Vue 宏编译: 以 defineProps 为例
Vue macro(宏) 随着`<script setup>`写法一同引入 Vue 生态, 进一步丰富了 Vue 在编译期的想象力. 本文主要分析 Vue defineProps 的 type-only 写法是如何根据类型信息生成运行时代码. 我们先拉取 Vue 的源代码, 并切换到3.0.3版本, 这是最早引入 script setup 和 defineProps macro 的版本. Vue 的 script setup 编译器源码位于`packages/compiler-sfc/src/compileScript.ts`, 接下来所有的代码都出自这个文件 为了方便查看
Vue 使用 Vitest 进行单元测试
# 单元测试的定义 > 本文源码: https://github.com/Ray-D-Song/vitest-tutorial-sourcecode > 单元测试(英语:Unit Testing)又称为模块测试 [来源请求] ,是针对程序模块(软件设计的最小单位)来进行正确性检验的测试工作。程序单元是应用的最小可测试部件。在过程化编程中,一个单元就是单个程序、函数、过程等;对于面向对象编程,最小单元就是方法,包括基类(超类)、抽象类、或者派生类(子类)中的方法。 ———wiki 在一个典型的 Vue 项目中, 我们经常需要进行单元测试的模块包括以下几种: * hooks * 工具
cloudflare worker/D1 初探
# 创建项目 如果是第一次使用 worker 服务, 需要登录一下 ```bash npx wrangler login ``` 通过命令行交互创建一个名为 event-tracking 的项目 ```bash npm create cloudflare@latest event-tracking ``` 项目创建完成后有两个关键的文件, `src/index.ts` 是 worker 的入口, `wrangler.toml` 是总的配置文件. 进入 dev01 目录, 执行命令创建数据库 ```bash npx wrangler d1 create event-tracking-db `
TailwindCSS 的价值
tailwind 一直饱受非议, 其中说的最多的大概就是「我为什么不直接写内联样式?」. 其实 tailwind 不仅是简写了样式名这么简单, 它是一系列便利的封装. # 动画 举个简单的例子, `animate-spin` 属性用于添加旋转动画, 常用在 loading 中. 如果你用传统的 css/sass 编写, 那你至少需要以下代码. ```css animation: spin 1s linear infinite; @keyframes spin { from { transform: rotate(0deg); } to { transform: r
协程(Coroutine)和纤程(Fiber)
最近在看 C++ 引入 Fiber 的[N4024文档: 区分纤程和协程](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2014/n4024.pdf), 文章给纤程和协程十分明确的区分. 但过去我看过的很多资料会将其混为一谈或者模糊二者的边界, 所以写了这篇博客来总结一下. # 纤程 线程是一种轻量级的线程, 本质是对线程时间进行切片处理, 调度也由用户进行. 最早是 Microsoft 为了解决 Unix 平台的引用程序移植到 Windows 上时出现的问题而发起的提案. 因此, 纤程是一种偏底层的概念, 通常由操作系统或runti
单线程并发
> 本文封面和思路来源于 Ruby China 2021 By 东仙队长的分享: [Ruby 高并发编程指北](https://www.bilibili.com/video/BV1h3411v7kq/?spm_id_from=333.999.0.0&vd_source=371668a779fa4a755fcbf62901a22d71) # 并发 假设有一个处理器, 因为只有一个核心, 所以同时他只能运行一个进程, 又因为一个进程上同一时间只能运行一个线程(task). 所以你可以认为, 同一时间, 这颗处理器只能处理一个任务. 操作系统会将`cpu 使用时间`这一资源进行切分, 这就是`时