unplugin-auto-import技术揭秘

背景

    之前做了个关于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,就不在这里详说,放到下一篇分享

你可能感兴趣的:(unplugin-auto-import技术揭秘)