v2ex_hot_2026-01-13

V2EX 热门帖子

1. 个人觉得差不多 200w 就可以提前退休了,前提

前提是无负债有房有车已婚有娃,能做到年化 15%左右的稳定收益。
对物质的欲望不要太高,家人身体健康就可以。

作者: Auston | 发布时间: 2026-01-12 23:15


2. 2FA 感觉就是时代倒退的产物

所谓的账号安全强制用 2fa 属于是因噎废食了, 完全不理解为啥国外大厂强制要求这玩意

你说他安全其实也是个纯靠手机才能使用的验证器, 这东西怎么看都不可能比短信安全

而且还容易丢失一丢失就完全无解, 纯纯的坑自己

印象里二十年前银行卡开通网上支付会送一个类似 2FA 的机器, 会隔几秒换一组数字作为验证码

结果后来线上支付发展起来之后, 这东西直接就淘汰了

国外那些人也不知道脑子里哪里出问题了, 把这玩意捡回来当个宝了

作者: hentailolicon | 发布时间: 2026-01-12 16:22


3. 每次学习 5 分钟就感到无聊, 不能专注, 容易沉迷在 YouTube 等视频网站, 如何破解?

我每次学习还不到 5 分钟会感到无聊,不能专注太久, 然后容易上 YouTube 一看就沉迷其中, 请问: 这如何解决

谢谢

作者: Lucy2025 | 发布时间: 2026-01-12 21:53


4. AI 和 Agent 时代,技术栈选型大佬们有什么建议?

AI 和 Agent 时代。大家整套技术栈有没有推荐的,我发现必须面向 AI 设计技术栈。 一个要 vibe coding 训练性好,一个要未来容易被 agent/skill 驱动。

前端:React 、Tailwind CSS 后端:fastapi 数据库:PostgreSQL 、Sqlite LLM:OpenAI/Anthropic 适配格式

多端/小程序:uni-app 、Flutter 原生:Swift 、Kotlin

技术菜鸡一个,求大佬们推荐和补充~~

作者: bixinhaner | 发布时间: 2026-01-12 04:47


5. oppo 系统自带的邮件 app 添加不了 outlook 邮箱

干净的系统 系统是 color 16 最新版 自带邮件 app 添加 outlook 邮箱 提示“无法连接到服务器 需要 tls” 邮箱类型选择 imap 也不行 后来用 QQ 邮箱可以添加 outlook 账号 哪位用过 color os 16 的朋友 你们遇到过这样的问题吗 怎么解决?

作者: jaleo | 发布时间: 2026-01-12 14:10


6. 做了个 Proxmox VE 多集群管理平台,有类似需求的朋友欢迎一起交流学习

最近写一个关于 Proxmox VE 多集群开源项目,第一次整这玩意,各位观众老爷们给评一评,国内会有人用?不知道有木有要入坑欢迎大家一起交流交流

项目简介

一个开源的 Proxmox VE 多集群 Web 管理平台,解决多集群运维的痛点。

解决什么问题

如果你运维多个 PVE 集群,应该深有体会:

  • 在多个 Web 界面之间频繁切换
  • 手动同步虚拟机模板费时费力
  • 缺少跨集群的资源全局视图

PveSphere 提供统一的控制面板,让你从单一界面管理所有集群。

核心功能

  • 多集群统一管理
  • 虚拟机生命周期管理(创建、迁移、备份等)
  • 自动化模板同步
  • 实时资源监控
  • VNC 控制台访问

快速体验

git clone https://github.com/pvesphere/pvesphere.git
cd pvesphere
make docker-compose-build

默认账号:[email protected] / Ab123456

访问: http://localhost:8080

技术栈

  • 后端:Go + Nunu 框架
  • 前端:Vue + vue-pure-admin
  • 部署:Docker Compose

适用场景

✅ 管理多个 PVE 集群 ✅ 需要自动化模板分发 ✅ 需要集中监控和管理

❌ 单集群用户(原生界面可能更合适)

项目地址

联系方式

博客原文

https://www.ljohn.cn/posts/91d244ba/

欢迎试用和反馈 🙌

作者: ljian6530 | 发布时间: 2026-01-12 15:59


7. 小白提问:大家平时用什么浏览器?使用隐私保护的浏览器有可能会反向导致 IP 风险值变高吗?

大家平时用什么浏览器?使用隐私保护的浏览器有可能会反向导致 IP 风险值变高吗?

比如 Brave ( Chromium )、LibreWolf ( firefox )、Mullvad Browser (无 tor 网络版的 tor Browser ) 等等浏览器。这些一定程度上隐藏了浏览器指纹,是否会反向导致 IP 被标记,IP 质量下滑?

另外如果长期使用这些浏览器,在一些高风控的平台的注册账号是否会被平台风控提升风险等级?

作者: Hanmi | 发布时间: 2026-01-12 15:18


8. 分享个非常棒的自动填充图片验证码的 Chrome 插件——AutoVerify

直接上地址: AutoVerity

用了一个多周了,体验下来真的太棒了,太棒了,太棒了(重复 3 遍,不是 AI )。

我平日工作中每天要打开验证码的网站,这个插件会 ocr+自动填充,节省不少时间。

这个工具半年没更新了,大家有类似的插件吗?担心后面不维护了。

ps. 只支持普通的 ocr ,上难度的不太行。

作者: Kinnikuman | 发布时间: 2026-01-12 11:13


9. 常用的大模型 api 都用哪些模型?

对话类的(不考虑 tts/生图/语音识别),平时用 api 比如翻译/aicommit 这种简单场景,会使用 deepseekv3/mimo-v2-flash/gpt-4.1-mini/qwen3-32b 等,这些模型访问快,消耗低。

另外是代码模型,会使用 gpt-5.2-pro/claude-opus-4.5/glm-4.7/minimax-2.1/gemini-3-pro 等。

再者在 cherry-stuido 中用的对话类的,基本就是 deepseekv3 了。

再如果想让 ai 联网搜索做对比推荐,会直接使用网页版 gpt/gemini/grok 等,不会使用 api 。

所以我好奇使用 api 推理模型的人多吗?比如 gpt 那些 o1/o3 等模型,我一次也没用过。

作者: ethusdt | 发布时间: 2026-01-12 13:23


10. 发一个内网端口穿透工具

发一个内网端口穿透工具, https://tunneling.cc/#download

家里有 NAS 、自建服务,想随时随地访问的人 运维/开发经常需要对外临时暴露测试环境的人 追求配置一次、长期稳定的人 不想每个内网设备都装客户端的人 祝大家内网穿透从此不再痛苦,远程访问一路丝滑!🚀

作者: 52money | 发布时间: 2026-01-12 10:35


11. Sublime Text 也出了国内特供?挂马版本?

用必应搜 sublime text 搜出了这个: https://sublime.njshenli99.cn/

安装包比官方的大好几倍,没敢安装

作者: songziming | 发布时间: 2026-01-12 09:41


12. 关于 AI Java 编程

平常我也会使用 GitHub copilot 进行编程,包括但不限于编写 chrome 插件,raycast 插件,macOS 程序。但是真正生产代码中只会用来 tab 补全,没真正让 AI 自主写过需求。

新公司打听了一下 AI 编程情况,隔壁组几十万行的生产项目( Java 项目)竟然新需求 50% 以上是 Cursor 编程的,着实让人震惊,现在 AI 编程已经进化到这么强了吗?我自己使用 copilot 也尝试过编写需求,确实不让我满意。不知道各位公司 AI 生成的生产环境代码占比高吗? Cursor 会比 Copilot 强很多吗(我觉得 Copilot 还不能写大型业务需求)。

