背景
之前做了个关于localStorage的库,为了完成功能,对源码做了大量的自动导入、源码提取转换等操作,最后遗留了一些影响开发体验的点
未生成.d.ts文件,导致需要手动在项目中写死
未重新设置sourceMap,导致页面无法debugger
只支持vite,对于webpack还需要额外写代码进行支持
今天得空,就对目前比较知名的auto导入的库做研读,并希望能从中得到参考
源码
"依赖"收集
根据文档所接受的参数来看,其在对页面进行注入前,势必要先解析出所有的待注入的值,这大致上分为三类:内置的、用户自定义的和第三方包的
内置的
在presets文件夹内,内置了常见的第三方包,以pinia为例子,就是将对应的库导出的api做预先定义
接着,只需要根据用户定义的预设拉取对应的文件
拿到导出的预设做normalize
然后合并下用户的忽略项,最终得到的就是待注入的内置列表
用户自定义的
在服务启动时,即buildStart阶段,可以来做这件事
这将在打包工具开始工作时进入scanDirs函数
该函数根据用户提供的目录扫描其文件,利用Promise.all取所有异步的.then一次性处理好所有的文件路径,然后丢给scanExports对每一个拼接好的绝对路径对应的源码做分析
可以看到主要是利用fs的readFile方法获取源码,借助mlly这个库去解析出所有的export的ast形式,然后再根据特定的信息normalize为需要的格式
最后,将结果保存到上下文对象中,并等待解析到文件时做分析--调用--注入
另外就是,由于这部分内容是写在用户侧的,存在随时变化的可能性,而buildStart这个hook仅在服务启动时调用,因此,需要接入热更新做re-scan
第三方包的
这个和内置包的处理逻辑是兼容的,如下框红所示,对象形式执行array取值逻辑
文件过滤
我们无法左右使用者在其项目中添加什么样的文件,但我们可以清楚的知道我们能处理哪些文件,因此对于不必要的文件应当skip,为此,需要创建过滤函数
并与打包工具配合跳过一些“非法”文件
"依赖"注入
至此,我们已经收集好了所有等待注入的变量,也对一些非法文件进行了跳过,此时便可以开始注入了,由于这涉及到对文件源码的转换,这是transform擅长的
可以看到,这里利用MagicString库来对源码字符进行代理,并在最后重新生成sourceMap,这很好的避免了对原sourceMap破坏导致的页面debugger错乱的问题
从本项目的功能来说,框红的位置才是核心,大致分为两步:分析源码
分析源码
这里利用vueTemplate库创建一个较为“干净”的源码(去除注释)以降低处理的心智负担,然后借助mlly分析当前源码的模块引入形式(纯esm还是cjs还是两者混合)以为后续做不同的分支处理
接着,拉取我们在“依赖”收集阶段保持在上下文的变量集
拿到变量集对源码做分析,找到当前页面使用到的需要被自动导入的变量
插入
调用vueTemplate.addImportToCode插入到源码中
生成配置文件
此时我们已经为源码做了自动导入,所有的变量都被正确的import xxx from "node_modules|绝对路径",这在js项目中没有问题,但是对于ts来说,却会导致报错,故,需要为此生成.d.ts配置文件
通用的打包工具处理
这里主要是利用了一个第三方库unplugin来完成的,其不仅抹平了vite和webpack,还支持rollup,就不在这里详说,放到下一篇分享