# 依赖变量声明

const deps: Record<string, string> = {}
const missing: Record<string, string> = {}

在扫描入口之前声明需要收集的构建依赖模块需要收集的构建依赖缺失模块两个变量。

# 生成插件容器

const container = await createPluginContainer(config)

Vite 启动时, 会形成内置插件, 同时也会有自定义插件, 所有的插件都将由插件容器进行调用。在扫描时, 用到了 resolveId 插件 api, 对导入的模块进行构建依赖收集时, 需要被收集的构建依赖将会被进行入口文件路径解析。

# esbuild插件(负责收集依赖)

const plugin = esbuildScanPlugin(config, container, deps, missing, entries)

esbuild 是一个构建工具,它只针对入口进行构建, 并不会进行依赖收集。但是esbuild提供了插件功能, 在构建的时候, esbuild 可以扫描出整个图谱模块与块引用关系, 通过分析导入的模块, 对非正常可解析文件 (比如.html .vue) 结尾的文件进行脚本提取, 同时收集需要构建的依赖。

# 通过 esbuild build 进行 假构建 扫描收集依赖

  await Promise.all(
    entries.map((entry) =>
      build({
        write: false,
        entryPoints: [entry],
        bundle: true,
        format: 'esm',
        logLevel: 'error',
        plugins: [...plugins, plugin],
        ...esbuildOptions
      })
    )
  )

当收集完需要解析入口之后, 将入口进行一一扫描 => (可以理解为通过 esbuild 进行构建,但是实际上只利用构建过程的寻找导入关系链抓到每个导入的模块,判断是我符合收集成为构建依赖)

  1. write 正是设置为 false 这里只收集依赖, 并不会产生构建打包文件。
  2. entryPoints 需要扫描文件的入口地址, 以数组的方式写入单个或多个。
  3. bundle 不设置bundle的情况下, 打包的入口文件如果有导入的文件, 并不会进行解析, 需要手动进行设置为true, 才会进行递归的方式进行深入解析。
  4. format 构建转换成什么格式。
  5. logLevel 报错提示等级。
  6. plugins 表示插件, 正是通过编写 esbuildScanPlugin 函数进行收集依赖。

# 自定义扫描过程

const { plugins = [], ...esbuildOptions } =
config.optimizeDeps?.esbuildOptions ?? {}

在文档中并没有 optimizeDeps.esbuildOptions 的用法。在扫描的时候对导入的模块进行额外处理, 我们可以通过 esbuild 插件功能实现额外的收集依赖拓展, 大部分功能在内部的扫描器插件中已经实现。同时还可以覆盖扫描的配置。