是不是后面手工编程真的要成古法编程了😂 2025 年已经这样很难想象两三年之后的情况呀

作者: M1234 | 发布时间: 2026-01-12 13:14


13. anki 初体验,个人想法:效率不高的样子。。。

鉴于最近有些记忆性的东西要整理,所以想起来很早起看到的 anki ,决定试用一下。

我导出了我的几篇文档,让 gpt 根据我的文档导出了知识条目为 csv 。

然后在 anki 里面根据 csv 的列名创建了笔记模板,让 gpt 生成了基于列名的卡片模板,然后库库一通把 csv 导入到 anki 里面。

试用了一会儿了,发现如下几个问题:
1. anki 我理解就是用户自定义的“英语背单词软件” plus ,百词斩,墨墨背单词,欧路词典这种的,用户可以自定义自己的知识领域,而不单纯是英文单词。

2. 这个什么记忆曲线的模式,好像对我当前的记忆场景来说,效率并没有很高。因为我要记忆的是几个基础的计算机相关的机械性的快捷键,或者命令。撑死了不过几百条。

我现在完全可以让 ai 生成一个结构化的,排版优良的,带有总结性对比性 markdown 表格的文档,然后每天过一两遍也就 ok 了。

anki 我感觉适合的场景可能就是每天利用零碎时间”背单词“。。。

但是背单词的话,why 不用百词斩这些现成的工具。

另外,调研工具期间还发现了一个 remNote 的笔记软件,导入了一个 anki 的牌组试用了一会儿也放弃了,感觉有点花里胡哨,还是直接抱着 obsidian 硬背完事儿了。

作者: YanSeven | 发布时间: 2026-01-12 07:51


14. [复盘] 48 小时 700+ Star:一次关于开源项目「技术价值」和「实用价值」的真实碰撞

最近做的一个自用项目「股票分析推送」开源之后,不到 48 小时就达到了 700+ star, 也引发了我的一些思考,分享给大家看看。

作为工程师,平时用开源项目用得很多,说实话也一直想着做点东西回馈社区。 当然,如果项目能被更多人看到,Star 往上涨,本身也是一种很直接的认可。

陆续发过一些项目,最近做的两个开源项目,结果反差非常大,也让我对「什么样的项目更容易被用、被传播」有了更清晰的认识。


第一个项目:花了最多精力,但反响最小

第一个项目是一个微调数据集构建相关的工具

起因其实很现实:之前项目中发现这块几乎没有现成好用的方案,很多事情要反复手工处理,于是就想着自己系统性地做一个。 这个项目前后投入了不少时间,代码结构、功能完整度都比较高,还专门整理好发布到了 PyPI 。

从技术和工程角度看,我对它是满意的,甚至还有公司因为这个项目找我,后续会集成到他们的项目中进行使用。 但数据也很直观:大半年时间,Star 只有 140+。

后来慢慢也想明白了原因:

  • 偏底层
  • 使用场景相对窄
  • 需要一定背景才能真正用起来

它不是没价值,而是真正需要它的人,本来就不多


第二个项目:做起来最轻,但反馈最猛

最近做的第二个项目,本来是写着自己用的,开源之后大家的热情程度是超乎意料的。

这是一个偏应用层的股票分析推送项目 ,逻辑并不复杂,目标也很明确: 拿来就能用。

从设计、简单测试到功能补充,其实都不算重活。很多细节甚至是开源之后,根据网友反馈一点点补上去的。 整个过程比第一个项目轻松得多。

但结果是: 48 小时内,Star 突破 700 。

这个增长速度,说实话我自己都有点意外。


一点很现实的反思

把这两个项目放在一起看,其实结论非常清楚:

开源项目火不火,很多时候和你“技术写得有多深”关系不大, 和它是不是立刻能用、有没有门槛、是不是热门方向 关系很大。

简单总结一下:

  • 第一个项目 偏底层、门槛高、需要理解背景 技术价值不低,但“用起来成本高”

  • 第二个项目 偏应用、零门槛、而且是 AI+股票这种热门方向 Fork 一下、配个配置就能跑,不用理解原理

当“直接可用”摆在面前,大多数人会自然做出选择。


这不是否定技术项目的价值,而是如果你做开源的目标里既有分享,也希望被更多人看到 ,那就必须正视“实用性”和“传播性”这件事。

这是我非常真实的一次经历,记录下来,希望对你有点参考价值。

最后也贴一下这两个项目,感兴趣可以看看:

作者: mumu157 | 发布时间: 2026-01-12 13:23


15. jetbrains 全家桶切换到 vscode 系列,快捷键大家怎么记的?

之前一直使用 jetbrains 全家桶,最近一直在使用 antigravity 进行开发。如果把快捷键设置成了 idea 快捷键怕影响 vscode 系 ide 特有的功能。最近这两年应该有很多人都切换了 ide ,想问下大家怎么处理的?常用哪些快捷键?

作者: GuluMashimaro | 发布时间: 2026-01-11 15:18


16. 好了好了好了 一提 AOP 就说打 log 那我知道你的水平了

  • 说出 5 - 10 个并发容器,再讲讲他们是如何保证线程安全的
    • 好了好了 没必要展开讲一个设计模式 还有没有其他的
    • jvm 都有几种 oom? 你项目中只遇到过一种?行吧我知道了
    • 行行 好这个问题可以了 没必要那么详细的解释
    • mongodb 内部是如何存储数据的 如何做集群的… 好好好 不用特别展开讲那么详细
    • k8s 、cicd, 项目经历,这些这些都不聊 今天是技术面,只聊 java 知识
    • 你说你做过运营商的项目 你说几个运营商的名字 哦哦 只有欧洲的几个对吧 行行行 …

以上选自今天的飞书面试

随便吐槽两句,各位新年快乐。

作者: jwenjian1210 | 发布时间: 2026-01-12 04:58


17. 想买个最便宜的云服务器做内网端口转发

想在国内买个最便宜的云服务器或者云容器,目的只有一个就是为家里的机器做端口转发,方便我在外边随时连接。 现在最便宜的似乎是阿里云和京东云,60 多一年,想知道各位大佬有没有什么更便宜的渠道? 我看云容器比云服务器还贵,真是没道理啊。

作者: timewarp | 发布时间: 2026-01-11 07:47


18. 老黄给的免费 LLM API 用来做网页翻译用着很爽

前几天折腾了一下,ministral-14b 配合魔改之后的某著名闭源翻译插件,效果极佳,速度也飞快

最爽的是卡都不用绑,唯一的限制是每分钟只能请求 40 次,对翻译场景绰绰有余

作者: lemoncoconut | 发布时间: 2026-01-11 08:13


19. 以后腾讯云的美区服务器,是不是不能用了?

收到腾讯云邮件,根据美国司法部的”DSP”通知的 balabala 内容没看懂。有没有大佬解读一下?
以后腾讯云的美区服务器,是不是不能用了?

-——-

关于使用腾讯云美国服务的重要监管更新通知

