ChatGPT 网页版崩了?魔法哥重操旧业,写个用户脚本来修复

就在八月初的这几天,ChatGPT 网页版开始灰度上线一个新版本,但很快就有不少网友发现自己用不了了!

具体的症状是,登录 ChatGPT 没问题,但只要一开始对话,网页就会显示 "Oops, an error occurred! (Try again)",如下图所示:

用不了 ChatGPT 可是个大问题。怎么办?

分析问题

此时,如果我们在浏览器中按 "F12" 键,打开控制台,会看到 TypeError: n.toSorted is not a function 这样的报错信息。

我们前往 OpenAI 官方的服务状态页面( status.openai.com/ ),发现 ChatGPT 并无故障。再结合控制台报错信息,我们可以推断:这个问题的根源不在服务器端,而是在浏览器端

魔法哥使用的浏览器是 Chrome 的一个较早版本,而换用另一款 Chrome Canary 浏览器(这是 Chrome 面向开发者提供的测试版,内核版本较高),则可以正常使用 ChatGPT。这个结果进一步验证了上面的推断。

回顾控制台的错误消息,再进行一番查证,可以得出结论:ChatGPT 新版本的 JS 代码中使用了 Array.prototype.toSorted() 这个方法,它是在 ES2023 规范中引入的新特性,而这个方法只有在较新的 Chrome 110 或以上版本中才能使用(参见下图)。

如果我们使用的是较低版本的 Chrome,或者你使用的国产浏览器内核太旧,就会遇到本文开头描述的问题。最简单的解决方案就是升级自己的浏览器。但如果你的软硬件条件不允许,或者你所使用的浏览器内核还没有升上来,那就需要另想办法了。

解决方案

这些年浏览器端的技术特性一直在飞速迭代,这类 "老浏览器不支持新特性" 的问题其实一直都存在。网页的开发者们通常采用一种叫做 "polyfill" 的技术手段来解决这类问题------给老浏览器打补丁,把它不支持的某些特性通过一段额外的代码来补上,从而让它可以像新浏览器一样运行那些用到新特性的代码。

原本 polyfill 是网页的开发者应该操心的问题,但 ChatGPT 这次显然没有考虑到这一点。确实 ChatGPT 在技术上一直相当激进,比如他们家的桌面客户端就只支持最新版的 macOS 操作系统。

因此,魔法哥决定自己动手,写一个 "用户脚本" 来给 ChatGPT 网页版补上缺失的 polyfill,让它可以在老浏览器中正常运行。

用户脚本

有一个小秘密,很多人可能还不知道------我们在浏览网页时,是可以根据自己的需要对网页进行自定义修改的。通常有这三种方法:

  • 用户样式(向网页注入自定义 CSS 代码来修改样式)
  • 用户脚本(向网页注入 JS 代码来实现更多的自定义效果)
  • 浏览器插件(不仅可以自定义网页,还可以增强浏览器的功能)

这三种方法的功能强弱依次递增,开发复杂度也依次递增。对于本文面临的问题,"用户脚本" 是最合适的解决方案。

也就是说,我们可以写一个用户脚本,让它在打开 ChatGPT 网页版时,自动向网页注入一段我们准备好的 polyfill,从而让 ChatGPT 的 JS 代码在老浏览器中正常运行。

当然,用户脚本并不是 Chrome 原生提供的功能,我们需要借助一款名为 "Tampermonkey"(篡改猴) 的插件来实现。Tampermonkey 作为用户脚本管理器,可以在浏览器中自动针对不同网页运行对应的用户脚本。

开发用户脚本

如果只是解决本文提到的问题,这个用户脚本并不算复杂。它只需要实现以下效果就可以了:

  • 在浏览器打开 ChatGPT 网页版时,自动运行我们的这个用户脚本。
  • 这个用户脚本向页面注入一段 polyfill 代码,用来给浏览器补上 Array.prototype.toSorted() 这个方法。

这两项工作其实都不需要我们掌握任何 JS 编程能力,因为 Tampermonkey 本身就提供了一些配置项来实现对应的效果。最小化的示意代码如下:

js 复制代码
// ==UserScript==
// @name         Polyfill ChatGPT
// @match        https://chatgpt.com/*
// @require      http://xxxxx.com/polyfill.js
// ==/UserScript==

console.log('Userscript Loaded.')

简单解释一下这几行代码的作用:

  • @name 是用户脚本的名称。这个名称会在 Tampermonkey 插件的 "已安装用户脚本" 中显示。
  • @match 是用户脚本的匹配规则。只有当网页的 URL 符合这个规则时,才会运行我们的这个用户脚本。我们在这里指定了 ChatGPT 网页版的 URL。
  • @require 用来指定我们的用户脚本需要加载哪些外部 JS 脚本。你肯定看出来了,这里的 JS 文件地址是虚构的,我们稍后会把它替换成真实的地址。
  • 最后一行 console.log('Userscript Loaded.') 是用户脚本的主体代码。这里我们只是简单地向控制台输出一行日志,用来验证用户脚本是否成功加载。

