zhbaor's Moments

让我们组建一支乐队,一起来超越我们的偶像吧!

Mar 26th
2023

最近帮助一图流升级网站。把技术应用在真实的网站上,真是种前所未有的体验。

我遇到的第一个问题,是打包相关的。一图流的网站用 CDN,按流量计费,非常烧钱。最初观察到后端接口返回的 json 的体积很大,于是启用了 gzip 压缩。然后是图片,从 png 改为 webp 有损压缩,手动调整参数,在看起来不糊的条件下尽量减小体积。

于是只剩下 js 了。最初没有将 js 分页面打包,还把 Element UI 放到了单独的文件里。尽管首页上只用了一小部分 Element UI 的组件,但在访问首页时,还是要把其它页面用到的 Element UI 的代码都下载下来。ECharts 没有使用 npm 安装,而是把它的 js 放在 static 目录下。网站的 js,一大半都是 Element UI 和 ECharts,就觉得“钱白花了”。

网站用的是 Nuxt 2 框架。我以前没有接触过这个框架,在网上搜索打包相关的内容,又看了文档,然而一无所获。以前 Vite 用惯了,看 Nuxt 2 启动开发服务器都要好久,非常不爽。索性新建项目,尝试把代码迁移到 Vite + Vue 3 + Element Plus。出乎意料的是,迁移过程非常顺利,代码几乎不用改就能跑起来。我用 vue-router 实现了分页打包的功能。装了两个插件,一个可视化地分析 js 产物,另一个能够将库从产物中排除。我把 Vue、Router、Element Plus、ECharts 等库都排除掉,在 html 里通过 CDN 引入,这样产物体积就小很多了。

下一步是 SSR。原先使用 Nuxt 2 时,并没有充分利用 SSR,页面上的数据,都是在 mounted() 中下载的,这也是需要改进的地方。我尝试安装了 vite-plugin-ssr,参照文档和示例代码,成功跑通了。对不同页面,分别采用不同的渲染策略:首页和礼包页面以数据展示为主,所以用服务端渲染;攒抽计算器和基建排班器以交互为主,加载又很慢,于是干脆用 SPA,这样页面出现时就立即能交互。然而,攒抽计算器加载很快,如果用 SSR,用户注意不到加载 js 的时间,用 SPA 反而会产生页面加载很慢的错觉。基建排班器加载却很慢,页面出现后要等很久才能交互,如果用 SSR,反而体验不好,有种网页坏了的感觉。所以攒抽页面用 SSR,基建页面用 SPA。最后是路由,出于简单起见,用 vite-plugin-ssr 的服务端路由,不再使用 vue-router。

加了 SSR 后,在打包时也要区分服务端和客户端。按照上面的做法,将一些库从客户端的打包产物中排除,在 html 里通过 CDN 引入;在服务端则不必这样做。好在 Vite 足够灵活,能够满足这样的需求。接着又重写了导航栏。原来的导航栏用的是 El-Menu,这个组件有几个缺点:不能右键,在新选项卡中打开、只能在客户端渲染,不能在服务端渲染、不够灵活,不能加按钮或开关等其它组件。以往首页切换亮色和暗色的按钮,做成菜单项,不是个好办法。再加上导航栏比较简单,样式也是现成的,于是自己写了一个。

将新网站上线后,本以为万事大吉,不料接连有用户反馈打不开。现象是 html、css 和图片完全正常,但 js 却被某种神秘力量阻碍,无法运行。同时在 QQ 内置的浏览器里,有些地方的样式也不对。本以为是网络问题,但又不像。经过排查后发现,QQ 和微信内置的浏览器不能识别 8 位 16 进制格式的颜色,只能用 rgba 格式,调整打包选项,就解决了这个问题。但是,js 依旧无法运行,毫无头绪。

某日,无意间看 nginx 的日志,发现一位有问题的用户,用的浏览器很老,User Agent 包含 Chrome/79 字样。再结合他的手机型号的发布时间,可以推断:他使用的小米浏览器虽然版本很新,但是它调用系统的 WebView。系统的 WebView 版本太老,不支持新的特性。我在手机上安装了 Chrome 79,果然有问题,不支持 ?? 运算符。于是改了打包设置,目标设为 es2015,顺利解决。顺便还学会了在电脑的 Chrome 上调试手机浏览器里的网页。

