原创@前端司南
插播个广告:最近我在掘金社区有个专栏,主要涉及Vite,Vue3,TypeScript,业务组件库等关键词,目的是帮助读者掌握基于 Vite 构建现代组件库的核心方法。 链接:https://juejin.cn/column/7140103979697963045
最近有个新项目启动,主体内容与先前做的一个项目相似度很高,于是我准备拿这个旧项目作为模板简单改改,就可以启动新项目的开发了。
先说说现状,为了更好地拥抱云原生,部门内部的构建方案进行过升级,目前采用的是 Buildpacks 构建项目镜像,并且相关的服务器架构也做了调整,打镜像的 Runner 是部署在内网的,没有外网通道,也就是说安装 npm 依赖时必须从企业私有的 Nexus NPM 代理走。
带来的问题就是:这个旧项目启动时还是采纳的旧版镜像构建方案,并不存在新版镜像构建方案带来的内网限制。而现在要基于这个旧项目开发新项目,对接的相关环境都是采纳的新方案,如果不将 npm registry 调整为私有的 Nexus NPM 代理,构建镜像这一步就没法走下去。
所以我就必须得先把 npm registry 调整一下,重新生成 lock 文件。
.npmrc
修改成如下(已去掉敏感信息):
registry=https://nexus.xxx.tech:8443/repository/npm-group/
always-auth=true
_auth=xxGxxxxxxxxxxyQ0xxlGxmc=
yarnrc
也修改一下:
registry "https://nexus.xxx.tech:8443/repository/npm-group/"
npm-group 包含了 npm-proxy 和 npm-hosted,从这里既可以下载通过 npm-proxy 代理过来的公开发行的 npm 包,也可以下载通过 npm-hosted 维护的企业内部私有的 npm 包。
这个项目用的是 Yarn,所以我接着删掉 yarn.lock
重新生成 lock 文件。
此时最好参照旧的 lock 文件,将关键依赖的版本号先锁住,再重新生成新的 lock 文件,防止在
~
,^
这种约束不强的规则下,最终安装的依赖版本号发生变化的情况。
生成完 lock 文件后,检查一下 dev 和 build 等场景,是不是基本上没什么问题。不出意外的话,就要出意外了!
很快,我就在一段 tsx 代码上遇到了这么一个报错:
代码语言:javascript复制Type '() => void' is not assignable to type 'MouseEvent'.ts(2322)
runtime-dom.d.ts(1401, 3): The expected type comes from property 'onClick' which is declared here on type 'IntrinsicAttributes & AntdIconProps'
这个报错是从 runtime-dom.d.ts
中抛出来的,我第一反应就是看看@vue/runtime-dom
这个包的版本是不是变了。
查了一下发现,@vue/runtime-dom
确实是变了,从3.2.33
变成了3.2.40
,
而这个变化是由于vue
的版本号变化引起的,这是因为我的vue
版本约束是~3.2.29
,重新生成 lock 文件时会检查有没有较新的版本。
好,那我就锁vue
的版本号,就定为原来生成的3.2.33
版本。
"vue": "3.2.33",
重新安装依赖,期待能解决问题。
但是这并没有解决问题,报错依然存在。于是我尝试去锁可能影响这个问题的一些依赖的版本号,包括typescript
, @typescript-eslint/eslint-plugin
, @vue/eslint-config-typescript
等等,最终都没有解决这个问题,搞了个把小时,emo了...
于是,我就尝试找问题源runtime-dom.d.ts
有没有什么问题,先仔细观察下报错信息,
The expected type comes from property 'onClick' which is declared here ...
既然你说 onClick
未声明,那我把 onClick
设置为可选的行不行?
// node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts
export interface Events {
// ...
onClick?: MouseEvent;
// ...
}
改了之后这个报错还真的消失了!!!
但是直接改 node_modules 里的代码肯定是不行的,离开自己的机器,就没法同步到这个修改。
借助 patch-package 可以实现修改 node_modules 后也能让其他人安装时同步到修改信息这种能力,但是我还不想这么做,能不能在项目中加一个d.ts
,把这个interface
修改一下呢?
考虑到interface
有合并能力,我先尝试在global.d.ts
中加同名的interface Events
,
declare interface Events {
onClick?: MouseEvent;
}
但是发现也并没有作用,因为runtime-dom.d.ts
中用了export interface Events
,这意味着Events
接口是模块下的,我这样直接加在全局是合并不了的,那有没有办法合并模块下的interface
呢?
我简单尝试了一下declare
一个同名的module
,然后加入一个interface Events
,也不行,这样就直接覆盖了node_modules
里的类型声明。
最后实在没办法了,我想到:既然覆盖了,那就全部覆盖吧!我干脆把node_modules/@vue/runtime-dom/dist/runtime-dom.d.ts
整个文件抄了出来,就改了onClick?: MouseEvent;
这一行,效果确实可以,这个问题算是临时解决了。
福无双至,祸不单行,我就知道事情没这么简单!
继续往下测试,我又遇到一个报错:
这真的是搞心态啊,@ant-design/icons-vue
不报错了,div
又报错了。
收拾好心情,发现 VSCode 右下角出现了一个提示信息。
打开一看,终于找到了问题原因,这是 Volar 给出的提示。
原来是@types/node@18.8.4
版本与vue@3.2.40
版本不兼容,会造成模板中的 DOM event type 出错,解决的方法有两个:
- 降低
@types/node
版本至18.8.0
。 - 升级 Vue 的版本号至
3.2.41
,后面还备注了(如果已发行)。
于是,我去看了一下 Vue 的最新版本,发现 3.2.41 还没有发布,可能也正在解决这个问题吧!
那就选择降低@types/node
的版本号吧,最终解决了这个问题,前面改的那个interface
相关的代码也可以删了。
相关 issue 还是 2 天前提出的,说明这个问题还蛮新的。
为啥 Volar 不早点提示我呢?难道是因为我第一个报错是在
.tsx
中?估计是...
END