阅读视图

发现新文章,点击刷新页面。

10 分钟 ZeroTier 私有 Plant 部署指南,提高游戏联机体验

在多人局域网游戏如星露谷物语、饥荒、我的世界等日益流行的今天,拥有一个稳定且低延迟的游戏联机环境对于提升玩家体验至关重要。本文将介绍如何使用 Docker 快速部署一个私有的 ZeroTier Planet 服务器,实现联机游戏低延迟,高稳定性。通过虚拟局域网技术,让不同地点的玩家能够如同在同一个局域网中一样进行游戏。

ZeroTier 简介

ZeroTier 是一种 P2P VPN 解决方案,它允许用户在互联网上创建一个虚拟的局域网,使得不同地理位置的设备能够像在同一个局域网内一样直接通信。也就是说,通过 ZeroTier,你可以和你的朋友在各自的家里,组成同一个局域网。然后你们就可以一起玩各种局域网联机游戏,如星露谷物语、饥荒、我的世界等。

ZeroTier 的核心组件包括 PLANET、MOON 和 LEAF,分别代表根服务器、卫星服务器和网络客户端。PLANET 是 ZeroTier 的根服务器,负责维护网络的全局状态和路由信息。

官方的 ZeroTier 服务器位于海外,对于国内用户来说,连接可能会不稳定。自建 PLANET 服务器可以有效解决这一问题,提升网络连接的稳定性和速度。

开始安装

准备条件

  • 一台具有公网 IP 的服务器,需要开放 3443/tcp、9994/tcp 和 9994/udp 端口。
  • 安装 Docker
  • Debian10+,Ubuntu20+ 等内核大于 5.0 的系统

使用 Docker 安装

新建 docker-compose.yml 文件,插入下面内容,
记得修改下面中的 IPV4IP ADDRESS 为你的公网 IP 地址。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
version: '3'services:  myztplanet:    image: xubiaolin/zerotier-planet:latest    container_name: ztplanet    ports:      - 9994:9994      - 9994:9994/udp      - 3443:3443      - 3000:3000    environment:      - IP_ADDR4=[IPV4IP ADDRESS]      - ZT_PORT=9994      - API_PORT=3443      - FILE_SERVER_PORT=3000    volumes:      - ./data/zerotier/dist:/app/dist      - ./data/zerotier/ztncui:/app/ztncui      - ./data/zerotier/one:/var/lib/zerotier-one      - ./data/zerotier/config:/app/config    restart: unless-stopped

在 docker-compose.yml 文件中目录下,使用如下命令启动

1
docker-compose up -d

后台配置

  1. 访问 http://ip:3443 进入 controller 页面,使用默认账号为:admin,默认密码为:password

  2. 进入后创建一个网络 (Add network),可以得到一个网络 ID

  3. 最后需要分配网络 IP: 选中 Easy setup->Generate network address

1d6b3d12c3a688385c45f6b940f42fae.png

b19f85de2600c57daefe7b9b344b27dc.png

Windows 客户端配置

下载

首先去 ZeroTier 官网下载一个 ZeroTier 客户端

覆盖 planet 文件

将服务器中 ./data/zerotier/dist 目录下 planet 文件覆盖粘贴到自己电脑的 C:\ProgramData\ZeroTier\One

覆盖 planet 文件.png

重启服务

Win+S 搜索 “服务”,打开 “服务”,找到 ZeroTier One,并且重启服务

重启服务

加入网络

在后台找到 ID,和平常使用 ZeroTier 加入网络的操作一样。

授权访问

在 ZeroTier 控制器的管理后台,找到新加的客户端并授权其访问。

授权访问.png

连通验证

马赛克处为你的公网 IP

连通验证.png

其他客户端

对于安卓客户端,目前只有非官方的客户端可用
https://github.com/kaaass/ZerotierFix

而 MacOS 用户需要替换 /Library/Application Support/ZeroTier/One/ 目录下的 planet 文件,并重启 ZeroTier-One:cat /Library/Application\ Support/ZeroTier/One/zerotier-one.pid | sudo xargs kill,后续则与 Windows 配置相似。

游戏联机

你的朋友也需要完成客户端配置,才能与你组成局域网。你可以手把手的教他如何操作,也可以让他参考下面的文章进行操作。

3 分钟加入朋友的私有 ZeroTier Plant 网络中

当网络组成后,你可以在后台找到朋友在局域网中的 IP,

