我不会在你的 URL 中添加查询字符串
摘要
Susam Pal 讨论了在 URL 中避免使用查询字符串的做法,引用了 Chris Morgan 对简洁 URL 的倡导,以及这对 Web 开发和 SEO 的技术影响。
<p><a href="https://lobste.rs/s/vbit2a/i_will_not_add_query_strings_your_urls">评论</a></p>
查看缓存全文
缓存时间: 2026/05/09 16:42
# 我不会在你的 URL 中添加查询字符串
来源:https://susam.net/no-query-strings.html
作者:**Susam Pal**,2026年5月9日
昨晚,我的 RSS 阅读器中出现了一篇简短的博客文章,读起来仿佛是在直接对我说话。那是 Chris Morgan 的出色文章《我已禁止查询字符串》([I've banned query strings](https://chrismorgan.info/no-query-strings))。
## 目录https://susam.net/no-query-strings.html#contents
- 网络上的智慧 ([Wisdom on the Web](https://susam.net/no-query-strings.html#wisdom-on-the-web))
- 网络漫游 ([Wander on the Web](https://susam.net/no-query-strings.html#wander-on-the-web))
- 设计缺陷 ([Misfeature](https://susam.net/no-query-strings.html#misfeature))
- 损坏的 URL ([Broken URLs](https://susam.net/no-query-strings.html#broken-urls))
- 结论 ([Conclusion](https://susam.net/no-query-strings.html#conclusion))
## 网络上的智慧https://susam.net/no-query-strings.html#wisdom-on-the-web
Chris([https://chrismorgan.info/](https://chrismorgan.info/))是我在过去大约五年间一直关注其互联网评论的人。我第一次注意到他的评论,是在他在 Hacker News 上对我整理的 CSS 规则集留下了非常详细的[反馈](https://news.ycombinator.com/item?id=25321222#25322611)。我并非网页开发者。我的职业生涯大部分时间([https://susam.net/twenty-five-years-of-computing.html](https://susam.net/twenty-five-years-of-computing.html))都花在使用 C 和 C++ 进行系统编程上。然而,开发网站和编写小型 HTML 工具([https://susam.net/tag/html.html](https://susam.net/tag/html.html))一直是我长期的爱好。作为一名业余爱好者,我通过研究别人的做法来学习大部分网页开发技能:最早是在 2000 年代初查看我喜欢的网站的源代码,后来则是偶尔被实现新游戏或工具的冲动所驱使,查阅 MDN Web Docs([https://developer.mozilla.org/en-US/docs/Web/HTML](https://developer.mozilla.org/en-US/docs/Web/HTML))来学习实现功能所需的知识。以这种方式学习技能的一个问题是,你有时会养成流行但未必最优或正确的习惯。因此,当 Chris 评论我整理的样板 CSS 规则集时,对我来说真的非常有价值。那帮助我大幅改进了 CSS 技巧。事实上,他评论中的几条建议让我记忆犹新;每当我制作业余 HTML 项目时,我都会牢记这些建议:始终在链接中保留下划线,并[保留紫色](https://susam.net/more-purple-links-please.html)用于已访问链接。
自那以后,我一直关注 Chris 关于网页相关主题的文章和评论。他经常对网页相关项目提供极佳的反馈。每当我看到这样的评论,我都会仔细阅读,即使项目不是我做的。我总能从他的评论中学到一些美好且实用的东西。这里有一个最近的例子,来自 Lobsters 社区关于[RSS 中添加作者上下文](https://lobste.rs/s/crcktq/adding_author_context_rss#c_wb5ryy)的讨论。
## 网络漫游https://susam.net/no-query-strings.html#wander-on-the-web
几个月前,我创建了一个名为*Wander Console*的新项目。它是一个小型、去中心化、自托管的网页控制台,让访问者能够探索由独立个人网站所有者社区推荐的有趣网站和页面。例如,我的控制台位于此处:[susam.net/wander/](https://susam.net/wander/)。如果你点击那里的“Wander”按钮,该工具会加载一个由 Wander 社区推荐的随机个人网页。
该工具由一个实现控制台的 HTML 文件和一个 JavaScript 文件组成,网站所有者在 JavaScript 文件中定义相邻控制台列表以及他们推荐的网页列表。如果你将这两个文件复制到你的 Web 服务器,就能立即在网络上拥有一个活跃的 Wander 控制台。除了基本的 Web 服务器外,运行 Wander 控制台不需要任何服务器端逻辑或软件。你甚至可以在 Codeberg Pages 或 GitHub Pages 等受限环境中托管它。当你点击“Wander”按钮时,控制台会连接到其他远程控制台,获取网页推荐,随机选择一个并在你的 Web 浏览器中加载。它有点像现在已经停用的[StumbleUpon](https://en.wikipedia.org/wiki/StumbleUpon),但它是完全去中心化的。它也有点像网页环(web rings),只不过社区网络不限于环形结构;它是一个图结构,更加灵活。
目前已有超过 50 个网站托管此工具。它们共同推荐了超过 1500 个网页。你可以在[susam.codeberg.page/wcn/](https://susam.codeberg.page/wcn/)找到已知控制台及其推荐页面的最新快照。欲了解该工具的更多信息或在你的网站上设置它,请参阅[codeberg.org/susam/wander](https://codeberg.org/susam/wander#readme)。
## 设计缺陷https://susam.net/no-query-strings.html#misfeature
如果你好奇为什么我会在上一部分突然推广我的项目,那是因为我最近给该项目添加了一个我自己都不完全认同的有争议的功能。这个设计缺陷与本文相关。
在 Wander Console 0.4.0 版本中,我在加载网页时添加了对 `via=` 查询参数的支持。例如,如果你在 [susam.net/wander/](https://susam.net/wander/) 的控制台中遇到了 [midnight.pub](https://midnight.pub/),控制台会使用以下 URL 加载该页面:
```
https://midnight.pub/?via=https://susam.net/wander/
```
这使得被推荐网站的站长可以通过访问日志看到,这次访问源自某个 Wander 控制台。Chris 最近的[博客文章](https://chrismorgan.info/no-query-strings)批评了此类功能。他写道:
> 我不喜欢人们在 URL 中添加追踪信息。更不喜欢人们在我的 *我的* URL 中添加追踪信息。`https://chrismorgan.info/no-query-strings?ref=example.com`?我要求过吗?如果我想知道,我会查看 `Referer` 头;如果它不存在,那通常是有原因的。你在链接中添加这些内容,是在滥用你的用户。
我之前提到过,我不完全确定添加推荐查询字符串是否是好事。那我为什么还要添加它呢?我屈从于大众的要求。让我简要描述一下我在考虑并实现该功能时的心态。当我在 Codeberg 上第一次看到[功能请求](https://codeberg.org/susam/wander/issues/1#issuecomment-11795493)时,我的初始反应是犹豫。我不认为这是一个好功能。但当时我正忙于一些正在进行中的代数图论研究——这是另一个近期的爱好——而且截止日期临近,所以我没有太多时间仔细思考。事实上,Wander Console 的所有内容都是在我从研究中短暂休息时,利用很少的时间完成的。我在那个清晨头脑太累、无法阅读更多代数图论文献、急需休息时,大约在一个半小时内完成了控制台的第一版。在另一次这样的休息期间,我重新审视了那个功能请求,尽管心存疑虑,还是决定将其实现。在又一次这样的休息期间,我写下了这篇文章。
通常,我不喜欢在我的小项目中添加太多新功能。我希望它们保持有限的范围。我也希望它们随着时间推移变得稳定。当一个项目满足了我的一些基本需求后,我只想宣布它功能完整,再也不添加新功能。当然,我会修复错误。但我喜欢无尽地不断添加新功能。这就是我维护业余项目的风格。因此,我应该能很容易地忽略为控制台工具加载的 URL 添加推荐查询字符串的功能请求。但我认为,长期而高强度的研究工作使身心疲惫,对我产生了影响。
虽然我的直觉告诉我这不是一个好功能,但我无法准确地向自己阐述原因。所以我还是实现了推荐查询字符串功能。在此过程中,我在配置中添加了退出机制,这样如果有人不喜欢该功能,可以为自己禁用它。这是另一个错误。如果必须实现这样的有争议功能,它应该作为一个“选择加入”(opt-in)功能,而不是“选择退出”(opt-out)功能。由于我没有太多时间来推理该功能的影响,我只是不加批判地直接实现了它。正如《侏罗纪公园》中的那句名言所说:
> 你的科学家太专注于“能不能做到”,而没停下来想想“该不该做”。
## 损坏的 URLhttps://susam.net/no-query-strings.html#broken-urls
很快事实证明,我的直觉是正确的。实现该功能后,我最喜欢的页面之一拒绝在控制台中加载:
https://int10h.org/oldschool-pc-fonts/fontlist/
通常情况下,上述 URL 可以正常加载,但现在控制台在加载时通过添加查询字符串修改了 URL。修改后的 URL 无法加载。例如,尝试访问以下修改后的 URL:
https://int10h.org/oldschool-pc-fonts/fontlist/?foo
上述 URL 返回 HTTP 404 错误页面。现在,经过一段时间的沉淀和一些事后反思,我能阐述为什么在正常的 URL 中添加推荐查询字符串是如此糟糕的主意。修改 URL 会得到一个*新的* URL。新的 URL 可能指向完全不同的资源,或者根本不指向任何资源,即使修改看似微小,如添加一个看似无害的查询字符串。通过添加推荐查询字符串,我实际上破坏了我非常[喜爱](https://news.ycombinator.com/item?id=39419054#39439453)的网站的一个正常工作的 URL。这里还有一个道德问题:为了插入推荐查询字符串,替用户修改给定 URL 是否合适?我认为不合适。
## 结论https://susam.net/no-query-strings.html#conclusion
最终,我决定从 Wander Console 中移除推荐查询字符串功能。有人可能会问,为什么不能将该功能作为“选择加入”选项保留?答案是,一旦我认为该功能方向错误,我就不想再在软件中保留它。该项目仍然很新,我们仍处于 0.x 版本发布阶段,所以如果要移除功能,现在正是合适的时机。但我正在进行的研究工作让我没有时间去做这件事。最后,当 Chris 的文章《我已禁止查询字符串》([I've banned query strings](https://chrismorgan.info/no-query-strings))昨晚出现在我的阅读器中时,它给了我足够的推动力,让我从学术爱好中抽出一点时间,专注于移除那个考虑不周的功能。该功能现已消失。详见提交 [b26d77c](https://codeberg.org/susam/wander/commit/b26d77c4da9ec11b655ba64a4ae4f3af56e06370)。最新版本 0.6.0 中已不再包含它。
这是我将在未来可能制作的任何新业余项目中铭记的一课。如果我再次加载 URL,我会严格按照网站作者的意图加载。我绝不会在你的 URL 中添加查询字符串。
巴特·辛普森风格黑板 meme,写着:“我不会在你的 URL 中添加查询字符串。”
使用 [Simpsons Chalkboard Generator](https://enufstyle.com/generators/bart/) 和 [GIMP](https://www.gimp.org/) 制作
相似文章
Cloudflare CAPTCHA 针对至少包含一个 & 符号的 URL
Simon Willison 分享了一个技巧,配置 Cloudflare 的 Managed Challenge 仅对包含 & 符号的搜索 URL 触发,从而改善简单查询的可用性。
不要自己造轮子…
作者将“不要自己造轮子”的原则扩展到Web开发领域,反对自定义实现滚动、链接导航、文本选择等浏览器原生行为。
Matrix URIs:蒂姆·伯纳斯-李提出但从未实现的URL语法(1996)
本文讨论了Matrix URIs,这是蒂姆·伯纳斯-李在1996年提出的一种URL语法,但从未被实际实现。
我不再在 JavaScript 里把所有东西链在一起
开发者 Matt Smith 解释,为了调试更轻松、性能更好,他现在在 JavaScript 中更偏爱一步步写代码,而不是冗长的方法链。
结构性修复注入漏洞 (2012)
文章认为,注入漏洞(XSS和SQL注入)应通过输出转义和完全避免问题来从结构上预防,而不是仅仅依赖输入清理。