面试官:回答我!在tsconfig配置了别名你为啥要在vite再配置一遍?嗯?

在一个月黑风高的夜晚,面试官看到我简历上的:熟悉typescript,轻蔑一笑:"你说你熟悉ts,那我问你,你配置的tsconfig里moduleResolution的node选项和classic选项有何区别?你都在tsconfig配置了别名,为什么要在vite.config.js里的resolve.alias又配置一遍?

回想起create-vite-app一路回车的爽感,回想起Vite + Vue3上手就开发的便利,我滴下了一滴冷汗。开始疯狂的头脑风暴

各位朋友,其实答案很简单,甚至各个前端er有手就会,只要稍微多想想。

Ts是什么,有什么用?

追根溯源,首先简略回想一下ts是个什么东西

  • js的超集,js被ts包含,所有js代码都是有效的ts代码
  • 静态类型检查,规避弱类型语言js可能发生的各种运行时错误
  • 增加代码感知,编程时获得属性提示
  • ...

可惜,浏览器他实在太专一了,他只认低级的ES5语法(不绝对,有些浏览器也支持ES6)。ts想在浏览器上运行还得经过一层编译,或者说转译,从ts转为js,再由babel将高级js语法转为低级js语法

Ts如何转为js?

当我们想要使用ts的时候,我们可以用pnpm add typescript为我们的项目加上ts依赖库。装上之后在node_modules/.bin文件夹就可以看到tsc可执行文件。这个时候我们可以利用npx tsc xxx来将ts文件转为js文件

为何要用tsconfig.json?

如果你仅需要编译一两个ts文件,直接用npx tsc或许是不错的选择,但当你的项目中包含了上百个ts文件,写一个集中的配置tsconfig或许是更明智的选择。

当你命令行输入tsc / npx tsc 的时候,tsc就会从执行的目录开始逐级向上找tscongig.json找到后按配置执行

中场休息

回想到这里,我已向面试官露出了微笑,tsconfig的别名、moduleResolution的设置,当然是帮助tsc运行的。vite.config.js的别名当然是帮助vite运行的,你说两者他搭嘎吗?他都不搭嘎,我设置两次别名很奇怪吗?

就在我胸有成竹,喷薄欲出的时候,面试官的冷笑让我冷静下来:我就这么说合适吗?合适吗?他会满意吗?还得说说原理吧...最好还要说说怎么能给他一次配置,两边通用吧...

我咬着牙,进行了第二次头脑风暴...

tsc相关的运行机制

首先我们想到,vite不仅仅是一个单纯的打包工具,他能编译ts、js,能处理scss、less,能处理静态文件,能启动本地服务...

换句话说,tsc只是vite play中的一环,而tsc只负责将ts转为js(影响范围可用include、exclude配置)

moduleResolution这个属性也很有意思,他的node策略模拟了 Node.js 的 CommonJS require() 解析算法,帮助代码找到他们的依赖项,而classic策略可以说是历史遗留问题,这是早期的策略,据我模糊不真实的记忆,设置classic之后再想要引用第三方库只能写../../node_modules/xxx 这种形式,实在过于反人类。至于为什么还能保留这个选项,大概是历史遗留的代码太多,直接弃用太痛了

别名其实也就是将设置的@替换成baseUrl + 'src' 然后tsc根据moduleResolution的策略寻找依赖项而已

至此,我们可以总结:tsconfig的别名和moduleResolution的作用其实就是

  1. 别名:将你设置的类似@ 的别名替换成baseUrl + 'src'
  2. moduleResolution:使用设定的策略,定义tsc寻找依赖文件的方式

二者都是用自己不同的方式帮助tsc寻找到正确的依赖文件

需要注意的是,tsc在编译时,即使找到了依赖项,也仅负责ts转为js的部分,并不会进行路径的改写,也就是说:你写的 import xxx from '@/xxx' 还是保留原样

vite相关的运行机制