然后使用 ping <IP> 命令测试网络延迟。

猜你也想读

Caddy, Docker 简单的自建 Tailscale DERP

作为一个拥有全端加密且能进行端到端连接的服务。Tailscale 现在的免费账户已经支持连接 100 台设备,这对于个人用户来说绰绰有余。我的内网设备几乎都在使用 Tailscale 连接。在前段时间发布的 用 VS Code 管理服务器,我有独特的服务器管理方式 中表明我很喜欢用 Remote SSH,我经常借住 Tailscale 组成的内网使用 Remote SSH 进行远程开发。

然而,Tailscale 在中国大陆的网络环境中存在一个问题,就是经常出现高延迟或者连接不上的情况。好在官方允许用户自建 DERP 服务,以充当中继,解决这个问题。再也不用担心写代码写一半就突然断了,而且优秀的网络体验也能提高 VS Code 的 Port Forward 的体验,方便远程预览开发。

由于我本身就有一台低配置的云服务器,过去曾经使用 Caddy 作为反向代理服务器来运行我的 Alist 项目。所以这次也考虑在同一台服务器上使用 Caddy 作为反向代理来部署 DERP 项目。

采用 Caddy 主要是他相比较于 Nginx 使用很简单的配置就能满足大部分需求,还有体验良好的自动 SSL 管理。能省很多事。

废话不多说,直接开始配置了。

配置 Docker

1
2
3
4
5
6
7
8
9
10
11
// docker-compose.ymlversion: '3'services:  derper:    image: fredliang/derper    restart: always    ports:      - 3478:3478/udp      - 23333:443    environment:      - DERP_DOMAIN=derp.example.com

然后启动

1
sudo docker compose up

配置 Caddy

1
2
3
4
// Caddyfilederp.example.com {    reverse_proxy localhost:23333}

重载 Caddy 的配置

1
sudo docker compose exec -w /etc/caddy caddy caddy reload

别忘了解析你的域名到你的 Caddy 服务器上。

配置 Tailscale

在 Access Controls 中配置

