用一行代码修复 Dev.to 的滚动条错误
很多文章都是事后才写的,作者要么忘记了,要么理所当然地认为他们犯了逻辑上的跳跃。这篇文章是我在解决问题的过程中写的,甚至在我知道自己能够解决这个问题之前。我希望这篇文章能让你更好地了解错误修复过程,从头到尾。闲话少叙:
=====================================
我正在编辑文章时,发现了一个非常恼人的问题——我输入的每个字符都会导致滚动条出现和消失。我的第一反应是打开开发者控制台查看,结果看到的是:
-oooooooo/- .+ooooooooo: +ooo+ oooo/
+MMMMMMMMMMm+ -NMMMMMMMMMMs +MMMM: /MMMM/
+MMMNyyydMMMMy /MMMMyyyyyyy/ mMMMd mMMMd
+MMMm :MMMM. /MMMN /MMMM/ /MMMM:
+MMMm .MMMM- /MMMN dMMMm mMMMh
+MMMm .MMMM- /MMMMyyyy+ :MMMM/ +MMMM-
+MMMm .MMMM- /MMMMMMMMy hMMMm NMMMy
+MMMm .MMMM- /MMMMoooo: -MMMM+oMMMM-
+MMMm .MMMM- /MMMN yMMMmNMMMy
+MMMm +MMMM. /MMMN .MMMMMMMM.
+MMMMdddNMMMMo /MMMMddddddd+ sMMMMMMs
+MMMMMMMMMNh: .mMMMMMMMMMMs yMMMMs
.///////:- -/////////- .::.
Hey there! Interested in the code behind dev.to? Well you're in luck - we're open source! Come say hi, tell us what you're debugging, or even lend a hand in our repo - https://github.com/thepracticaldev/dev.to
Did you find a bug or vulnerability? Check out our bug bounty info here: https://dev.to/security
我很惊喜他们居然有安全漏洞悬赏计划。我继续研究悬赏计划,然后突然想起有个问题需要解决。
我打开了代码库,并在他们的问题中搜索“滚动条”。我偶然发现了https://github.com/thepracticaldev/dev.to/issues/3330,它描述了我遇到的确切问题。奇怪的是,只有一个用户报告了这个问题——这肯定比较罕见。或者人们不知道去 GitHub 报告这个问题。我创建AREPL的经验告诉我,对于人们费心报告的每一个问题,根据遥测数据,它可能已经发生过多次了。
在确认这是一个已报告的问题(带有“求助”标签!)后,我回到了开发工具。我注意到每次输入时,文本区域的高度样式都会发生变化。
之前:(无滚动条)
<textarea style="height: 968px;" class="articleform__body" id="article_body_markdown" placeholder="Body Markdown" name="body_markdown" ></textarea>
之后:(滚动条)
<textarea style="height: 924px;" class="articleform__body" id="article_body_markdown" placeholder="Body Markdown" name="body_markdown"></textarea>
这说得通——只有当高度不够显示所有内容时才会出现滚动条。但为什么高度会变呢?我又不是在换行,只是在现有行中添加了一个字符。真奇怪。
在这期间,我突然意识到——我可以写一篇关于这个的文章!这可以很好地记录我解决问题的思路。缺点是现在已经没有回头路了——如果我解决不了,我就会……
等等!我的天哪——我刚刚也遇到了一模一样的 bug:
由flux提供的可怕的黄色
我暂时只能用记事本来记录了。不过,万幸的是,我可以重现这个问题。我把下面这段文字粘贴到一个新的草稿里。结果……啊,问题并没有出现在那里。后来我才想起,根据问题报告,只有当代码行数达到一定数量时才会出现这种情况。于是,我又在前面加了 21 行,问题又出现了🐛!
下一个问题是,如果超过一定行数就会出现这种情况,为什么不是每个人都遇到这个问题?dev.to 的作者之间是否有一个不成文的约定,规定不要超过 21 行,就像 Twitter 的字符限制一样?我非常怀疑。我肯定漏掉了什么。也许与我输入的文本有关。
稍微修改了一下文本后,我发现如果删除行中的“I'll have a” The downside is there's no turning back now - If I fail to solve this I'll have a
,问题就不再出现了。只有当行超出草稿宽度时,问题才会出现。
现在我应该可以创建一个最小可复现的示例了。我打开一个新草稿,输入“aaa....”直到溢出一行,然后添加了 21 行。没有错误🤔。
我又稍微修改了一下结尾,发现错误只会在非常特殊的情况下发生,即空格超出了草稿宽度。任何普通字符都会直接跳到下一行,但你可以在现有行中添加任意数量的空格。
现在我可以复现了,这已经成功了一半。接下来是调试!
但在此之前,我想检查一下——我在设置中注意到我正在使用 V1 编辑器。这个问题在 V2 编辑器中还会出现吗?
没有。问题并没有出现在那里。
而且比我想象的还要严重——新用户默认使用 v2 编辑器,所以这个问题只影响像我这样的老用户,而且只影响一小部分老用户。
好吧,这真是浪费时间。:|
好的一面是,我可以把解决方案(切换到 v2 编辑器)发到问题评论里,这样应该能帮到一些人。为了自尊,我会花 10 分钟时间尝试解决这个问题。现在就开始。
事实证明,这个问题在 v2 编辑器中仍然存在,幸好我再次检查了一下。只是在 v2 编辑器中,当你的空格超过草稿宽度时,光标会停留在同一个位置,所以看起来一切正常。但稍微调整一下,仍然可能会重现错误。
现在我们开始调试吧。
终于,你说对了!
我为 textarea 元素的属性修改设置了一个断点。我编辑了该元素,导致高度发生变化,最终导致代码在断点处停止。可惜的是,该文件是空白的,所以我看不到代码停止的地方。不过,我查看了堆栈跟踪,发现在文件夹下TextareaAutosize.js
的 文件夹中有一个名为 的文件。所以,dev.to 的textarea 实现使用了preact (React 的变体)包。我用 Google 搜索了一下,找到了https://github.com/DisplaySweet/preact-textarea-autosize,结果出现了 404 错误。preact-textarea-autosize
node_modules
叹
因此我转到下一个链接——npm 包:
代码库链接指向https://github.com/evenius/react-textarea-autosize,它已经两年多没有更新了,而且也没有问题版块。这很好。然而,它是从一个更受欢迎的代码库fork 过来的,这个代码库确实存在问题,并且有一个演示网站。我搜索了相关问题,但没有找到那里报告的滚动条问题。我去了演示网站,结果发现,你可以在他们的演示网站上重现这个问题!所以问题可能不在于 dev.to 代码,而在于调用库的方式,或者库本身的问题。
现在已经凌晨一点了,所以我去睡觉了。睡眠对健康有益,大家。
第二天,我在15Five结束了一天的忙碌工作,读了大约 100 页的Scythe之后,又回去工作了。我把昨天的工作记录了下来,并在过程中发现了另一个react-autosize-textarea
名为. (不要与 混淆react-textarea-autosize
)的 React Textarea 包。它们有多少个??虽然 dev.to 上的 textarea 脚本显示为空白,但我注意到它是从捆绑文件中源映射过来的,于是我点击了左下角的小 {} 来美化打印,在库中搜索与最近提交匹配的代码,并确认我找的是正确的。呼。已经过去一个小时了,现在我终于可以开始调试了。
你不是已经打算这么做了吗?
呃,是的。总之:
我开始尝试调试打包的最小化代码,结果简直是一场噩梦。我很快做出了明智的决定——放弃,克隆了代码库,并制作了一个可复现的示例,其中包含一些我可以轻松调试的代码。
或者至少我应该这么做。接下来的一个小时,我又回去尝试调试打包的代码。
有趣的事实:看到断点所在的那一行了吗m=1/0
?它对应于这一行:
let maxHeight = Infinity;
你没看错,在 JavaScript 中,1/0 等于无穷大!如果你真的想看得晕头转向,试试在控制台里执行这行代码(按 F12 键打开):
"b" + "a" + +"a" + "a"
输出是 baNaNa。我是说,呃。你还指望什么呢⸮。不过,JavaScript 的 WTF 本身就是一本好书1。让我们回到正题。
我以为代码是每隔一个字符设置一次高度,但结果好像不是这样。calculateNodeHeight
执行时,textarea 的高度已经不一样了。我猜想这与原生 textarea 的工作方式以及 HTML 的约束有关。谜团越来越深了……
我尝试在Winmerge中比较两个文本区域对象,但没有发现任何可疑之处。
如果这是 HTML 的问题,那就该去学习一下了。我读了https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollHeight。然后我突然意识到:为什么一开始还要滚动条呢?浏览器屏幕边缘已经有滚动条了。已经把文本区域无限扩展到2 的react-textarea-autosize
长度了。滚动条完全没必要。
于是我在 Google 上搜索“禁用滚动条”,偶然发现了一篇论坛帖子,推荐了这种 CSS 样式overflow:hidden
。它可以禁用滚动条——你可以在这里hidden
阅读更多overflow
选项。把它应用到 textarea 样式上,问题就解决了!🎉
接下来我尝试了不同的页面布局——它还能在半窗口宽度下工作吗?四分之一窗口宽度下?手机上?iPad上?答案是肯定的,肯定的,肯定的,肯定的。
感谢 chrome devtools 的这个可爱功能,我能够从我的笔记本电脑上测试所有的移动布局,甚至不需要手机。
现在浏览器又不一样了。我把它放到IE浏览器里,结果吓坏了,页面竟然没有滚动条,这说明textarea必须得有滚动条!我的计划泡汤了!IE浏览器该死!3
但后来我注意到,页面甚至没有“保存更改”按钮——它已经完全崩溃了,我根本不用担心支持 IE。问题就这么解决了。
然后我尝试了 Edge。我输入了大约 19 行,但当我输入新行时,垂直滚动条开始随机闪烁。哇哦。你甚至可以在底部的页脚内输入内容——你甚至可以看到那里的光标。所以 Edge 已经有很多 bug 了(我怎么就不惊讶了)。添加后overflow:hidden
解决了垂直滚动条的问题,并且没有在其他地方引发其他问题。
最后我尝试了 Firefox。修复后,这个问题甚至在 Firefox 中都没有出现,Firefox 真棒!
确认修复有效后,我创建了一个PR。甚至不需要打开编辑器——我只需打开https://github.com/thepracticaldev/dev.to/blob/master/app/assets/stylesheets/preact/article-form.scss
,点击编辑铅笔图标,进行修改,然后提交即可。Github 自动创建了 fork 的仓库——然后我点击“创建 Pull 请求”,填写一个简短的模板描述修改内容,就大功告成了!
嗯,不完全是。审阅者有一条评论(审阅者总是这样),要求提供前后对比图。有了ShareX,提供起来相当简单。几天后,我的 PR 就被合并了!
你可以自己检查一下——创建一个新文章,右键单击文本区域,然后单击检查元素,下面.articleform__body
有一行 css,overflow: hidden
可以防止滚动条出现🎉
那么,我们可以从中得到什么呢?
- Bug 可以用意想不到的方式解决。你应该留意各种变通方法、捷径和其他新颖的方法来彻底绕过问题。这绝不是使用肮脏、难以理解的 hack 的借口。(看看你的正则表达式,亲爱的,爱你,但你确实遇到了一些问题)记住,过早优化是万恶之源,你阅读代码的时间会远远超过编写代码的时间。
- 进入开源世界,你不需要任何高深的算法知识,也不需要昂贵的MacBook。你只需要一个网页浏览器。随着repl.it等软件的进步,几乎所有事情都可以在云端完成。你可以用所有空闲的硬件空间来拍性感的黄瓜照片(恕不评判)。
- 更多的公司应该开源他们的代码。这样你就能免费贡献代码,还能获得免费的公关宣传。在某些情况下,贡献者可以成为员工,为你节省数千美元的招聘成本。最终,开源打破了“通过隐藏实现安全” 4 所带来的虚假安全感——开源意味着你必须确保代码安全,以免被人看到。尽管实际上只有少数人会费心寻找漏洞,其中大多数可能是安全研究人员或赏金猎人。你确实有安全赏金,对吧?
- 修复 Bug 的大部分工作在于重现 Bug、找出 Bug 发生的原因、找到修复方案并测试修复方案。编码只是其中很小的一部分。
- 遇到问题时,请尝试找到相关的 GitHub 仓库并向维护人员报告问题。只需提供详细的复现步骤,就能帮他们大忙5,有时仅仅是研究问题本身就能让你找到解决方法(或者让你觉得自己是个傻瓜,做了蠢事)。最后,如果代码是开源的,修复它也是有可能的!只是需要付出一些努力🔨。
-
如果你想深入研究技术,你“最多”能读几十亿行代码,内存就用完了。UTF-8 编码下,每个 ASCII 字符占一个字节,所以 4GB 的内存足够容纳 40 亿个字符。你懂的越多越好!~~~ ⭐ ↩
-
请注意,模糊性作为纵深防御措施是可以的,只是你不应该依赖它 。↩
-
一份好的 Bug 报告包含五个部分:A. 摘要 B. 复现步骤 C. 预期结果 D. 实际结果 E. 当前设置(例如:Windows、Chrome)以及你是否真的想要解决问题 F. 问题的图片/视频。这样的报告会让开发者对你赞不绝口😇。大多数问题只有 A 部分写得很糟糕,甚至连理解到底发生了什么都让人很沮丧 。↩