1. "LONGER"不是一个Bug,而是四件每天都在发生的事
1.1 上周复现的真实场景:升级依赖之后的整屏警告
上周五下午,我把一个躺了大半年的老项目重新拉起来改需求。准备开工第一件事就是升级依赖,结果pnpm install一跑,终端里呼啦冒出一大片警告,最显眼的一条长这样:
pnpm dev [warn] the "pnpm" field in package.json is no longer read by pnpm. the following keys were ignored: "pnpm.overrides". see https://pnpm.io/settings for the new home of each setting.同一屏里还混着 node-sass 的 deprecation 报错、某个在线工具提示 "this client is no longer supported"、以及 Windows 同事发来的长路径截图。我盯着满屏英文,突然意识到这些看似八竿子打不着的报错,背后全是一个词:LONGER。
不是指某个具体 Bug,而是工程世界里普遍存在的四类"更长"问题:支持链路"不再更长"的 no longer、任务执行"比预期更长"的 takes longer、文件路径"超过 260 字符"的 longer than 260、以及项目生命周期里那些"还能撑多久"的隐性倒计时。
这篇文章就把这四类问题一次性捋清楚,包括每类问题的成因、现场现象、解决步骤和避坑经验。内容不挑技术栈,前端、后端、客户端方向都能用得上,尤其适合那种长期维护老项目、经常被依赖升级和系统限制折磨的开发者。
1.2 先把"LONGER"拆成四个看得懂的工程问题
我第一次把这几条报错放在一起时,本来想用"过时""变慢""超长"三个词归纳一下,但聊着聊着发现不对,它们对应的根本不是同一类问题,处理方式也不能混着来:
| 关键词 | 实际含义 | 典型案例 | 处理思路 |
|---|---|---|---|
| no longer | 功能或接口被移除,旧写法失效 | pnpm 不再读 package.json 里的 pnpm 字段 | 迁移配置到新位置 |
| deprecated | 官方认为该方案过时,但暂未删除 | node-sass 被标记为废弃 | 替换为现代方案 |
| takes longer | 性能退化,等待时间变长 | AI 编码工具响应缓慢 | 定位瓶颈并优化 |
| longer than 260 | 受系统限制,路径超长无法工作 | Windows 无法访问深层目录 | 开启系统长路径支持 |
这四个象限看起来互不相干,但如果你在同一个项目里待得够久,大概率会依次撞上。而且它们都有一个共同点:报错信息往往只是"警告"级别,不会立刻让构建挂掉,于是很多人选择无视,直到某个深夜发布前突然演变成 Error。下面我按这个框架,把每个象限都拆开讲清楚。
2. "No Longer"家族:旧习惯集体失效的现场还原
2.1 pnpm v10 不再读取 package.json 里的 pnpm 字段:完整迁移步骤
先处理最关键的 pnpm 警告。pnpm 在 v10 之前,允许在 package.json 里写一个pnpm字段,用来放overrides、packageExtensions、patchedDependencies、onlyBuiltDependencies这些配置。很多人图省事,把它当默认配置位用了好几年,比如:
{ "name": "legacy-project", "version": "1.0.0", "scripts": { "dev": "vite --port 5173" }, "pnpm": { "overrides": { "lodash": "^4.17.21", "minimist": "^1.2.8" } } }从 pnpm v10 开始,这个字段直接不读了,配置必须挪到项目根目录的pnpm-workspace.yaml里。我第一次看到警告时以为只是元数据校验问题,结果pnpm run dev一切正常,但pnpm install之后发现 lodash 根本没被 override 到指定版本,依赖还是旧的——这就是"配置静默失效"最坑的地方:警告不会让你构建失败,但行为已经悄悄变了。
迁移其实很简单,两步:
第一步,在项目根目录创建pnpm-workspace.yaml(没有就新建):
packages: - . overrides: lodash: ^4.17.21 minimist: ^1.2.8第二步,把 package.json 里的pnpm字段整体删掉。这样 pnpm install 就不会再报这个 warn 了。
为什么 pnpm 要这么做?原因是配置归属的"单一真相源"问题。package.json本质上是描述包依赖与元信息的文件,而 pnpm 的偏好设置属于项目管理配置,把它们塞进 package.json 会让各种工具对同一个文件的解析规则产生混淆。把设置统一挪到pnpm-workspace.yaml之后,编辑器、CI、其他脚本都能用同一份文件识别工作区和配置,语义更干净。官方在警告里给出的地址https://pnpm.io/settings就是完整的配置迁移对照表,如果项目里用到的配置不止 overrides,挨个对照着挪就行。
这里提个容易漏的细节:很多老项目把onlyBuiltDependencies(用来白名单化构建脚本的包)也写在pnpm字段里。迁移时漏掉这一项,安装时就会看到 pnpm 询问是否允许某个包执行 postinstall 脚本,CI 里还会因为交互式提示直接卡住。所以迁移完建议执行一次pnpm install,把脚本确认类的问题一并处理掉。
2.2 node-sass 的黄昏:为什么必须换掉它
同样是"旧习惯失效",node-sass 的情况更典型。我那台老项目的依赖树里有node-sass@4.14.1,一遍又一遍地刷警告:
DeprecationWarning: node-sass@4.14.1 is deprecated: Node Sass is no longer supported.这条警告从几年前就开始出现了,到现在依然有成千上万的项目还在用。原因不难理解:node-sass 底层是 LibSass,用 C++ 实现的 Sass 编译器,二进制版本必须跟着 Node 的 ABI 走,每升级一次 Node 就要重新下二进制、重新编译。如果项目里再牵扯到私有镜像源缺包、内网环境禁止下载,装一次能折腾一下午。
更重要的是功能层面:LibSass 已经停止维护,而 Dart Sass 成了官方唯一的实现,新语法比如@use、@forward,以及math.div代替/做除法,只在 Dart Sass 里可用。只要你的代码还写着@import,或者用/做除法,node-sass 也许还能凑合跑,但一旦依赖链里某个包升级,SCSS 语法兼容性立刻暴露问题。
我的建议是长痛不如短痛,直接把 node-sass 换成 sass(Dart Sass):
npm uninstall node-sass npm install -D sass然后处理三处常见语法差异:
@import改成@use/@forward,避免全局变量互相污染。/除法改成math.div(a, b),记得@use "sass:math";。rgba(..., 0.5)这类老写法,逐步迁移到color-mix()或现代色值函数。
替换完成后用npx sass --version确认生效,再跑一遍完整构建。实测一个中等规模项目,替换后构建时间基本持平,但团队以后不会再被 Node 版本升级绑架。唯一要注意的是,如果项目里深度依赖了 node-sass 的render同步 API 做自动化脚本,需要把调用方式同步改成 sass 的异步接口。
2.3 在线服务也有生命周期:从 Teams 和 Gemini 的退出提醒说起
还有一类 "no longer" 不在代码里,而在你依赖的在线服务上。前两天我同事打开某协作工具的免费版,弹出一条公告:免费个人版不再可用;另一个同事则是在某个 AI 工具里看到 "this client is no longer supported" 的登录失败提示。
这两条消息放在一起看很有意思:免费个人版和某个老版本客户端,都属于"服务方主动终结支持"。原因一般不外乎三点:免费版商业模式扛不住、维护成本过高、以及为了强制用户迁移到新版。对普通用户来说只是换个入口,但对把这类服务接进自动化脚本、机器人流程的开发者来说,这就是一次不折不扣的 breaking change。
我的经验是:接到这类"no longer"通知后,不要只看第一行,要往下翻到底,确认三件事:
- 服务停止的具体日期,以及有没有宽限期。
- 官方提供的替代方案是什么,数据能不能迁移、怎么导出。
- 你正在用的 API 或集成是否有对应的新版端点,鉴权方式有没有变。
把这些信息记到项目 README 或运维文档里,比转发到群里让大家"各自留意"可靠得多。任何在线服务的使用周期都不由你控制,唯一能做的就是在周期终结前,给自己留好退路。特别是那些接入了 Webhook、定时同步脚本的项目,建议在服务停用前一周就把切流方案演练一遍,别等到服务真的断掉才发现数据导不出来。
3. "Takes Longer":当工具比预期更慢,怎么定位真正的原因
3.1 AI 编码工具卡顿的真相:慢在四个环节
"No longer" 处理完,接着就是另一个更让人抓狂的 "longer":工具跑得比预期慢。很多人应该都遇到过 AI 编码工具在生成代码时,盯着光标等了十几秒,心里已经默认它"卡死"了。实际上这几个月我用下来,发现它的耗时基本由四段组成:请求排队、模型推理、响应流式返回、以及编辑器本地渲染。
其中大部分项目根本轮不到"模型推理"就已经慢了。比如打开一个巨大的 monorepo,编辑器在后台做全量索引,CPU 被打满,你再发一个补全请求,本地渲染和补全请求去抢线程,于是观感就是"转圈转了半天"。
想确认是不是本地索引拖后腿,一个简单办法是打开任务管理器,看编辑器进程 CPU 是否长时间处于高位,同时观察界面右下角的索引进度状态。如果索引持续好几个小时,就要考虑减少它的扫描范围了。
3.2 定位"慢工具"的通用排查顺序
不仅仅是 AI 编码工具,任何"takes longer than expected"的开发工具,我都会按同一套顺序排:
- 先看是不是全局性的。重启编辑器后如果立刻变快,说明是会话期的缓存堆积;如果重启也慢,进入下一步。
- 看资源占用。CPU、内存哪个被打满,对应到是索引、编译还是同步任务。在 macOS 上用活动监视器,在 Windows 上用任务管理器,重点看进程名对应的线程数变化。
- 看网络。工具如果依赖远程服务,先 ping 或看请求日志,确认是不是服务端响应问题。这一步很容易被忽略,很多人以为是本地问题折腾半天,结果发现是公司出口带宽或者代理配置的问题。
- 缩小范围。把项目拆小、把某些目录排除,看慢的是不是某一类特定文件。比如只慢在
.md文件,可能是 Markdown 预览插件的问题;只慢在大型 JSON,可能是语法高亮解析的问题。
以编码工具为例,最有效的一招是加忽略规则。像.cursorignore这类文件,作用跟.gitignore类似,可以排除掉node_modules、dist、.next等生成目录,让索引器专注在真正要改的业务代码上。加完之后,索引体积能砍掉一大半,补全速度体感明显提升。
3.3 一个降低等待感的实际配置组合
这里分享一个我现在一直在用的组合方案,适用于大部分 AI 编码工具和前端项目:
- 在
.cursorignore或等效文件里排除node_modules/、dist/、build/、.git/、coverage/。 - 把 monorepo 中不常改的包子应用单独排除,只保留当前工作包。
- 避免一次性吞入过大的上下文,提问时明确指定文件,而不是丢一整包路径让它自己找。
- 后台自动更新关闭,避免它趁你写代码时偷偷下载新版本。
这一套做完,响应速度通常会有可感知的提升。如果还慢,再考虑是不是要换更好的硬件,或者换轻量模式。另外有个容易被忽略的细节:如果你开着多个项目的窗口,每个窗口都在做索引,内存占用是叠加的。我习惯只开当前工作的窗口,其余项目窗口关掉,索引线程数立刻降下来。
4. 突破 260 字符:Windows 长路径实战
4.1 MAX_PATH 的前世今生
"No longer" 和 "takes longer" 都处理完了,最后聊一个最物理、最直接的限制:Windows 上路径长度不能超过 260 字符。这个数字来自 Windows API 里的MAX_PATH常量,是早期文件系统设计的产物。当年硬盘那么大点,目录嵌套十几层已经很夸张了,260 字符绰绰有余;如今在node_modules这种生成目录面前,260 字符就是个笑话。
我在老项目上经常碰到这种情况:pnpm install装到一半报ENAMETOOLONG,或者 Git 拉代码时提示Filename too long,甚至某些 Windows 工具直接拒绝访问一个明明存在的文件。根因都一样:完整绝对路径超过 260 字符。
这个问题虽然历史悠久,但 Windows 10 1607 之后的版本已经内置了长路径支持,只是默认关闭,需要我们手动打开。很多人不知道这个开关,白白被这个限制折磨很多年。
4.2 三步开启 Win32 长路径支持
开启方式并不复杂,按下面三步来:
第一步,修改注册表。在开始菜单搜索"注册表编辑器",打开后定位到:
HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Control\FileSystem找到LongPathsEnabled这个 DWORD 值,双击把数值数据从 0 改成 1,点确定,重启系统。如果没有这个值,就在右侧空白处右键,新建 DWORD(32 位)值,命名为LongPathsEnabled,再改成 1。
第二步,确认组策略同步开启。有些精简版系统注册表改了但策略没放行,保险起见,在运行框输入gpedit.msc打开组策略编辑器,找到:
计算机配置 → 管理模板 → 系统 → 文件系统 → 启用 Win32 长路径把它设为"已启用"。
第三步,验证是否生效。重启后打开 PowerShell,执行:
(Get-ItemProperty "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem").LongPathsEnabled返回1就说明成功了。之后访问超过 260 字符的路径就不会再被系统层拦截。
需要提醒的是,注册表和组策略只是"系统允许",具体的应用程序还得声明自己支持长路径。Windows 自带记事本、新版资源管理器都能处理长路径,但第三方老工具不一定。所以改了系统设置不等于所有程序都能访问超长路径,这一点务必要有预期。
4.3 开启后仍要处理的三个配套项
除了系统开关,我建议顺手做三件配套的事,避免后续反复踩坑。
第一件,给 Git 开长路径。在 Git Bash 里执行:
git config --global core.longpaths true这样仓库内出现超长路径时,Git 不会直接拒绝 checkout。很多团队在 Windows 上拉完代码后,发现某些文件"不翼而飞",其实就是 checkout 时被静默跳过了,开了这个配置才能避免。
第二件,给 Node 项目配置缓存目录。npm 和 pnpm 的全局缓存路径通常都在用户目录下,用户名一长,缓存路径也跟着长。可以通过设置环境变量把缓存挪到短路径下,比如:
npm config set cache "D:\.npm-cache"pnpm 同理,在.npmrc里配置:
store-dir=D:\.pnpm-store这一步对 CI 环境尤其有用。很多 Windows 构建机因为用户目录层级深,硬生生把安装路径堆到了 260 字符,随手改个短路径,构建成功率能提升一大截。
第三件,重新审视项目目录结构。源文件路径尽量短,比如src/components/ui/buttons/primary而不是src/app/features/ui/core/components/buttons/primary-submit-button。长路径系统支持打开了,但短路径依然是成本最低、最稳的做法。团队里如果还有人用旧系统,短目录能让所有人都少碰一鼻子灰。另外,npm 生态里很多老包对长路径支持仍然不佳,路径短一截,兼容性问题就少一截。
5. 面对 "LONGER" 类问题,我沉淀的排查清单
5.1 先完整读警告,再动手搜
处理了这么多年 "LONGER" 类问题,我最深的体会是:大多数人(包括以前的我)看到报错第一反应是复制粘贴去搜索引擎,或者直接去问 AI。但 pnpm 那条警告里其实已经写清楚了——字段被忽略、键名是什么、官方设置文档在哪里。node-sass 那条也一样,deprecation 信息里直接说了 "no longer supported"。
所以我现在的习惯是:先不搜,先把报错完整读三遍。确认三件事:
- 这是 error、warn 还是 deprecation 提示?影响构建还是只影响体检?
- 消息里是否带了官方文档 URL?
- 消息里是否指定了具体的包名、版本号、配置键名?
把这三个信息抓出来再动手,效率至少翻一倍。很多报错根本不需要搜索引擎,答案就在报错信息本身。
5.2 按错误信息里的 URL 去找官方迁移指南
稍微老练一点的同学会发现,新版工具在废弃旧功能时,几乎都会在警告里附带官方文档链接,这是处理 "no longer" 类问题最权威的入口。pnpm 那条警告的 URL 是https://pnpm.io/settings,打开就是完整的设置迁移对照表。
我的建议是,把这些 URL 存进项目的docs/目录或者 README 里,不要只存在终端历史里。等下一次有人遇到同样问题,直接把链接甩过去,就是最好的团队沉淀。这块的收益是复利式的:每解决一个问题,项目里的"防御性文档"就厚一层,后面新成员上手踩坑的概率就低一截。
另外还要注意一个细节:报错信息里的 URL 所指向的文档,可能和当前版本不完全一致。访问时如果看到 "latest" 字样,最好确认一下页面里标注的版本号,别拿新版的说明去适配旧版配置。有些工具会在文档页提供版本切换器,切到跟项目匹配的版本再看。
5.3 给老项目做一次"去 LONGER 化"体检
最后,如果你手里也有那种躺了很久的老项目,我推荐花一个下午做一次"去 LONGER 化"体检。我自己的固定流程是:
- 执行
pnpm outdated或npm outdated,看依赖是否大版本落后。 - 全局搜报错信息里常见的 "deprecated"、"no longer" 字样,范围包括
package.json、构建日志、CI 输出。 - 检查构建日志里有没有非致命的警告,这些最容易被人无视,也最容易被忽略到某一天突然变成 Error。
- 检查有没有把配置塞在已经不再被读取的位置,比如旧版 pnpm 的 package.json 字段。
- 如果用了在线服务,翻一下官方公告,确认没有临近的生命周期终结。
这套体检不保证让项目变成最新最酷,但能保证它在下一次被拉起来改需求时,不需要再花一个下午处理满屏的 "LONGER" 警告。我做过很多次类似清理,最快的一次只花了四十分钟,却省下了后面整整一周的返工时间。
最后再分享一个习惯:我现在处理任何报错,都会先在本地新建一个notes/文件,把报错原文、解决步骤、官方链接一并记下来。等这类问题第三次出现时,我就能直接翻笔记,而不是又从头搜一遍。这大概是面对所有 "no longer"、"takes longer"、"longer than 260" 类问题,最省时间也最稳妥的做法。