不料第二天,又有一名用户反馈网站打不开。这次不是手机了,而是在电脑上。一问,他用的是 2345 浏览器。2345 浏览器的内核是 Chromium 69,不支持 globalThis。搜索了一圈,通过 Polyfill.io 补上了这个功能。

然而第三天,又有一名用户反馈网站仍然打不开。他的系统 WebView 内核是 Chromium 61。本来以为会和上次一样顺利,不料 Chrome 61 不支持正则的 s 标志,Polyfill.io 也不包括这一功能。@vite/plugin-legacy 插件还和 vite-plugin-ssr 冲突。尝试在浏览器里直接引入 core-js 也没有成功。无奈只得放弃,劝他装个新版浏览器。

这样,一图流前端的迁移算是告一段落了。

09:46


Mar 7th
2023

为了这碟醋(100 首歌)包的饺子(B 站音频下载器)

Responsive image

11:44


Feb 18th
2023

最近想要自建语音聊天服务,以代替音质非常糟糕的 QQ 语音,于是发现了 Mumble(服务端叫 Murmur)。因为是在家中使用,所以没有把 Murmur 搭在 VPS 上,而是直接把它跑在笔记本上。Murmur 占用的内存很小,空闲时大概不到 30 MB。

Mumble 客户端上手很容易。首次启动软件时会运行向导,帮助调整声音相关的选项。Mumble 支持 PipeWire 后端,自带 Speex 和 RNNoise 两种降噪方式(可以关闭或选择一种,也可以同时开启),实际效果极佳。

安卓上有第三方客户端 Mumla

12:07


Jan 28th
2023

GNOME Terminal 不支持 OSC 52,于是我把终端换成了 Kitty。然而通过启动器或 Nemo 的菜单打开 NeoVim 或终端时,由于 GLib 的问题,Cinnamon 不会用 Kitty,还是会选择 GNOME Terminal。其实指定 Terminal=true 的程序都会受到影响。

按照 GLib Issue 338 的内容,GLib 2.76.0 会在最近几个月内新增 xdg-terminal-exec 的命令,以解决这个 12 年前提出的问题。不过在用上新版 GLib 前,还是得有临时解决方案:把 ~/.local/kitty.app/bin/kitty 软链接到 ~/bin/gnome-terminal,Cinnamon 就会调用 Kitty 了。

GNOME Terminal 运行程序,参数的格式为 gnome-terminal -- <command>。Kitty 可以接受相同格式的命令。但是比如 Alacritty,它接受的参数格式就与 GNOME Terminal 不一样。可以写一个脚本,转化一下参数:

 1#!/bin/bash
 2
 3while [[ $# -gt 0 ]]; do
 4  case $1 in
 5    --)
 6      shift
 7      break
 8      ;;
 9    *)
10      shift
11      ;;
12  esac
13done
14
15alacritty -e $@

赋予可执行权限,保存到 ~/bin/gnome-terminal,就可以了。

PS:用 Python 也挺短的:

 1#!/usr/bin/env python3
 2# -*- coding:utf-8 -*-
 3
 4import sys
 5import subprocess
 6
 7while len(sys.argv) > 0:
 8    if arg := sys.argv.pop(0) == "--":
 9        break
10
11subprocess.run(["alacritty", "-e"] + sys.argv)

17:42


Jan 22nd
2023

过年喽!

pictures
pictures

22:33


Jan 19th
2023

Distrobox 可以方便地运行其它发行版的程序。它支持 Podman 和 Docker,不仅可以运行命令行程序,还能直接跑 GUI 程序并使用显卡加速,声音、网络等等都没问题,甚至可以用来运行桌面环境(不过我没试过)。

我在安装 distrobox 时用的是 rootless 的方法,把 Podman 和 distrobox 安装到 ~/.local 下,改好 PATH,就可以使用了。

Distrobox 对我有很大的帮助:

一是 gamescope。Ubuntu 下的依赖太旧,没法编译新版的 gamescope,只能通过 ppa:ar-lex/gamescope 安装旧版。现在我参照 issue 451,用 Arch Linux 容器,终于用上了最新的 gamescope。

二是 wine-tkg。Debian/Ubuntu 的 32 位依赖总是有些问题,比如在 Ubuntu 22.04 下,32 和 64 位的 krb5-multidev 无法同时安装,所以 wine-tkg 不得不移除 Debian/Ubuntu 下 32 位的 krb5 支持。有了 distrobox,我通过 Arch Linux 容器使用 wine-tkg,就没有这个烦恼了。

