半吊子全栈开发者的日常

极空间与 QNAP NAS 实现共享 NUT UPS

我有三台 NAS,Synology 群晖、QNAP 威联通和 ZSpace 极空间,前者放在出租屋里作为主力,后两台放在老家作为备份。

因为极空间是 arm64 版本双盘位的,功耗不高,所以和 QNAP 共用一台 UPS 就好了。之前折腾了一下,让极空间作为 Master 通过 USB 连接 UPS,然后 QNAP 作为 Slave 通过 NUT (Network UPS Tools) 局域网连接。

不过因为涉及到系统文件改动,每次极空间系统升级后都需要重新操作一遍,每次我都会忘记要怎么捣鼓……所以写篇博客记录下。

话说 2025 年居然一篇博客都没写,工作太忙了呀,而且总是犯懒。以前上学的时候写博客,不怎么理解那些断更的博主,现在可以体会到那种感觉了……草稿倒是堆了很多,希望明年可以发出来吧!

> READ MORE...

重构博客友链页面 & 友链朋友圈开源

先来看看效果:友情链接 - PRIN BLOG

自我感觉还是不错的,友链的博客们有什么更新都可以实时展示在页面上,一目了然。作为博主,不用打开 RSS 阅读器就可以查看新文章;作为访客,也可以快速找到更多自己感兴趣的内容,比起原来全是链接的页面,看起来也让人更有点击欲望了。

从临时起意到开发完成总共两个晚上,最速传说就是我!(误)

> READ MORE...

真的不可以在 React 组件内部嵌套定义子组件吗?

最近在 Code Review 时,看到有同事写了这样的代码:

function TodoList() {
  const [list, setList] = useState([]);

  const TodoItem = useCallback((props) => {
    return <li>{props.text}</li>;
  }, []);

  return <ul>{list.map((item, index) => <TodoItem key={index} text={item} />)}</ul>;
}

有经验的 React 开发者肯定一下子就看出问题了:在组件内部嵌套定义组件,会导致子组件每次都重新挂载。因为每次渲染时,创建的函数组件其实都是不同的对象。

但是他又有包了 useCallback 让引用保持一致,好像又没什么问题……?

这波骚操作让我突然有点拿不准了,所以今天咱们一起来验证一下,用 useMemo 或者 useCallback 包裹嵌套定义的子组件,对 React 渲染会有什么影响。以及如果有影响,应该如何用更合适的方法重构。

> READ MORE...

使用 TikZ 在 Hexo 博客中愉快地画图

一转眼就到 2024 年了!大家新年快乐!

前段时间在写文章时,需要一些配图,于是就使用了 TikZ 来绘制。TikZ 是一个强大的 宏包,可以使用代码的形式绘制出各种各样精美的矢量图。

xf(x)f(x)=xf(x)=sinxf(x)=120exA0B0ABC0D0CDf0ag0h0bfhk0cdkg

如果你的阅读器看不到上面的 SVG 格式图片,可以点这里查看 PNG 格式。 example-tikz-graph

上面的图对应的 TikZ 代码可以在这里找到。然而画是画爽了,想把它贴到博客里时却犯了难——目前竟然没有什么好办法可以直接在博客里使用 TikZ!

> READ MORE...

详解 PixiJS Filter 中的参数与坐标系

除草啦除草啦,再不更新博客就要变成热带雨林啦!🌿

最近在给一个 PixiJS 程序编写 WebGL Shader,被各种参数和坐标系搞得晕头转向。痛定思痛,整理了一下 PixiJS Filter 系统中的各种概念,以供后续参阅。

在 WebGL 中,我们可以通过编写顶点着色器 (Vertex Shader) 和片元着色器 (Fragment Shader) 来实现各种各样的渲染效果。而在 PixiJS 中,渲染引擎为我们屏蔽了绝大多数的底层实现,通常情况下用户是不需要自己调用 WebGL API 的。如果有编写自定义着色器代码的需求,一般是使用 Filter 来实现。

> READ MORE...