尊敬的腾讯云用户,您好!
感谢您的腾讯云账号(账号 ID:****,昵称:)一直以来对腾讯云的支持与信任。
自 2025 年 4 月 8 日起,美国司法部根据《关于防止受关注国家或受限主体获取美国敏感个人数据及政府相关数据的最终规则》(” DSP “),限制了向受关注国家或受限主体提供美国敏感个人数据及政府相关数据。
腾讯云始终恪守合规经营理念,致力于为客户提供高质量的服务。为此,腾讯云的服务产品内置完善的技术与流程管控措施,确保客户在信息处理与安全保障方式拥有完全自主权。
请注意,根据您使用腾讯云服务的具体情况,在某些场景下,腾讯云的非美国实体及/或雇员可能在您及您所在企业明确授权的前提下,可控地参与在客户数据的处理活动。
例如,当您授权腾讯云的非美国人员为美国境内的产品或服务提供运维支持时,可能涉及远程处理。因此,腾讯云将确保客户有能力准确评估通过腾讯的产品或服务处理的数据类型(及所在区域)、客户数据的使用方式,以及是否涉及任何美国敏感数据,从而判断相关交易是否会导致任何一方落入 DOJ 规则的限制范围。 我们的职责是确保您掌握必要信息,以便合理配置从我们获取的产品服务,或调整使用方式。
如有任何疑问,敬请通过 cloudlegalnotices@tencent.com 联系我们。

作者: jacketma | 发布时间: 2026-01-12 10:04


20. 你是一个严格的技术经理,请用一个词评价一下当前的代码库,并给出理由。

看看你们的代码库是什么结果?


我的:😆

评价:脆弱

理由:

作为严格的技术经理,我最关注的是代码库的可持续性和变更安全性。尽管这个代码库有许多优点……

作者: flankerfc | 发布时间: 2026-01-12 03:11


21. 安卓 app“清空数据”居然把 发通知 权限也清空了??

抖阴也吃空间就顺手 清空 cache+清空数据

一不留神给我推一堆通知。点开一看居然权限又自动打开了。

安卓的权限设置是跟 app 数据走的?

这种设计好吗。。。?

作者: tf2 | 发布时间: 2026-01-12 02:30


22. 谷歌翻译不能用

今天谷歌翻译不能用了,重试多次也不行,有人知道原因吗?或者有啥替代产品吗?谢谢

作者: test9106 | 发布时间: 2026-01-12 06:23


23. 有没有自动管理下载目录的工具或者方法?

需求是:

  • 安装包自动在一周后清理
  • 书籍移动到书籍目录,并且去重
  • 文档移动到文档目录
  • 压缩包根据解压后的内容,移动到安装包或者书籍目录

作者: shyrock2026 | 发布时间: 2026-01-12 08:24


24. php74-fpm 加 nginx, PHP 文件只要不是 root /var/www/html 就提示 No input file specified.求大佬看看

使用的测试文件 info.php,调用 php.info(); 现在网站需要放在其他路径底下,修改了 nginx 中的 root 之后就提示 No input file specified. 但是 index.html 静态文件显示正常

在网上查的和 gpt 问,试过以下几种方式还是不行,求大佬帮忙看下

1 ,php74/etc/php-fpm.d/www.conf 文件中 chroot 和 chdir 参数都是默认注释的, 在 info.php 中,参数显示如下 USER www-data HOME /var/www

2 ,nginx 中的 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; $document_root 或者修改成绝对路径也不行

3 ,修改 cgi.fix_pathinfo=0

4 ,;cgi.force_redirect=1 取消注释

上述的 4 种方式最多就是某 2 个一起试过。 关于文件权限问题,/var/www 使用的是 777 ,html 和我想放的文件夹 site 的权限也是 777 ,site 和网站文件的属组和属主都是 www-data php74/etc/php-fpm.d/www.conf 文件中


user = www-data

group = www-data

listen = /run/php74-fpm.sock

listen.owner = www-data

listen.group = www-data

listen.mode = 0660


/run/php74-fpm.sock 的属组和属主是 www-data

求大佬帮忙看下还有什么办法嘛,想放到/var/www/site 文件夹下

作者: baiyekaslana | 发布时间: 2026-01-12 02:41


25. 分享一个在 Linux 上编译静态 Git 二进制的项目

去年底(距今也没有多久),发现我为上上家公司写的 Git 构建脚本还在用,于是我花业余时间写了一个新的脚本,用来构建仅依赖 libc 或者静态编译 Git 的项目,现在分享出来:https://github.com/baulk/git-minimal,旨在提供最新版无依赖的 git 二进制。

Release 可下载 deb/rpm/apk(alpine) 安装包,还有 tar.xz 压缩包(压缩包里有启动器,修正了路径和 SSL 证书,证书下载自 cURL 站点),压缩包(安装包)中还有开启了 HTTP/3 的 cURL 最新版本。

风味

包名 libc 可运行的系统
git-minimal glibc Linux ,x86_64 ,glibc >= 2.39
git-minimal-static glibc (静态链接) Linux ,x86_64
git-minimal-musl musl (静态链接) Linux ,x86_64/aarch64

由于 musl 的内存分配器比较差,git-minimal 在链接阶段链接了 mimalloc 。

作者: forcecharlie | 发布时间: 2026-01-12 01:49


26. online 黑客松,欢迎大家来参与

🏆 $3,000 奖金池 · 线上黑客松 · Agent 基础设施技术栈

一场聚焦 Agent 技术栈的全球线上黑客松现已开启。 你可以在任何地方参与,独立完成任务,并为真实的开源项目贡献代码。

MemU 赛道( Agent 记忆系统方向)

如果你对 Agent 的记忆系统感兴趣,其中一个赛道是 memU PR Hackathon 。 也非常欢迎你为我们点一个 GitHub Star ⭐️: https://github.com/NevaMind-AI/memU

你可以参与的任务包括:

-修复 Bug ,提升系统稳定性

-添加集成与新功能

-设计与“记忆”相关的应用场景

每一个被合并的 PR 都将计入积分、荣誉与奖励。

👉 memU 赛道规则与任务详情: https://memu.pro/hackathon/rules

作者: Koimiao | 发布时间: 2026-01-12 12:01


27. AI 赛事通 - 2026 年 1 月 AI 竞赛和黑客松汇总合集

AI 赛事通(CompeteHub) 专注于精心挑选最新的全球 AI 竞赛信息,涵盖数据算法比赛、AI 大模型比赛、工程开发比赛、AI Agent 挑战赛、黑客松. 已经收集 500+比赛、100+竞赛来源、超 5000 万奖金,还在继续更新中。订阅 AI 赛事通周报,第一时间获取最新比赛信息,不错过任何机会错过任何一场 AI 赛事,赢取奖金。

发现 1 月开始的最新 AI 竞赛,包括数据算法竞赛、AI 大模型竞赛、工程开发竞赛、AI Agent 挑战赛、黑客松。 共 112 场比赛 1 月 1 日 - 1 月 31 日, 查看 1 月比赛信息

作者: wuswoo | 发布时间: 2026-01-12 07:16


28. 为啥有时候 Google 地图可以直接用

为什么有时候打开 Google 地图可以直接用,包括街景也可以查看,国外的公共交通也可以查看,有人知道原因吗?
有九段线和 “台湾省” 的地图版本
国内对于谷歌地图的服务不是早就停了吗?感觉墙也没有漏风到这种程度吧?

作者: S179276SP | 发布时间: 2026-01-12 08:34


29. 内网环境,产品埋点怎么简单的技术实现?

之前做 App 或者是网站的埋点,都是用友盟、talkingdata 、百度之类的第三方的 SDK 。

如果是内网环境怎么搞?难道需要自己实现一整套埋点方案吗,这成本不是很高么?

现在公司有给银行/政府做的项目,我在考虑怎么进行数据收集,用来评估产品的优化效果。

作者: asdblue | 发布时间: 2026-01-12 03:01


30. 做了个 mcp-cli 对标 claude code 的 mcp-cli,欢迎尝试

支持 claude code, gemini, cursor 的 mcp 配置

使用场景

关于 Claude Code 内置的 mcp-cli ENABLE_EXPERIMENTAL_MCP_CLI=true 开启后,会不用传统的 tools 方式调用 mcp ,节省 token 能配合 bash 工具一起使用

