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
    });
  }
};
`

转换后得到的数组如图
image

被黄色覆盖的代码为正则匹配成功的,可以看都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了

posted @ 2023-12-09 23:59  爱吃巧克力的狗  阅读(36)  评论(0编辑  收藏  举报