逆向拼多多上的「关灯神器」,实现蓝牙遥控开关灯

依稀记得以前在某个友链博主那边看到过一篇文章,讲的是因为他们寝室所有人都懒得下床关灯,所以就用树莓派和舵机做了个远程遥控关灯的小玩意儿,当时我就感叹,果然懒才是第一生产力。

自从今年初开始出来租房住,突然就感觉睡前关灯变得好麻烦好麻烦。我的房间里是有好几盏灯的,床头的开关只能控制其中的两盏,剩下的开关在另一个地方,另外还有一个总开关位于进门的门厅处。于是我就陷入了两难之境:

  • 不用总开关:每天睡前把灯一一关掉,第二天回家又得一一开回来;
  • 直接用总开关:开关离床太远,关完灯要摸黑上床,早上起来又得先过去开灯。

不爽,太不爽了!现在都讲究智能家居,我这他喵的是智障家居啊……

> READ MORE...

在 M1 Mac 上运行 macOS 虚拟机

Apple M1 芯片问世一年有余,时至今日,在 M1 Mac 上运行 Windows、Linux 虚拟机的方法都已经比较成熟了。然而 macOS 本身的虚拟化却并非如此:直到 Monterey 发布,于 M1 Mac 上运行 macOS 虚拟机才成为可能。

最近有几个小实验需要在 macOS 虚拟机上跑,本来以为去 Parallels Desktop 上开一个就完事了,搜了一下才发现,其实事情没那么简单……实际配置过程中也是踩了几个坑,所以顺带记录一下。

> READ MORE...

GitHub 全家桶:Actions 自动构建多架构 Docker 镜像并上传至 Packages (ghcr.io)

前段时间把 GitHub 的用户名修改成了 @prinsss,准备把其他地方的账号也修改一下的时候,却发现 Docker Hub 的 username 不能改,只能砍掉重练(npm 也是)。

想想反正我 Docker Hub 上也没上传什么东西,不如就用 GitHub 自家的 Container registry 来托管镜像吧!

这里有个小插曲:其实我挺早之前就想要改名了,但当时在忙秋招,考虑到改名后可能会有一些后续要处理(擦屁股),所以只是创建了一个 organization 把名字占住,等有时间了再正式改名。然而后来我把组织删了,想要修改 GitHub 账户的用户名时,却提示 prinsss 这个名称 unavailable(我确定它是没被占用的,因为我还能再用这个名字创建组织),不知道是不是触发了内部的什么保留机制。

最后还是发工单找客服解决了,而且等了一个多星期才回复,也是挺无语的。原来的 printempw 这个名字我也保留了,所以 printempw.github.io 这个域名还是可以访问的,目前是两边同步更新,后续再慢慢迁移。

> READ MORE...

使用 ESLint + Prettier + Commitlint 规范代码风格与提交流程

最近因为课程需要开了几个多人协作的新项目,感觉有必要在团队中强制一下代码规范,免得提交上来的东西对 leader 血压不好。前后端都是 TypeScript 的,所以就用流行的 ESLint + Prettier 组合拳(配合 Standard 规范),EditorConfig 同步编辑器配置,再加上 commitlint 规范提交信息,最后用 Git Hooks 实现自动化检查。

配置虽然不难,但还是有点繁琐的,所以记录一下,如果忘了下次可以翻回来看。

> READ MORE...

使用国内镜像加速 Laravel Sail 构建

Laravel Sail 是什么?简单来说就是一个基于 Docker 的开发环境。其核心就是一个 docker-compose.yml 配置文件和 sail 脚本,定义了 PHP、MySQL、Redis 等一系列容器,然后把程序放里面跑。

至于好处嘛,主要就是使用方便、运行环境统一、不会弄乱系统。同样是 Laravel 开发,本机安装 LNMP、Valet、Homestead 这些方法我都用过,但现在我肯定首选 Laravel Sail(容器化是真滴爽)。

不过 Laravel Sail 好是挺好,想要在墙内顺利使用还是要费点功夫的。

> READ MORE...