源码 https://github.com/wenerme/wode/tree/develop/packages/wener-mcp-cli

e.g.

bunx @wener/mcp-cli servers -s
chrome-devtools (~/.gemini/antigravity/mcp_config.json)
  • click
  • close_page
  • drag
  • emulate
  • evaluate_script
  • fill
  • fill_form
  • get_console_message
  • get_network_request
  • handle_dialog
  • hover
  • list_console_messages
  • list_network_requests
  • list_pages
  • navigate_page
  • new_page
  • performance_analyze_insight
  • performance_start_trace
  • performance_stop_trace
  • press_key
  • resize_page
  • select_page
  • take_screenshot
  • take_snapshot
  • upload_file
  • wait_for

context7 (~/.claude.json)
  • resolve-library-id
  • query-docs

Context7 (~/.cursor/mcp.json)
  • resolve-library-id
  • query-docs

deepwiki (~/.gemini/antigravity/mcp_config.json)
  • read_wiki_structure
  • read_wiki_contents
  • ask_question

Config Sources:
  claude: ~/.claude.json
  cursor: ~/.cursor/mcp.json
  gemini: ~/.gemini/antigravity/mcp_config.json

Duplicates (first occurrence used):
  context7: ~/.claude.json, ~/.gemini/antigravity/mcp_config.json 

作者: wenerme | 发布时间: 2026-01-12 06:25


31. 这把实锤了, win11 是微软 25 年来最慢的系统

https://www.techspot.com/news/110817-windows-11-performs-worse-than-older-windows-versions.html

测试所有指标都落后以前的老系统

https://www.eteknix.com/microsoft-may-have-created-the-slowest-windows-in-25-years-with-windows-11/

作者: iorilu | 发布时间: 2026-01-11 09:07


32. 国漫的这种 AI 绘图用的什么工具?

看起来很逼真,比动画中的分辨率还高。大模型都有审查吧,这种是怎么弄得?想学习学习。

作者: wsseo | 发布时间: 2026-01-12 05:06


33. 以后验收是不是得控制代码行数了

比如一个小项目,乙方用 AI 直接拉了托几十 w 行的代码,但功能都没问题。

作者: COW | 发布时间: 2026-01-11 05:24


34. 发现了一些 AI 的学习资料

传送门: https://github.com/twwch/AI-Tracker

作者: jaycee110905 | 发布时间: 2026-01-12 09:14


35. 以后发软件库是不是只用发 spec?

X 上看到 阮一峰 发了一个好玩的库:

https://x.com/ruanyf/status/2010225187594334692

https://github.com/dbreunig/whenwords

顺手一个小时就 Vibe coding 了一个 Ruby Implementation

https://github.com/ZPVIP/whenwords

感觉以后可以用 spec 发库了

作者: zpvip | 发布时间: 2026-01-11 08:31


36. 基于 Pydantic-Resolve 和 FastAPI-Voyager 的 Clean Architecture 实践 – 一套面向复杂业务场景的 Python Web 开发方法论

基于 Pydantic-Resolve 和 FastAPI-Voyager 的 Clean Architecture 实践

篇幅较长无法粘贴全文,原文链接: https://github.com/allmonday/A-Python-web-development-methodology-for-complex-business-scenarios/blob/main/README.zh.md

一套面向复杂业务场景的 Python Web 开发方法论

目录


1. 背景与问题

1.1 当前主流做法及其痛点

在 Python Web 开发中,处理复杂业务场景时,开发者通常采用以下几种模式:

模式一:直接使用 ORM (如 SQLAlchemy )

@router.get("/teams/{team_id}", response_model=TeamDetail)
async def get_team(team_id: int, session: AsyncSession = Depends(get_session)):
    # 获取团队基本信息
    team = await session.get(Team, team_id)

    # 获取 Sprint 列表
    sprints = await session.execute(
        select(Sprint).where(Sprint.team_id == team_id)
    )
    team.sprints = sprints.scalars().all()

    # 获取每个 Sprint 的 Story
    for sprint in team.sprints:
        stories = await session.execute(
            select(Story).where(Story.sprint_id == sprint.id)
        )
        sprint.stories = stories.scalars().all()

        # 获取每个 Story 的 Task
        for story in sprint.stories:
            tasks = await session.execute(
                select(Task).where(Task.story_id == story.id)
            )
            story.tasks = tasks.scalars().all()

            # 获取每个 Task 的负责人
            for task in story.tasks:
                task.owner = await session.get(User, task.owner_id)

    return team

这种做法在简单场景下确实很直观,能够快速上手。ORM 的类型安全特性也能在编译时发现一些错误,而且与数据库表结构的一一对应关系让代码容易理解。但当我们面对真正的业务场景时,这种方式的缺陷很快就暴露出来了。

最致命的问题是 N+1 查询。虽然代码看起来很清晰,但执行时会产生大量的数据库查询。每当我们访问一个关联关系时,ORM 就会发起一次新的查询。在深层嵌套的情况下,查询数量会呈指数级增长。更糟糕的是,这种性能问题在开发阶段不容易发现,只有当数据量积累到一定程度后才会显现出来,那时候往往已经太晚了。

代码的组织方式也是个问题。数据获取的逻辑散落在各个嵌套的循环中,业务逻辑和数据获取逻辑混在一起,难以阅读和维护。当需要修改业务规则时,开发者不得不在复杂的嵌套结构中寻找修改点,很容易引入新的 bug 。性能更是不可控,随着数据量的增长,查询效率会急剧下降,而这些性能瓶颈很难在代码层面直接观察到。

此外,相似的数据获取逻辑会在多个 API 中重复出现,导致大量代码冗余。当一个 API 需要获取”团队及其 Sprint”,另一个 API 需要”团队及其成员”时,即使它们的查询逻辑非常相似,也不得不重复编写。这违反了 DRY ( Don’t Repeat Yourself )原则,增加了维护成本。

模式二:使用 ORM 的 Eager Loading

@router.get("/teams/{team_id}", response_model=TeamDetail)
async def get_team(team_id: int, session: AsyncSession = Depends(get_session)):
    # 使用 joinedload 预加载关联数据
    result = await session.execute(
        select(Team)
        .options(
            joinedload(Team.sprints)
            .joinedload(Sprint.stories)
            .joinedload(Story.tasks)
            .joinedload(Task.owner)
        )
        .where(Team.id == team_id)
    )
    return result.scalar_one()

为了解决 N+1 查询问题,ORM 提供了 Eager Loading 机制,让我们可以通过 joinedloadselectinload 等方式预先加载关联数据。代码变得更简洁了,性能问题也得到了缓解。但这种方案也带来了新的挑战。

最明显的问题是笛卡尔积。当我们使用多层 JOIN 预加载关联数据时,数据库返回的数据量会急剧膨胀。比如一个团队有 10 个 Sprint ,每个 Sprint 有 10 个 Story ,每个 Story 有 10 个 Task ,那么 JOIN 的结果集会包含 1000 行数据,即使每行的数据量不大,也会给网络传输和内存占用带来压力。

更严重的问题是灵活性差。Eager Loading 的策略是在代码中硬编码的,所有使用同一个 Model 的 API 都会执行相同的预加载逻辑。但不同的 API 往往需要不同的数据。比如一个 API 只需要团队的基本信息,另一个 API 需要团队的 Sprint ,还有一个 API 需要团队的成员。如果统一使用 Eager Loading 加载所有关联数据,就会出现过度获取的问题,前端不需要的数据也被查询和传输了,浪费了资源。