pictures
pictures

10:46


Jan 8th
2023

以前写 QQ 机器人都是用 Python。从接触 NoneBot 到转去用 Ariadne,我逐渐发觉,Python 在构建 QQ 机器人时有天生的劣势:一是同步与异步混合非常麻烦,二是难以实现重载单个插件。于是放弃了框架、用 WebSocket 客户端直接连接 go-cqhttp,倒也省去了不少心智负担。

最近看到一个基于 Node.js 的 QQ 机器人框架——KiviBot。看了插件 API 文档,感觉真是简洁实用,不搞多账号、跨平台,而是清晰简明地把常用功能做好。

于是尝试部署。再次感叹当初选 AlmaLinux 8 非常明智,不必添加额外的软件源,一条命令(sudo dnf module install nodejs:18)就装好了 Node.js。

然后写插件试试。写了经典的“芜湖起飞”和 vnstat。体验只有一个字——“”!写好插件后,直接向机器人发送 /plugin on wuhu-takeoff/plugin reload vnstat,就能启用或重载相应的插件,特别方便。

pictures
pictures

09:04


Jan 6th
2023

打过了 1 难度的海沫!嘿嘿嘿……

用 Waydroid 玩明日方舟时,鼠标在基建和集成战略中不能拖动。Waydroid 提供了让鼠标模拟触摸的功能,还可以分应用设置。我参照文档进行设置时,却遇到了报错。我打开提示报错的文件一看,原来作者在十几个小时前的上一次提交中刚改过这块功能,但是不小心忘记把一处 helpers 对应地改成 tools.helpers 了。我把本地对应的文件 /usr/lib/waydroid/tools/actions/prop.py 一改,果然没问题了,于是提了 PR,很快就被合并了。

1waydroid prop set persist.waydroid.fake_touch "com.hypergryph.arknights"

用上面这行命令设置之后,在明日方舟的基建和集成战略中,就能用鼠标进行拖动了。

pictures
pictures

22:33


Jan 5th
2023

Spek 是一个声学频谱分析软件,可以用来鉴别无损音频。许久没有关注,Spek 还在不断更新,去年 7 月发布了 0.8.4 版本。记录一下编译安装的过程:

 1# 安装编译依赖
 2sudo apt install libwxgtk3.0-gtk3-dev wx-common libavcodec-dev libavformat-dev
 3
 4# 下载解压源码
 5wget https://github.com/alexkay/spek/releases/download/v0.8.4/spek-0.8.4.tar.xz
 6tar xvf spek-0.8.4.tar.xz
 7
 8# 编译
 9cd spek-0.8.4
10./configure
11make -j$(nproc)
12
13# 安装
14sudo make install
Responsive image

10:30


Jan 1st
2023

之前注意到中文标点符号的宽度不是很理想。连续出现的一些标点组合,应该缩短宽度;某些组合,比如右括号与句号,中间应当避免换行;而像逗号与引号的组合中间则应允许换行。

昨日经过一番试验,终于把标点符号的问题弄好了,还一并解决了中英文混合排版的间隙问题。

“他?……他景况也很不如意……”母亲说着,便向房外看,“这些人又来了。说是买木器,顺手也就随便拿走的,我得去看看。”

下午,他拣了好几件东西:两条长桌,四个椅子,一副香炉和烛台,一杆抬秤。他又要所有的草灰(我们这里煮饭是烧稻草的,那灰,可以做沙地的肥料),待我们启程的时候,他用船来载去。

标点压缩和间隙调整,不仅要用 CSS,也要用 JavaScript。

我总共研究了三套方案:

  1. 汉字标准格式:最新的 Release 在 2015 年。尝试直接加到主页上,不知道哪里的样式冲突了。
  2. hiugiak/cj-typo:需要字体支持 OpenType 的 halt 特性,因此背弃开源信仰,使用微软雅黑的 Windows 用户有难了。🙏🙏🙏 用 webfont 感觉有些得不偿失,中文字体体积比较大,大陆不一定能打得开 Google Fonts,打开不一定快,用国内的反代不一定稳。
  3. 赫蹏:看起来不错,是个 2020 年开始的新项目。直接用在主题上没有太大的问题,效果还不错。于是进行了一番魔改,调整或去掉与主题冲突的样式,再适配一下无限滚动,得到的效果很理想。

22:36