tsc把ts一编译就直接原封不动的丢来了import xxx from '@/xxx' ,但是作为老妈子的vite 可不能这么不负责任,因为vite编译后的代码可是要在浏览器上运行的。浏览器知道什么,他太单纯了,不可能会认识 '@/' 这样子妖艳的 '码' 的,他只认识 './' 码 和 '../' 码。所以经过vite编译后的代码,才真正消除了'@'别名

与此相对应的,tsc是根据moduleResolution的策略来寻找三方库的,vite呢?

在node_modules下面有这样的目录:.vite/deps,这是vite利用esbuild进行预构建之后生成的第三方依赖代码,vite会将引用第三方库,比如lodash,直接改成写成引用node_modules/.vite/deps/lodash.js 这样一种形式,来帮助浏览器找到正确的依赖文件

tsconfig别名与vite别名同步

回忆至此,我早已了然。甚至于悠然回想起写过的一个vite小插件,帮助同步两个别名,原理很简单

利用node的fs模块读取项目中tsconfig的配置,当然也可以用load-tsconfig这个第三方库来帮助读取,读取之后提取paths属性,在插件的config钩子函数中根据paths属性生成vite规则定义的对应的alias别名,然后

return { resolve: { alias } }

等会儿就说给这个面试官听,让他也知道知道我的厉害

总结

  1. moduleResolution的node策略模拟了 Node.js 的 CommonJS require() 解析算法,可以通过require('axios')的方式直接找到第三方库,而classic策略则只能通过../../node_modules的方式
  2. tsconfig所定义的别名仅起作用在tsc的编译阶段,将别名替换成对应的路径,帮助tsc寻找到正确的依赖,编译后的文件并未进行别名替换,且无法直接运行于浏览器
  3. 而vite所定义的别名起作用在dev/build 阶段,也就是启动本地服务和打包的阶段,编译后的文件会直接进行别名替换改写,且直接运行于浏览器
  4. vite会进行依赖预构建,且在找寻第三方依赖时会将路径改写到node_modules/.vite/deps目录下
  5. tsconfig和vite的别名其实各不相关,仅在各自的阶段各司其职,但是由于开发的候的观感,让人以为其有联系
  6. tsconfig和vite的别名确实在很多情况下完全一致,可以利用vite插件来进行同步,仅配置一次tsconfig别名,同步到vite别名上
  7. 如有错误,还请指出,本小白立刻改正!

面试官:?请问你在做什么?怎么发了这么久的呆,还一脸痴汉笑?不想过面试了?

相关推荐
紫微AI5 小时前
前端文本测量成了卡死一切创新的最后瓶颈,pretext实现突破了
前端·人工智能·typescript
若梦plus6 小时前
TypeScript进阶
前端·javascript·typescript·ecmascript
Restart-AHTCM14 小时前
AI 时代的大前端崛起,TypeScript 重塑前端开发
前端·人工智能·typescript·ai编程·a
一袋米扛几楼9814 小时前
【报错问题】解决 Vercel 部署报错:Express 类型失效与 TypeScript 2349/2339/2769 错误排查
ubuntu·typescript·express
一袋米扛几楼9817 小时前
【报错问题】彻底解决 TypeScript 报错 TS2769: No overload matches this call (JWT 篇)
linux·javascript·typescript
涵涵(互关)17 小时前
语法大全-only-writer-two
前端·vue.js·typescript
漫游的渔夫18 小时前
前端开发者做 Agent:Tool Calling 别只写函数名,用 Schema 少踩 5 个坑
前端·人工智能·typescript
zhensherlock20 小时前
Protocol Launcher 系列:Beorg 高效任务管理的协议支持
前端·javascript·typescript·node.js·自动化·github·js
深海鱼在掘金1 天前
深入浅出 LangChain —— 第二章:环境搭建与快速上手
人工智能·typescript·langchain
俺不会敲代码啊啊啊2 天前
el-table实现行拖拽(包含展开项)
前端·vue.js·typescript