配置 Eager Loading 本身就很复杂。开发者需要理解 lazyjoinedloadselectinloadsubquery 等多种加载策略的区别,知道什么时候用哪一种,以及它们各自会有什么副作用。这种配置错误很容易导致性能问题或意外的数据加载行为。而且,这种”一刀切”的配置方式意味着所有 API 都使用相同的加载策略,无法针对特定场景进行优化。

模式三:手动组装数据

@router.get("/teams/{team_id}", response_model=TeamDetail)
async def get_team(team_id: int, session: AsyncSession = Depends(get_session)):
    # 1. 批量获取所有需要的数据
    team = await session.get(Team, team_id)

    sprints_result = await session.execute(
        select(Sprint).where(Sprint.team_id == team_id)
    )
    sprint_ids = [s.id for s in sprints_result.scalars().all()]

    stories_result = await session.execute(
        select(Story).where(Story.sprint_id.in_(sprint_ids))
    )
    story_ids = [s.id for s in stories_result.scalars().all()]

    tasks_result = await session.execute(
        select(Task).where(Story.id.in_(story_ids))
    )
    tasks = tasks_result.scalars().all()

    owner_ids = list(set(t.owner_id for t in tasks))
    owners_result = await session.execute(
        select(User).where(User.id.in_(owner_ids))
    )
    owners = {u.id: u for u in owners_result.scalars().all()}

    # 2. 手动组装数据结构
    sprint_dict = {s.id: s for s in sprints_result.scalars().all()}
    story_dict = {s.id: s for s in stories_result.scalars().all()}

    for story in story_dict.values():
        story.tasks = [t for t in tasks if t.story_id == story.id]
        for task in story.tasks:
            task.owner = owners.get(task.owner_id)

    for sprint in sprint_dict.values():
        sprint.stories = [s for s in story_dict.values() if s.sprint_id == sprint.id]

    team.sprints = list(sprint_dict.values())

    return team

为了获得最优的性能和精确的数据控制,有经验的开发者会选择手动组装数据。这种方式完全掌控查询逻辑,可以精确控制每个查询的 SQL 语句,避免不必要的数据库访问。通过批量查询和智能的数据组装,可以获得最佳的性能,而且没有冗余数据。

但这种方式的代价是代码变得非常冗长。如上面的例子所示,为了获取一个团队的完整信息,我们需要编写多个查询,手动构建数据字典,然后通过嵌套循环组装数据。代码的长度和复杂度都大幅增加,而真正表达业务逻辑的代码反而被淹没在数据组装的细节中。

更容易出错也是个大问题。手动组装数据涉及到大量的索引操作和循环嵌套,很容易出现索引错误、空指针引用等 bug 。而且这些错误往往只有在运行时、特定数据条件下才会暴露,难以在开发阶段发现。

维护成本更是高昂。当业务规则发生变化时(比如需要添加一个新的关联关系),开发者需要在所有相关的 API 中修改数据组装逻辑。如果遗漏了某个地方,就会导致数据不一致。而且,相似的数据组装逻辑会在多个 API 中重复出现,违反了 DRY 原则。

最根本的问题是,这种代码已经变成了纯粹的数据搬运工,看不出任何业务意图。代码中充满了字典操作、循环嵌套、索引查找,而这些都是技术细节,与业务需求毫无关系。新加入的团队成员很难从这些代码中理解业务逻辑,业务知识的传递变得异常困难。

模式四:使用 GraphQL

type Query {
    team(id: ID!): Team
}

type Team {
    id: ID!
    name: String!
    sprints: [Sprint!]!
}

type Sprint {
    id: ID!
    name: String!
    stories: [Story!]!
}

type Story {
    id: ID!
    name: String!
    tasks: [Task!]!
}

type Task {
    id: ID!
    name: String!
    owner: User!
}

GraphQL 确实是一个很有吸引力的方案。前端可以按需获取数据,需要什么字段就查什么字段,不会有过度获取的问题。它提供了类型安全的查询接口,而且通过 DataLoader 可以自动解决 N+1 查询问题。这些特性让 GraphQL 在前端开发中广受欢迎。

但 GraphQL 的学习曲线非常陡峭。开发者需要学习全新的查询语言、Schema 定义、Resolver 编写、DataLoader 配置等一堆概念,这与 REST API 的直观性形成了鲜明对比。更麻烦的是,GraphQL 的过度灵活性给后端带来了巨大的挑战。前端可以构造任意复杂的查询,有些查询甚至可能是开发者没有想到过的,这导致后端很难进行针对性的优化。当一个查询嵌套了 10 层,返回了数百万条数据时,数据库和服务器都会面临巨大的压力。

调试 GraphQL API 也比调试 REST API 复杂得多。当一个 GraphQL 查询出错时,错误信息往往很难定位到具体的问题源头。而且 GraphQL 需要额外的服务器和工具链支持,无法直接利用现有的 FastAPI 生态系统。比如 FastAPI 的依赖注入、中间件、自动文档生成等特性,在 GraphQL 中都无法直接使用。

还有一个更深层次的问题是 ERD 和用例的界限模糊。GraphQL 的 Schema 同时扮演了实体模型和查询接口两个角色。当我们设计一个 GraphQL Schema 时,很难确定应该按照实体来组织(一个 Type 对应一个数据库表),还是按照用例来组织(不同的业务场景需要不同的字段)。这导致最佳实践不清晰,不同的项目、不同的开发者可能有完全不同的组织方式。

而且随着业务增长,所有的用例都会堆砌在同一个 Schema 中,导致 Schema 膨胀,难以维护。权限控制也变得异常复杂。不同的 API 端点可能有不同的权限要求,但它们可能都查询同一个实体(比如 User ),在 GraphQL 中很难针对不同的查询场景应用不同的权限规则。

1.2 问题根源分析

上面我们探讨的所有模式,虽然表面上的问题各不相同,但它们的核心困境其实是一致的。

问题 1:业务模型与数据模型混淆

# SQLAlchemy ORM 同时扮演两个角色:
# 1. 数据模型(如何存储)
# 2. 业务模型(业务概念)

class Team(Base):
    __tablename__ = 'teams'

    id = Column(Integer, primary_key=True)
    name = Column(String)

    # 这是数据库的外键关系,还是业务关系?
    sprints = relationship("Sprint", back_populates="team")

在传统的 ORM 开发中,业务模型和数据模型是混在一起的。看看这个例子,Team 类既表达了业务概念(团队是什么),又承载了数据模型的细节(如何在数据库中存储)。当我们在 sprints 字段上定义 relationship 时,这到底是在描述一个业务关系(团队有多个 Sprint ),还是在声明一个数据库外键约束?这种模糊性会导致很多问题。

数据库的设计约束会直接影响我们的业务建模。比如,如果数据库中的 teams 表没有直接到 users 的外键,而是通过中间表 team_members 关联,那么在 ORM 中我们也必须通过这个中间表来定义关系。这意味着业务模型被迫适应数据库的实现细节,而不是反过来。

更严重的是,这种方式无法表达跨库、跨服务的业务关系。现代系统中,数据可能分布在不同的数据库中,甚至存储在外部服务里。比如用户的基本信息在 PostgreSQL ,而用户的偏好设置在 MongoDB ,用户的实时状态在 Redis 中。ORM 的 relationship 无法跨越这些边界,业务模型因此被限制在了单一数据库的范围内。

问题 2:依赖方向错误

传统架构的依赖方向:
┌─────────────┐
│   API Layer │  ← 依赖于
└──────┬──────┘
       │
       ↓
┌─────────────┐
│ ORM Models  │  ← 依赖于
└──────┬──────┘
       │
       ↓
┌─────────────┐
│  Database   │
└─────────────┘

问题:业务规则依赖于数据库实现!