直达链接:https://login.tailscale.com/admin/acls/file

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
{  // ... 其他 ACL 配置  "derpMap": {    "OmitDefaultRegions": true, // 是否只连接自建 derper 节点    "Regions": {      "900": {        "RegionID": 900,        "RegionCode": "myderp",        "Nodes": [          {            "Name": "1",            "RegionID": 900,            "HostName": "derp.example.com", // 域名            "STUNPort": 3478,            "DERPPort": 443,          }        ]      }    }  }}

结束。

参考

  1. GitHub - fredliang44/derper-docker: tailscale‘s selfhosted derp-server docker image
  2. Custom DERP Servers
  3. How NAT traversal works
  4. Tailscale 基础教程:部署私有 DERP 中继服务器
  5. 浅探 Tailscale DERP 中转服务

自建 Sentry 使用 script 启用时无效

最近在服务器上面自建了 Sentry。

用 script 方法加入到网站后,始终没有效果,然后在控制台中发现了下面的报错。

The Sentry loader you are trying to use isn’t working anymore, check your configuration.

于是去 Github 上找了下,看着应该是国内网络的问题。

在 sentry/sentry.conf.py 内添加下面内容可以解决。

1
JS_SDK_LOADER_DEFAULT_SDK_URL = "https://browser.sentry-cdn.com/%s/bundle.tracing.replay.debug.min.js"

然后记得重启 Sentry 的 Docker 服务

1
2
sudo docker compose restartsudo docker compose up -d

VS Code 插件 Monitor Pro - 监控一切你在意的资源信息

Monitor Pro 是一个全面的资源监控工具,旨在帮助你实时跟踪重要的系统指标并提供直观的展现方式。无论你是什么职业,如果你用 VS Code,请不要错过它。

安装使用

安装后会自动启用该插件。

https://marketplace.visualstudio.com/items?itemName=nexmoe.monitor-pro

屏幕截图

功能特点

  • 资源监控
    • CPU 使用率:监控 CPU 利用率的百分比,以了解系统正在利用多少处理能力。
    • CPU 频率:跟踪当前 CPU 频率,以了解系统如何动态调整其处理能力。
    • CPU 温度:(如果可以的话)监控温度。
    • 内存使用:关注计算机的内存消耗情况。
    • 网络使用:跟踪机器上的网络活动,包括传入和传出的数据传输速率。
    • 文件系统使用(Linux、macOS):提供磁盘的读写速率。
    • 电池百分比和充电状态:如果你使用的是笔记本电脑或便携设备,此功能可让你监控电池电量和充电状态。
    • 操作系统发行版名称
    • 磁盘使用
  • 排序:自定义监控资源的显示顺序,方便一目了然地监控它们。
  • 刷新间隔:设置更新资源指标的刷新间隔。
  • 无布局移位:确保状态栏中元素的位置和大小不会意外改变。
  • 远程 SSH 资源监控:你可以在远程 SSH 连接的设备上跟踪重要
    的系统指标。
  • 高占用率警报:当任何监控的资源达到高占用水平时,接收警报。
  • 仪表板:我希望在一个页面上显示你关心的所有信息,并配备丰富的图表。

愿景

我深知监控信息的重要性,所以我的目标是打造一个最全面、最直观的监控工具,让你轻松掌握系统状态。开发 Monitor Pro 的初衷是为了满足大家对系统监控的各种需求。

同时在未来我也希望集成图表的设计,让这些数据更加直观易懂。你可以通过这些图表清楚地看到系统各项指标的变化趋势和相互关系。这样,你就能轻松地了解系统的性能表现。并能够基于这些指标做出明智的决策。

为什么要开发这款插件?

为了在使用 VS Code 的 Remote SSH 时提供一种全面的资源监控工具,以便更好地管理和监控服务器的状态。

详细参考:https://juejin.cn/post/7284885060338155539

建议反馈

我非常重视用户的反馈和意见,因为它们对于我改进和完善产品至关重要。有好的建议或者遇到了 BUG,请前来反馈:

https://github.com/nexmoe/vscode-monitor-pro/issues

支持我

Github 点个 star 或是来 VS Code 市场 给个五星好评吧!

动画 PNG(APNG) 转 GIF 并无限循环

今天在网上找了些 PNG 格式的动态表情包我是不会告诉你是我是在 LINE 偷的表情包的,于是了解到是 APNG 这种格式。由于微信和 QQ 不支持 APNG,所以就把 APNG 转为 GIF 了,在使用 APNG 转换成 GIF 后,发现在微信上只能播放一次,就产生了如何批量修改 GIF 的循环次数的问题。

所以准备简单介绍一下 APNG。并提供了一个在线工具,可以将 APNG 批量转换为 GIF,但是该工具不能实现无限循环。所以分享了一个批量修改 GIF 循环次数的方法,使用了 Node.js 和批处理脚本两种不同的实现方式。方便 Node 开发者和使用 Windows 的普通用户直接批量处理。

APNG 是什么?

APNG(Animated Portable Network Graphics)是 PNG 的位图动画扩展,可以实现 PNG 格式的动态图片效果。APNG 相比于 GIF 在图片质量和细节表现方面更有优势,而且随着越来越多的浏览器对 APNG 的支持,它有望成为下一代动态图的标准之一。主要有以下区别:

  1. 图片质量:GIF 最多支持 256 种颜色,并且不支持 Alpha 透明通道,这导致 GIF 在色彩丰富的图片和含有半透明效果的图片上质量较差。而 APNG 可以支持更高质量的图片,包括更多的颜色和 Alpha 透明通道,使得动画效果更加细腻。

  2. 构成原理:APNG 和 GIF 都是由多帧构成的动画,但是 APNG 的构成原理允许超自然向下兼容。APNG 的第一帧是标准的 PNG 图片,即使浏览器不认识 APNG 后面的动画数据,也可以无障碍显示第一帧。而如果浏览器支持 APNG,就可以播放后面的帧,实现动画效果。

  3. 浏览器支持:从 Chrome 59 开始,Chrome 浏览器开始支持 APNG,使得大部分浏览器都能显示 APNG 动画。唯独 IE 浏览器不支持 APNG。

更多内容请参考:https://xtaolink.cn/268.html

APNG 批量转 GIF

该工具可以批量将 APNG 转为 GIF,不过不能无限循环。

https://cdkm.com/cn/png-to-gif

批量修改 GIF 为无限循环

bat(普通用户请使用该方法)

下面是使用批处理脚本(.bat)来实现相同的功能:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
@echo offsetlocal enabledelayedexpansionset "directoryPath=C:\path\to\directory"for /r "%directoryPath%" %%f in (*.gif) do (    echo Modifying %%~nxf    call :modifyGif "%%f")exit /b:modifyGifset "filePath=%~1"set /p data=<"%filePath%"set "index=!data:~0,16!"set "modifiedData=!data:~0,16!!data:~16,1!!data:~17,1!!data:~19!"echo.!modifiedData!>"%filePath%"exit /b

请将C:\path\to\directory替换为实际的目录路径。将上述代码保存为.bat文件,双击运行即可。脚本将遍历指定目录下的所有.gif文件,并对其进行修改。

请注意,批处理脚本的功能相对有限,无法直接读取二进制文件。上述脚本通过读取文件的第一行来模拟读取文件内容。在修改文件时,它直接将修改后的数据写入文件,而不进行二进制操作。这种方法可能不适用于所有情况,尤其是处理大型文件时可能会有性能问题。如果需要更复杂的二进制文件处理,请考虑使用其他编程语言或工具来实现。

Node(Nexmoe 使用的该方法)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
const fs = require('fs');const path = require('path');function unlimitedGifRepetitions(path) {  const data = fs.readFileSync(path);  const index = data.indexOf(Buffer.from([0x21, 0xFF, 0x0B]));  if (index < 0) {    throw new Error(`Cannot find Gif Application Extension in ${path}`);  }  data[index + 16] = 255;  data[index + 17] = 255;  return data;}function batchModifyGifFilesInDirectory(directoryPath) {  fs.readdir(directoryPath, (err, files) => {    if (err) {      console.error('Error reading directory:', err);      return;    }    files.forEach(file => {      const filePath = path.join(directoryPath, file);      const fileExtension = path.extname(file);      if (fileExtension === '.gif') {        try {          const modifiedData = unlimitedGifRepetitions(filePath);          fs.writeFileSync(filePath, modifiedData);          console.log(`Modified ${file}`);        } catch (error) {          console.error(`Error modifying ${file}:`, error);        }      }    });  });}const directoryPath = './path/to/directory';batchModifyGifFilesInDirectory(directoryPath);

请注意,上述代码使用了 Node.js 的文件系统模块(fs)来读取和写入文件。此外,需要将./path/to/directory替换为实际的目录路径。在执行该脚本之前,请确保已经安装了 Node.js。

该脚本将批量遍历指定目录下的所有文件,并对后缀名为.gif的文件调用unlimitedGifRepetitions函数进行修改。修改后的数据将写回原始文件。在控制台输出中,你可以看到每个已修改的文件的信息或任何出现的错误信息。

更多内容参考:https://www.b612.me/golang/232.html

更好的工具

这个批处理工具可以将多个 APNG 文件批量转换为 GIF 文件,并且可以对转换后的 GIF 文件批量设置为无限循环。

https://github.com/nexmoe/batch-apng2gif

累积布局偏移优化 CLS 完全指南

什么是布局偏移

一个十几秒的短视频解释清楚。

更详细的解释是:布局偏移指的是在网页上发生突然变化时,页面中的内容位置发生意外移动的现象。这种情况常常让人感到困扰,因为它会导致阅读中断或误操作。布局偏移通常是由于资源异步加载或动态添加到页面上的 DOM 元素导致的。可能的原因包括具有未知尺寸的图像或视频、字体与其备用字体渲染大小不同,或者第三方广告或小部件动态调整大小。

难受的是,网站在开发过程中的功能通常与用户体验有很大不同。个性化或第三方内容在开发中的行为通常与生产环境中不同,测试图像通常已经存在于开发者的浏览器缓存中,本地运行的 API 调用通常非常快,延迟几乎不可察觉。

什么是 CLS

累积布局偏移 CLS(Cumulative Layout Shift)是一个指标。

是对页面整个生命周期中发生的每个意外布局变化的最大布局变化分数的度量。

CLS 通过测量实际用户遇到布局偏移的频率来帮助解决布局偏移问题。它可以帮助开发者了解布局偏移在真实用户中发生的情况,从而采取相应的措施进行修复。

为什么要优化 CLS

布局偏移是一个非常影响用户体验的问题,通过上面那一个简短的视频也能理解。

布局偏移通常会导致意外点击、页面方向的迷失,最终导致用户受挫。用户往往不会逗留太久。有时也会使用户不按照预计的产品流程走。

通常优化好布局偏移能够很好的提高用户粘性、用户停留时间等指标。

Yahoo! JAPAN News 通过降低 CLS 0.2 分,得到如下成果。

如何降低 CLS

图片等媒体元素占位

在图像、视频等媒体资源元素中始终包含宽度和高度大小属性。或用 CSS 中的 min-heightaspect-ratio 或类似的方式保留所需的空间。

aspect-ratio

可以用来直接指定当前元素的比例。

https://developer.mozilla.org/zh-CN/docs/Web/CSS/aspect-ratio

对浏览器的支持:

padding-bottom

如果考虑浏览器支持问题仍然可以考虑使用目前一个被广泛接受的基解决方案 “Padding-Top Hack”。这个解决方案需要一个父元素和一个绝对型的子元素。然后计算出长宽比的百分比来设置为 padding-top。例如:

1
2
3
<div class="container">  <img class="media" src="..." alt="..."></div>
1
2
3
4
5
6
7
8
9
10
.container {  position: relative;  width: 100%;  padding-top: 56.25%; /* 16:9 Aspect Ratio */}.media {  position: absolute;  top: 0;}

使用不易产生偏移的 CSS

其中 transfrom 表现很好,以下举几个例子。
用例可以在这里找到:https://play.tailwindcss.com/26PxFA6UVI

zoom VS transform: scale

zoom 会撑大页面并向右偏移时,transform: scale 只是在原地放大。

margin VS transform: translate

margin 造成父元素变大,transform: translate 只是让当前元素移动。

border VS box-shadow

border 会撑起父元素,而 box-shadow 并不会。

小心你的懒加载

懒加载会引起布局的偏移,如果你在有懒加载长列表的里进行跳转,请小心!
无动画进行跳转,能够一定程度上避免该问题。

小心使用 transition: all

在页面首次加载或者跳转页面时,transition: all 可能会导致元素的 padding 等从参数为 0 开始渲染,照成页面的抖动。

这都是痛:
Commit:表格以及友情链接图标抖动
Commit:修复导航栏抖动问题

标签顺序导致的偏移问题

由于在移动端上优先展示主要内容,因此侧边栏的 markup 位于主要内容的后面;而在更大的屏幕上,则通过设置 CSS order 的方式进行排序,将主要内容移到中间(即第二列),伪代码如下:

1
2
3
4
5
6
7
8
9
export default function MainLayout(props) {  return (    <Container>      <Main className={css`@media screen and (min-width: breakpoint) { order: 0 }`} />      <Left className={css`@media screen and (min-width: breakpoint) { order: -1 }`} />      <Right className={css`@media screen and (min-width: breakpoint) { order: 1 }`} />    </Container>  )}

浏览器在首次绘制时并没有完整解析 DOM、只知道 <Main /> 的存在、但不知道 <Left /> 或者 <Right /> 的存在,才因此将 <Main /> 渲染进第一列而不是第二列;直到第二次绘制时,浏览器才将 <Main /> 渲染进第二列、将 <Left /> 渲染进第一列。

Chrome 并不是一次完整解析 HTML 的,在以下两种情况下,Chrome 会暂停解析、开始渲染和绘制:

  1. Chrome 解析器在读取了 65535 字节的 HTML 后暂停
  2. Chrome 在遇到 <script> 标签后,会继续读取约 50 个「Token」之后暂停

详细了解请看:优化博客的累计布局偏移(CLS)问题

网页跳转与前进后退缓存

默认情况下,所有浏览器都使用 bfcache,但由于各种原因,有些站点不适合使用 bfcache。有关如何测试和识别阻止 bfcache 使用的任何问题的更多详细信息,请阅读 bfcache 文章

在你离开后,bfcache 将页面保存在浏览器内存中很短的一段时间,所以如果你返回它们,那么它们将完全恢复为你离开时的样子。这意味着完全加载的页面立即可用,而不会出现任何变化。

现在的 SPA 应用也能很轻易的保证路由跳转页面布局的一致性。记住始终保持你的目录和导航栏在页面的固定位置。

字体

在下载和渲染网络字体之前,通常有两种处理方式:

  1. 使用网络字体替代备用字体(FOUT——未样式化文本的闪烁)。
  2. 使用备用字体显示“不可见”文本,直到网络字体可用并且文本可见(FOIT——不可见文本的闪烁)。

着两种方式都可能导致布局变化。即使文本是不可见的,它仍然使用备用字体进行布局。这意味着使用该字体的文本块以及周围的内容在网络字体加载时会发生布局变化,与 FOUT 的可见字体完全相同。

以下方法可以帮助你最小化这种问题:

  1. 使用 font-display: optional 可以避免重新布局,因为只有在初始布局时网络字体可用时才会使用它。
  2. 使用匹配度高的备用字体。例如,使用 font-family: "Google Sans", sans-serif; 将确保在加载"Google Sans"字体时使用浏览器的无衬线备用字体。如果只使用 font-family: "Google Sans" 而不指定备用字体,将使用默认字体,而在 Chrome 上默认字体是"Times",它是比默认无衬线字体的匹配度更差。
  3. 使用新的 size-adjustascent-overridedescent-overrideline-gap-override API 来尽量减小备用字体和网络字体之间的大小差异,详细信息请参阅“Improved font fallbacks”文章。
  4. 使用 Font Loading API 可以减少获取所需字体的时间。
  5. 使用 <link rel=preload> 尽早加载关键的网络字体。预加载的字体有更高的机会达到首次绘制,这样就不会发生布局变化。
  6. 阅读有关字体最佳实践的“Best practices for fonts”文章。

使用真正的骨架屏

骨架屏好坏示例

测量 CLS 分数

生产阶段

实验阶段

Lighthouse in DevTools

能够针对移动设备和桌面设备生成网页的实际性能报告,并能够提供关于如何改进相应网页的建议。

在本地开发期间从 DevTools 运行 Lighthouse 非常方便。

PageSpeed Insights

应该就是在线版的 Lighthouse。

Performance in DevTools

性能选项卡在 Chrome 的 DevTools 配置文件的所有页面行为在一段时间内记录。时间轴上会出现一个标记为“Experience”的图层,突出显示布局的变化和发生变化的元素。

Web Vitals extension

最好将 Web vital 扩展视为查找性能问题的抽查工具,而不是全面的调试工具——这是 Chrome 的 DevTools 中的性能选项卡的工作。

结语

作为一个对自己项目有较高要求的人,平常几乎都会接触到布局偏移优化或者 Lighthouse,只不过之前自己瞎折腾的时候还没有 CLS 这个概念,现在算是对 CLS 有了较为清晰的概念了。
CLS 作为一个非常基础的优化指标,在用户体验上非常重要,任何项目都应该针对 CLS 做优化。

如有勘误,请及时指出,感谢!

参考

  1. https://web.dev/cls/
  2. https://web.dev/optimize-cls
  3. https://developers.google.com/publisher-tag/guides/minimize-layout-shift
  4. https://web.dev/yahoo-japan-news/
  5. https://addyosmani.com/blog/infinite-scroll-without-layout-shifts/
  6. https://blog.skk.moe/post/fix-blog-cls/
  7. https://developer.mozilla.org/en-US/docs/Web/CSS/aspect-ratio

我的作品让360团队看上了,作为一个大学生无比荣幸

这么厉害的作品不来尝试一下吗?https://explorer.xiaoshuapp.com/

探索者小舒

强大快捷的开源侧栏搜索切换工具。
GitHub 上开源不久就被 360 无追搜索插件内置进去了,360 无追搜索插件主打隐私安全,探索者小舒的隐私安全也不错。
本来感觉这个项目都要凉了,然后 360 无追搜索看上过后就突然感觉非常惊喜。本来还写了个感谢信,由于社恐让朋友念了一下,不过好像容易产生误会,这里就不发了。
欢迎来 GitHub 点个 star https://github.com/xiaoshuapp/explorer-xiaoshu

9db0c150811b527a046545d469008ad7.jpg/nexmoe
68af62b3daa2fcff6609ca5f551df2e4.jpg/nexmoe

不错的设计给你轻松的体验

极简模式仅一条线,不用时收起,用时展开,还有暗色模式。

主动嗅探添加

让添加搜索引擎轻松一点
Snipaste_2022-06-04_20-19-54.png

随意的拖动

按住然后拖动鼠标,就能排序,分组

随意的拖动

自定义搜索引擎

自定义添加搜索引擎,在分组标题处单击右键唤起菜单
自定义搜索引擎

活着的分组

相关分组自动提前,更快切换当前场景所需的搜索引擎
活着的分组

360

360 无追搜索插件主打隐私安全
cce5a550c64abab6049436285bfe3b2b.jpg/nexmoe
21f9ed29b39b451c963284b9d0cd93ae.jpg/nexmoe

❌