unplugin-auto-import 插件源码的简单实现
工作中用到了这个插件 好奇是通过ast还是什么方式实现的判断代码是否调用了某个库,所以就研究了下
准备工作
1 一个vite项目 安装了该插件,预设只有vue
import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'
import vueJsx from '@vitejs/plugin-vue-jsx'
import AutoImport from 'unplugin-auto-import/vite'
export default defineConfig({
plugins: [
vue(),
vueJsx(),
AutoImport({
imports: [
'vue'
// 预设
]
})
]
})
2 一个超级简单的vue文件,有使用ref,但没有引用
<script setup>
const count = ref(100);
</script>
<template>
<h1>
{{ count }}
</h1>
</template>
调试源码找到相关代码
大致原理是在一个类似于webpack的loader的钩子里拿的文件的后缀和内容,如果是vue文件那么解析内容,
找出有没有需要引入的方法。关键代码在unimport/dist/shared/unimport.05b109bd.mjs的detectImports方法中
这个方法的实现逻辑是通过正则来找的,正则大佬可真是恐怖。
先是解析的第一步正则,和vue经过其他loader转换后的内容
<script setup>
var matchRE = /(^|\.\.\.|(?:\bcase|\?)\s+|[^\w_$\/)]|(?:\bextends)\s+)([\w_$]+)\s*(?=[.()[\]}}:;?+\-*&|`<>,\n]|\b(?:instanceof|in)\b|$|(?<=extends\s+\w+)\s+{)/g
var strippedCode = `
import { createVNode as _createVNode } from " ";
export default {
setup() {
const count = ref(100);
return () => _createVNode(" ", null, {
count
});
}
};
`
转换后得到的数组如图
被黄色覆盖的代码为正则匹配成功的,可以看都ref也在里面,
接下来进行一系列的删除,正则如下
const excludeRE = [
// imported/exported from other module
/\b(import|export)\b([\s\w_$*{},]+)\sfrom\b/gs,
// defined as function
/\bfunction\s*([\w_$]+?)\s*\(/gs,
// defined as class
/\bclass\s*([\w_$]+?)\s*{/gs,
// defined as local variable
/\b(?:const|let|var)\s+?(\[.*?\]|\{.*?\}|.+?)\s*?[=;\n]/gs
];
这个正则还蛮简单的,我一个菜鸟,不看注释也能明白,就是把一些已经有相关的定义找出来,在最前面正则匹配的数组中
删掉在这个正则中匹配出来的内容
然后就是最后一步,在相关预设里面看看有没有对应的key。发现vue的预设里 有这个ref所以就可以自动在内容里面加上相关import了
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现