这违反了 Clean Architecture 的依赖规则。正确的依赖关系应该是:业务规则最稳定,不依赖任何外层;数据库是实现细节,应该依赖业务规则;当数据库变化时,业务规则不应该受影响。但传统架构的依赖方向恰恰相反,业务规则被数据库的实现细节所绑架。

问题 3:缺少业务关系的显式声明

# 传统方式:业务关系隐藏在查询中
async def get_team_tasks(team_id: int):
    # "团队的任务"这个业务概念隐藏在 SQL WHERE 中
    result = await session.execute(
        select(Task)
        .join(Sprint, Sprint.id == Task.sprint_id)
        .where(Sprint.team_id == team_id)
    )
    return result.scalars().all()

业务关系没有被显式声明出来,这是个很隐蔽但危害很大的问题。看看这个例子,”团队的任务”是一个清晰的业务概念,但这个概念被隐藏在 SQL 的 JOIN 和 WHERE 子句中。新加入团队的成员需要阅读大量代码才能理解系统中有哪些业务关系,这些关系是如何定义的。更糟糕的是,没有自动化的方式来检查业务关系的一致性。当需求变化需要修改某个关系时,开发者很难找到所有相关的代码,很容易遗漏某个地方,导致业务逻辑的不一致。

问题 4:中间表的技术暴露

在 SQLAlchemy ORM 中,多对多关系需要显式定义中间表,这导致技术细节泄漏到业务层。

# SQLAlchemy ORM:必须定义中间表
class Team(Base):
    __tablename__ = 'teams'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    # ORM relationship 需要指定中间表
    members = relationship("User",
                          secondary="team_members",  # 必须指定中间表
                          back_populates="teams")

class User(Base):
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)
    name = Column(String)

    teams = relationship("Team",
                        secondary="team_members",  # 必须指定中间表
                        back_populates="members")

# 中间表(技术实现细节)
class TeamMember(Base):
    __tablename__ = 'team_members'
    team_id = Column(Integer, ForeignKey('teams.id'), primary_key=True)
    user_id = Column(Integer, ForeignKey('users.id'), primary_key=True)
    role = Column(String)  # 可能还有额外字段

# 查询时需要关心中间表的存在
@router.get("/teams/{team_id}")
async def get_team_members(team_id: int, session: AsyncSession):
    # 必须通过中间表查询
    result = await session.execute(
        select(User)
        .join(TeamMember, TeamMember.user_id == User.id)  # 中间表暴露
        .where(TeamMember.team_id == team_id)
    )
    return result.scalars().all()

这个问题的根源在于,ORM 的多对多关系需要显式定义中间表,这导致技术细节直接泄漏到业务层代码中。业务代码必须知道 team_members 中间表的存在,查询时也需要显式地 join 这个中间表。这增加了代码复杂度,更重要的是,业务逻辑被数据库的实现细节所绑架。

更深层的问题是业务语义变得模糊。TeamMember 到底是一个有意义的业务概念,还是纯粹的技术实现?如果中间表还有额外的字段(比如 role 表示用户在团队中的角色,joined_at 表示加入时间),这些字段应该被建模为独立的实体吗?不同的开发者可能给出不同的答案,缺乏统一的指导原则。

数据组装也因此变得复杂。查询”团队的所有成员”需要 join 中间表,查询”用户所属的团队”也需要 join 中间表。所有涉及多对多关系的查询都变得冗长和难以理解。当业务规则要求”获取用户在所有团队中的角色”时,情况就更加复杂了。这些技术细节让业务逻辑的实现变得异常沉重。

对比:Pydantic-Resolve ERD 的方式

# ERD:业务概念清晰,无需关心中间表
class TeamEntity(BaseModel, BaseEntity):
    """团队实体 - 业务概念"""
    __relationships__ = [
        # 直接表达"团队有多个成员"的业务关系
        Relationship(
            field='id',
            target_kls=list[UserEntity],
            loader=team_to_users_loader  # loader 内部处理中间表
        ),
    ]
    id: int
    name: str

class UserEntity(BaseModel, BaseEntity):
    """用户实体 - 业务概念"""
    __relationships__ = [
        # 直接表达"用户属于多个团队"的业务关系
        Relationship(
            field='id',
            target_kls=list[TeamEntity],
            loader=user_to_teams_loader
        ),
    ]
    id: int
    name: str

# Loader 实现细节:中间表只在这里出现
async def team_to_users_loader(team_ids: list[int]):
    """加载团队成员 - 内部处理中间表"""
    async with get_session() as session:
        # 只有这里需要知道中间表的存在
        result = await session.execute(
            select(User)
            .join(TeamMember, TeamMember.user_id == User.id)
            .where(TeamMember.team_id.in_(team_ids))
        )
        users = result.scalars().all()

        # 构建映射
        users_by_team = {}
        for user in users:
            for tm in user.team_memberships:
                if tm.team_id not in users_by_team:
                    users_by_team[tm.team_id] = []
                users_by_team[tm.team_id].append(user)

        return [users_by_team.get(tid, []) for tid in team_ids]

关键差异

维度 SQLAlchemy ORM Pydantic-Resolve ERD
中间表位置 暴露在业务层 隐藏在 loader 实现中
业务语义 技术关系 (secondary) 业务关系 (团队包含成员)
查询代码 需要 join 中间表 loader.load(team_id)
代码位置 分散在多处 集中在 loader
测试 依赖数据库表结构 可 mock loader

架构优势

传统方式:
Team → TeamMember (中间表) → User
业务层需要知道中间表的存在

Pydantic-Resolve 方式:
Team → User (业务关系)
中间表是数据层的实现细节,业务层不关心

这意味着:

  1. 业务模型纯净 :Team 和 User 的关系直接表达业务语义

  2. 技术细节封装 :中间表的存在被封装在 loader 中

  3. 灵活的存储策略

    • 数据库可以用中间表实现
    • 也可以用 JSON 字段存储
    • 甚至可以是外部服务(如 LDAP )
    • 业务层代码无需修改
  4. 易于理解 :新人看到 ERD 就能理解业务关系,不需要先学习数据库设计


2. Clean Architecture 思想

2.1 核心原则

Clean Architecture 由 Robert C. Martin (Uncle Bob) 提出,核心思想是:

“Software architecture is the art of drawing lines that I call boundaries.” 软件架构的艺术在于画界线。

原则 1:依赖规则

外层依赖内层,内层不依赖外层。

                ↓ 依赖方向
    ┌─────────────────────┐
    │   Frameworks &      │  外层
    │   Drivers           │  (实现细节)
    ├─────────────────────┤
    │   Interface         │
    │   Adapters          │
    ├─────────────────────┤
    │   Use Cases         │
    │   (Application)     │
    ├─────────────────────┤
    │   Entities          │  内层
    │   (Business Rules)  │  (核心)
    └─────────────────────┘

遵循依赖规则有几个关键点需要注意。首先,内层不知道外层的存在,这意味着核心业务逻辑不依赖于任何框架、数据库或 UI 的细节。其次,内层不包含外层的信息,比如业务规则不应该知道数据是用 PostgreSQL 还是 MongoDB 存储的。最后,外层的实现可以随时替换而不影响内层,这意味着我们可以从 SQLAlchemy 切换到 MongoDB ,或者从 FastAPI 切换到 Django ,而业务逻辑代码无需修改。

原则 2:业务规则独立

# ❌ 错误:业务规则依赖数据库
class Task:
    def calculate_priority(self, session):
        # 业务逻辑被数据库实现细节污染
        if self.assignee_id in session.query(TeamMember).filter_by(role='lead'):
            return 'high'