准备所需的 Polyfill

既然 Tampermonkey 允许我们的用户脚本加载外部 JS 脚本,那么接下来,我们就需要完成以下任务:

  1. 得到 Array.prototype.toSorted() 的 polyfill 代码。
  2. 把这段 polyfill 代码保存为一个单独的 JS 文件。
  3. 把这个文件发布到某个公开的地址。

我们一步一步来。

首先 ,提到浏览器端的 polyfill,就不得不提到 core-js 这个开源项目( github.com/zloirock/co... )。它分门别类地整理了几乎所有 JS 新特性的 polyfill 代码,已经成为这个领域的事实标准。

接下来 ,我们利用 core-js 提供的 core-js-builder 工具,稍作配置,就可以生成我们需要的 polyfill 文件。

最后,我们把这个文件上传到一个公开的地址。如果你有自己的个人网站,完成这一步应该不在话下。或者你也可以利用 GitHub Gist 服务来把代码发布为一个可访问的 URL。

当然,如果你只想给自己一个人用,也可以在本机运行一个简易的静态 web 服务器,只要让这个文件能以 HTTP 形式被访问到即可。如果你连这一步也不想弄,可以直接使用本文末尾的资源。

安装用户脚本

我们在 Chrome 的插件工具栏中点击 Tampermonkey 插件的图标,在弹出的菜单中选择 "创建一个新脚本",会进入一个编辑器界面。

这个编辑器里有一些初始代码,我们把它清空,把上面那段示意代码粘贴进去,再把 @require 字段修改为真实的 polyfill 文件的地址,保存即可生效。

此时,我们切换到 "已安装的用户脚本" 标签下,应该可以看到我们刚刚创建的这个用户脚本。

走完这一步,我们就可以打开 ChatGPT 网页版,刷新页面,再发起一轮新对话,应该可以看到对话功能已经恢复正常,而且控制台也不再报错了!

开源

如果你懒得跟着上面的步骤自己做,或者你觉得上面的描述不够详细,那可以直接参考魔法哥写好的这个开源项目。相关的背景说明、源代码、构建脚本、使用方法都放在这个仓库里: github.com/UserScript/...

如果你也想打造自己的用户脚本,并分享给更多的人使用,那这个仓库也会是一个不错的参考。此外,估计有朋友会在安装 Tampermonkey 插件时遇到困难,因此 README 中也提供了必要的帮助信息。

这个项目还不错吧?如果觉得有用,不妨点个 Star,支持一下魔法哥的开源精神。

小结

假如你是一名程序员,相信你已经 Get 到了今天的知识点,并且打开了一扇叫做 "用户脚本" 的大门。这确实是一项不为人知的神器,在某些时候,它往往可以出奇制胜,帮你解决棘手的问题。

即使你目前对编程无感,相信你也已经知道了 "如何魔改别人的网页" 这个小秘密。在未来的文章里,魔法哥还将分享通过 "用户样式" 来优化 ChatGPT 的使用体验,敬请期待!

🙏 抱歉,断更了一段时间,不过魔法哥并不是出去浪了,而是在筹备新书。群里的小伙伴应该都知道了,魔法哥参与撰写了一本面向零基础同学的 "AI 辅助编程" 入门书,已经进入出版流程,很快上架。一直想学编程但又无从下手的朋友,不妨持续关注。

魔法哥最近一年都在做 AI 领域的研发和探索,下期分享更精彩。各位新朋友请点关注,下次更新不迷路。


🔥 往期推荐

AI 应用开发指南:

ChatGPT 高级技巧:

AI 资讯与评述:


© Creative Commons BY-NC-ND 4.0

相关推荐
GDAL12 分钟前
vue3入门教程:ref能否完全替代reactive?
前端·javascript·vue.js
小马哥编程2 小时前
Function.prototype和Object.prototype 的区别
javascript
王小王和他的小伙伴3 小时前
解决 vue3 中 echarts图表在el-dialog中显示问题
javascript·vue.js·echarts
学前端的小朱3 小时前
处理字体图标、js、html及其他资源
开发语言·javascript·webpack·html·打包工具
outstanding木槿3 小时前
react+antd的Table组件编辑单元格
前端·javascript·react.js·前端框架
好名字08213 小时前
前端取Content-Disposition中的filename字段与解码(vue)
前端·javascript·vue.js·前端框架
摇光934 小时前
js高阶-async与事件循环
开发语言·javascript·事件循环·宏任务·微任务
胡西风_foxww4 小时前
【ES6复习笔记】Class类(15)
javascript·笔记·es6·继承··class·静态成员
布兰妮甜4 小时前
使用 WebRTC 进行实时通信
javascript·webrtc·实时通信
艾斯特_4 小时前
JavaScript甘特图 dhtmlx-gantt
前端·javascript·甘特图