# ✅ 正确:业务规则独立
class Task:
    def calculate_priority(self, assignee_roles):
        # 业务逻辑只依赖业务概念
        if 'lead' in assignee_roles:
            return 'high'

原则 3:跨边界的数据传递

# 内层定义数据结构
class TaskEntity(BaseModel):
    id: int
    name: str
    assignee_id: int

# 外层负责转换
def task_entity_to_orm(entity: TaskEntity) -> Task:
    return Task(
        id=entity.id,
        name=entity.name,
        assignee_id=entity.assignee_id
    )

2.2 依赖规则

在 Web 开发中,依赖规则可以这样理解:

┌────────────────────────────────────────────────────┐
│         Presentation Layer (外层)                   │
│  - FastAPI Routes                                   │
│  - Request/Response Models                          │
│  - 依赖: Application Layer                          │
└────────────────────────────────────────────────────┘
                    ↓
┌────────────────────────────────────────────────────┐
│      Application Layer (Use Cases)                 │
│  - 业务用例(获取用户、创建订单)                    │
│  - 依赖: Domain Layer                               │
└────────────────────────────────────────────────────┘
                    ↓
┌────────────────────────────────────────────────────┐
│           Domain Layer (内层)                      │
│  - Entities (业务实体)                              │
│  - Business Rules (业务规则)                        │
│  - Value Objects (值对象)                           │
│  - 不依赖任何外层                                    │
└────────────────────────────────────────────────────┘
                    ↓
┌────────────────────────────────────────────────────┐
│    Infrastructure Layer (最外层)                   │
│  - Database (SQLAlchemy)                           │
│  - External Services                               │
│  - File System                                     │
└────────────────────────────────────────────────────┘

关键洞察

  • Entities 不应该知道 SQLAlchemy 的存在
  • Business Rules 不应该知道数据库表结构
  • Use Cases 不应该知道 HTTP 协议的细节

2.3 在 Web 开发中的应用

传统架构的问题

# 传统方式:所有层次耦合

# Domain Layer (应该独立,但实际上依赖了 ORM)
class User(Base):  # ← SQLAlchemy Base
    __tablename__ = 'users'
    id = Column(Integer, primary_key=True)

# Application Layer (应该只依赖 Domain ,但直接使用了 ORM)
async def create_user(data: dict, session: AsyncSession):
    user = User(**data)  # ← 直接使用 ORM Model
    session.add(user)
    await session.commit()

# Presentation Layer
@router.post("/users")
async def api_create_user(data: dict, session=Depends(get_session)):
    return await create_user(data, session)  # ← 暴露了数据库细节

这段代码暴露了传统架构的核心问题。SQLAlchemy 虽然建立了对象关系映射( ORM ),让数据库表可以通过 Python 对象来操作,但这种映射关系过于紧密。ORM Model 既承担了数据持久化的职责,又要表达业务概念,导致对象无法自由地代表业务模型。业务实体被数据库的实现细节所绑架,每个字段、每个关系都必须与数据库表结构一一对应,完全失去了作为独立业务概念存在的自由。

更深层次的问题包括:

  1. Domain Layer 被 SQLAlchemy 绑定 :业务实体继承了 SQLAlchemy 的 Base ,无法独立于数据库存在
  2. 业务逻辑无法脱离数据库测试 :编写单元测试时必须启动完整的数据库环境,大大降低了测试效率
  3. 切换数据库需要修改所有层 :当从 PostgreSQL 迁移到 MongoDB 时,所有使用 ORM Model 的代码都需要重写

。。。

作者: tangkikodo | 发布时间: 2026-01-11 10:26


37. 北京的 AGI-Next 闭门会,有人在现场么?谈论了点什么?

如题:

image.png

作者: ToDayMkCode | 发布时间: 2026-01-11 14:26


38. 小米 13 手贱升了 hyperos3,崩了

不是米粉也不是米黑。
一个月前小米 13 手贱升了 hyperos3,电池续航从一天降到 0.3 天,快充也没了,和家人打打视频电话( volte/nr )动不动就卡画面,只能换微信打,各种小 bug,又降不回去,也没有 root 。
失望,准备 ld 淘汰的 iphone13 当主力机了。

作者: ipfox | 发布时间: 2026-01-08 23:55


39. Incremark Solid 版本上线: Vue/React/Svelte/Solid 四大框架,统一体验

Incremark 现已支持 Solid ,至此完成了对 Vue 、React 、Svelte 、Solid 四大主流前端框架的全面覆盖。

为什么要做框架无关

市面上大多数 Markdown 渲染库都是针对特定框架开发的。React 生态有 react-markdown ,Vue 生态有各种 v-md 组件。这带来几个问题:

  1. 重复造轮子 :每个框架社区都在独立实现相似的功能
  2. 能力不一致 :不同框架的实现质量参差不齐
  3. 团队切换成本 :换框架意味着重新学习新的 API

Incremark 采用不同的思路:核心逻辑与 UI 框架完全解耦

@incremark/core 负责所有解析、转换、增量更新的工作,输出的是框架无关的数据结构。各框架包(@incremark/vue@incremark/react@incremark/svelte@incremark/solid)只需要把这些数据渲染成对应框架的组件即可。

这意味着:

  • 核心能力一次实现,四个框架同时受益
  • Bug 修复和性能优化自动同步到所有框架
  • API 设计保持高度一致,切换框架几乎零学习成本

包结构

┌───────────────────────────────┐
│       @incremark/core         │
│                               │
│  增量解析 · 双引擎 · 插件系统  │
└───────────────┬───────────────┘
                │
                ▼
┌───────────────────────────────┐
│  @incremark/vue               │
│  @incremark/react             │
│  @incremark/svelte            │
│  @incremark/solid  ← NEW      │
└───────────────┬───────────────┘
                │
                ▼
┌───────────────────────────────┐
│       @incremark/theme        │
│                               │
│     样式 · 主题 · 代码高亮     │
└───────────────────────────────┘

增量解析

传统 Markdown 渲染器在流式场景下存在性能问题:每次新内容到达都要重新解析整个文档,复杂度是 O(n²)。

Incremark 只处理新增内容,已解析的块不再重复处理,复杂度降至 O(n)。

四个框架的用法对比

四个框架的组件 API 完全一致,只是语法风格不同:

Vue

<script setup>
import { IncremarkContent } from '@incremark/vue'
// ...
</script>

<template>
  <IncremarkContent :content="content" :is-finished="isFinished" />
</template>

React

import { IncremarkContent } from '@incremark/react'
// ...

<IncremarkContent content={content} isFinished={isFinished} />

Svelte

<script>
import { IncremarkContent } from '@incremark/svelte'
// ...
</script>

<IncremarkContent content={content} isFinished={isFinished} />

Solid

import { IncremarkContent } from '@incremark/solid'
// ...

<IncremarkContent content={content()} isFinished={isFinished()} />

可以看到,除了各框架本身的响应式语法差异( Vue 的 ref、React 的 useState、Svelte 的 $state、Solid 的 createSignal),组件的使用方式完全统一。

在线演示

链接

MIT 许可证。

作者: 1244943563 | 发布时间: 2026-01-10 19:12


40. Gemini Code Assist 插件是如何用来做代码审查?

RT ,网上找了一圈,只有 gemini cli 来审查代码。

作者: Hyvi | 发布时间: 2026-01-11 15:33


41. 大模型写的代码几乎一摸一样

提了一个项目需求,让 chatgpt 分析,把分析的结果给 glm 4.7 和 claude code 4.5 ,发现两者写的代码几乎一摸一样。。。。。

作者: guotie | 发布时间: 2026-01-09 08:53


42. 解决了一个非常棘手的问题,内心止不住的开心。

15 年前的项目,sqlserver2008r2

php 5.6 / 7 项目

开发环境 mac 26.2 的系统。

各种编译 pdo_sqlsrv 扩展终于解决了。可以顺畅开发了

主要故障源于 arm 架构无法编译 pdo_sqlsrv 低版本的扩展。

mac 的 odbc17 只支持 tls1.2 以上。 sqlserver2008r2 不支持 tls1.2

odbc13 已经不可用。这顿捣鼓

搞了两天两夜 可算搞定了。能睡个好觉

作者: gyinbj | 发布时间: 2026-01-10 18:49


43. [Antigravity/反重力] 免 TUN/强制代理/除臭补丁/代理补丁/完整开源学习

缘由

一切都基于论坛某放了个成品 DLL…导致我的反重力时不时崩溃

我一直以为是Antigravity本身的问题,更新最新版也无济于事,就没去使用了,直到最近拉了几个家庭组想搞一个 2api 结果发现是不是崩,让我很难受 :bili_020:

最后被我追述到来源是一个除臭补丁 DLL

我甚至都忘了什么时候放进去的

时不时崩溃一下(这一崩我也很崩溃) 打开就会崩溃并且需要连续打开好几次才能稳定下来。

最后不得已删掉 dll ,本想找某, 结果发现他的帖子止步于 11 月,没有了后续回复和更新,可能不关注了, 我就寻思自己搞一个开源 DLL ,就当学习了, 手搓+AI 的帮助直接飞起~ 一时之间居然让我回到了以前为了写 CF 挂装逼,去硬啃那些驱动,看不懂,我真的看不懂 :bili_020: , 那些驱动哪怕现在有了 AI 帮助说不定可以看懂并且一点点修复可是好像已经无用了,没人玩 CF 了,我也再回不到那个夏天了。

咳咳,说多了


总结

总结一下,在这个过程御三家帮了大忙,

1 、Gemini 收集信息和总结开发文档

2 、Claude Sonnet 4.5 搭框架

3、Claude Opus 4.5 写核心Hook注入 ,以及修复编译报错 ( Sonnet4.5 这一块真的拉,很多语法错误)

4 、最后就是GPT5.2 收尾最后 20% ➕ 核查、完善其他功能

整体用时五小时,其中最消耗时间的就是反复测试代理是否有效,协议是否完善,转发协议等等手搓+AI

socks5 生效,http 不生效,http 不生效,结果 socks5 又不生效,最后一遍遍在 Opus4.5 和 GPT5.2 中反复折磨。

PS:GLM4.7 帮了大忙,GLM4.7 居然帮我指出了 socks5 的 hook connect 方法时读取地址字节异常问题导致崩溃或者代理不生效,这个惊到我了,御三家都没找出问题,被他找出来了还修复了,虽然只有几行,果断继续,然后..后面果然一大坨 :bili_020:

稳定使用一整天,不崩溃,不占内存,并且支持socks5http 怎么并发都没事,GUI 好像也没啥并发?管他呢,可以不用,不能没有 :tieba_025:

macos 版本属于有生系列了~ 等后续继续研究吧(我不一定啊,没有 macos 无法测试所以大概率不会考虑写和兼容了)亦或者有后继者 可以根据我这个开源项目继续研究~

写了一个初版,能编译?! socks5 可以用?!搞定!直接开始测试,还能顺便 DLL 测试稳定性,果断切到 Antigravity 里面,主要原因是Cursor都烧光二个 Pro 号额度了 :bili_083:


用的 Hook 框架是:minhook

参考 DLL: https://linux.do/t/topic/1189424


开源地址,记得点赞

yuaotian/antigravity-proxy: 给 Antigravity 强制开启代理免 TUN


某佬相关帖子

Antigravity 除臭补丁 for Win 10 - 资源荟萃 / 资源荟萃, Lv1 - LINUX DO

作者: yuaotian | 发布时间: 2026-01-12 06:56


44. 甲骨文的免费 ARM 实例收费问题

Oracle 云升级了付费账号,创建了一个 4/24G 内存的 ARM 实例,过了几天修改实例把内存 24G 改成 25G ,Cost 报表里没产生费用明细,月底出账单发现依旧没有产生费用。
难道 A1 的 ARM 实例不是超出 4 核 24G 会收费的吗?

作者: none | 发布时间: 2026-01-11 09:51


45. 解决老账号 Google One 提示 “此账号无法订阅 Google One AI Pro” 解决方法

提示下antigravity增加周限额了,专门为 antigravity 而半价年付需要谨慎。

之前我一直在用老账号老提示“此账号无法订阅 Google One AI Pro”,变更过地址,一直不行,搁置许久。今天心血来潮又折腾了一下,终于搞定了。分享下处理步骤:

  1. 访问以下网址 https://policies.google.com/terms ,登录自己的账号即可查看账号当前的国家或地区,中国的话,请换区(注意,申请换区换区理由选“其他”;一年只能修改一次) —– 换成功了,没有效果
  2. 看下“付款资料” https://pay.google.com/gp/w/home/settings ,看下付款地区是否有中国的,有的话就删除(底部有“关闭支付资料”按钮,可以删除当前默认的)。增加一个其他支持的国家的。
  3. 如果还是不行,看下是否开通过 google enterprise 的试用,如果有,请关闭 (之前有一个月的免费使用活动的羊毛,gemini 告诉我需要关闭)

完事儿,可以再重新进入 https://one.google.com/about/plans 页面试试看出现没出现半价包年的优惠。

作者: tyrad | 发布时间: 2026-01-09 15:19


46. 大模型 agents 为什么不自带 skills?

为什么大模型不自带 skills ?可能所有 skills token 太多了,那可以维护一个云端技能列表,模型按需加载。

作者: ethusdt | 发布时间: 2026-01-09 14:32


47. google ai pro 99.99 美刀一年值得购买吗

不想折腾学生白嫖的原因:

1. 懒得搞各种学生的虚假认证,想想就头大
2. 比较爱惜自己手上的 google 账号,担心搞了学生后指不定哪天被风控了,限制一些功能。

作者: YanSeven | 发布时间: 2026-01-06 06:55


48. 分享一个免费使用内网穿网站 tikrok.cc

新开了一个网站,tikrok.cc ,目前免费使用。 没什么浏览,去 google 搜索了一下,都搜不到。

作者: 5wunian | 发布时间: 2026-01-11 00:52


49. 各位大佬,店内人脸识别方案有推荐吗

记性太差,守店老会忘记再进店的老顾客;

各位大佬有推荐稳定的人脸识别的软/硬件不;

作者: tmdgri | 发布时间: 2026-01-10 12:07


50. 老项目升级推荐 Podman

最近计划重构停滞升级了 N 年的老项目。感叹目前技术的发展。
跟大家分享一些发现

Podman 部署 (真的爽到极致,线上服务器打包,线下开箱即用,再也不用怕网路问题了)

AlmaLinux 感觉比 debian 好啊,只是感觉,没有具体比较

FlightPHP 是真快啊,简单。终于可以完全掌控代码了,Laravel 给了我太多不理解的代码,虽然我很爱她

litestar 看起来不错哟,AI 项目靠你了,反正代码也是 AI 写

GoLang 也不错,就用你来查询 GEO 吧,不懂 GO ,没关系,AI 写

ValKey 听说你比 redis 快,就你了

PostgreSQL 听说你比 Mysql 好,好的,你来代替 MySQL 吧

SvelteKit 简单易懂

Podman+microservices 天下为我所有

作者: Loser110 | 发布时间: 2026-01-12 03:00