前端 Vite 项目使用 vite-plugin-dts 打包输出类型文件,处理踩坑:Cannot find module 'vue'. Did you ...

最近在尝试做一个自己的前端组件库,build 打包构建的时候要输出 .d.ts类型文件,用到 vite-plugin-dts 这个 vite 插件,这里记录自己的使用和踩坑记录,会逐步分析解决问题,跟着思路相信会比较清晰。

安装 vite-plugin-dts

bash 复制代码
pnpm i vite-plugin-dts -D

简单使用

先 import 导入一下,然后直接作为插件引入即可,例如:

ts 复制代码
import { resolve } from "path";
import { defineConfig } from "vite";
import dts from "vite-plugin-dts";

export default defineConfig({
  build: {
    lib: {
      entry: resolve(__dirname, "src/index.ts"),
      name: "MyLib",
      formats: ["es"],
      fileName: "my-lib"
    }
  },
  plugins: [dts()] //在这里作为插件引入
});

处理踩坑

引入插件之前 build 是正常的,引入之后 build 报错如下:

bash 复制代码
src/index.ts:1:26  - error TS2792: Cannot find module 'vue'. Did you mean to set the 'moduleResolution' option to 'nodenext', or to add aliases to the 'paths' option?

1 import type { App } from 'vue';
                           ~~~~~
src/index.ts:2:20  - error TS2792: Cannot find module './components/Button'. Did you mean to set the 'moduleResolution'
option to 'nodenext', or to add aliases to the 'paths' option?

2 import Button from './components/Button';

先直接讲解决方案,有耐心的看后续分析

  1. 在根目录下新建 tsconfig.build.json 文件,写入内容如下:
json 复制代码
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["src/index.ts", "src/components/**/*", "src/hooks/**/*"],
  //include内容根据具体情况自己定制,我是根据组件库自己修改的,如果没动过原来的应该是下面这个:
  //"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "references": [
    {
      "path": "./tsconfig.node.json"
    },
    {
      "path": "./tsconfig.app.json"
    }
  ]
}
  1. 然后把tsconfig.build.json导入到 vite.config.ts 的插件 dts()中:
ts 复制代码
dts({ tsconfigPath: "./tsconfig.build.json" });
  1. 先 build 一下,看看找不到 Vue 的报错有没有消失,如果消失了说明问题已经解决了,其他的报警应该是路径的问题,把相对路径改成以@/*这种形式的绝对路径,因为tsconfig.build.json中配置了baseUrlpaths,所以要使用绝对路径,而不能使用相对路径,不然插件会找不到。

这样重新 build 就可以了,错误应该会消失。有耐心的朋友可以看看我是怎么一步一步分析和解决的哈。

先说明我的报错的环境

我的项目是 vite 5,vue 3.4, TS 5.4,使用 Vue 官方的推荐安装方式安装的项目环境。安装完成后根目录中有三个 tsconfig 相关的文件,分别是 tsconfig.json,tsconfig.node.json,tsconfig.app.json,其中 tsconfig.json 的内容如下:

json 复制代码
{
  "files": [],
  "references": [
    {
      "path": "./tsconfig.node.json"
    },
    {
      "path": "./tsconfig.app.json"
    }
  ]
}

分析报错以及初步尝试修改

报错的位置:src/index.ts

报错的类型: TS 报错

报错的结果:找不到相关模块。如'vue','./components/Button'

报错修改建议:尝试修改 'moduleResolution'nodenext,或者给 paths 添加别名。

初步尝试: 尝试一:全局搜索'moduleResolution'发现他在tsconfig.node.json中,修改后并没有消除错误。

尝试二:我发现 tsconfig.app.json 中"compilerOptions"paths中已经添加了@/*,如下,于是我尝试把'./components/Button'这种相对路径的写法改成带'@/*'的方式,结果 build 还是报错,错误几乎没变。

json 复制代码
"paths": {
    "@/*": ["./src/*"]
}

后续又去各个国内外知名论坛社区搜了搜,结果尝试了好多方案还是没解决,真是痛苦。

分析和解决

自己根据报错提示和社区没有找到正确的方式,然后就去 vite-plugin-dts官方 github 仓库,看看 issues(找到了一个跟我类似的但是还没解决,我后续解决了之后还给他写了一大篇英文 comment,我见不得别人受苦哈哈哈),看看源码和文档说明。结果看到了关于 options 的接口说明,其中有这么一个属性字段:

ts 复制代码
/**
   * Specify tsconfig.json path
   *
   * Plugin resolves `include` and `exclude` globs from tsconfig.json
   *
   * If not specified, plugin will find config file from root
   */
  tsconfigPath?: string,

这段代码就是说的,tsconfigPath 是可选的,如果指定了路径,插件会从指定的路径中读取配置文件,然后根据 include 和 exclude 选项来解析 glob 表达式,如果没有指定就从项目根目录找 tsconfig.json 文件。

这就提示我了,默认不传参,插件会从项目根目录开始搜索 tsconfig.json 文件,然后根据 include 和 exclude 选项来解析 glob 表达式。

但是我自己的 tsconfig.json 文件内部是 references 的其他两个文件,除了这两个里面自己并没有 include 和 exclude 选项,所以插件很可能没有解析到 include 和 exclude,这样的效果就是:插件就相当于没有找到任何文件,所以没有生成类型文件。

为了验证我自己的想法,我去 dist 目录一看果然一个都没有生成.d.ts类型文件,稍微看一下源码 getTsConfig 函数的实现,发现确实是进行文件读取再解构得出的 include 和 exclude 一系列配置的,更加验证了我的猜想。

于是我尝试把 tsconfig.app.json 中的 include 和"compilerOptions"的内容复制到 tsconfig.json 中,但是直接就报警告了,说可能会让后续 references 的内容失效,但是我就是想确认一下,所以就没管报警直接 build 的了一下,直接就成功了,现在就只差消除警告了。

上文说过tsconfigPath可以传进去一个配置,用来代替tsconfig.json,所以只需要新建一个tsconfig.build.jsontsconfig.json的内容复制一份进去,然后把这个路径传给vite-plugin-dts插件,就可以了。 我自己的tsconfig.build.json内容如下:

json 复制代码
{
  "extends": "@vue/tsconfig/tsconfig.dom.json",
  "include": ["src/index.ts", "src/components/**/*", "src/hooks/**/*"],
  //include内容根据具体情况自己定制,我是根据组件库自己修改的,如果没动过原来的应该是,下面这个:
  //"include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      "@/*": ["./src/*"]
    }
  },
  "references": [
    {
      "path": "./tsconfig.node.json"
    },
    {
      "path": "./tsconfig.app.json"
    }
  ]
}

vite.config.ts 的 plugins 配置内容:

ts 复制代码
plugins: [
    vue(),
    vueJsx(),
    dts({
      tsconfigPath: './tsconfig.build.json',
    }),
  ],

这样就可以通过 build 生成类型文件了。

总结

本文介绍了 vite-plugin-dts 插件的安装和使用,以及如何解决报错使用插件时遇到的找不到相关模块的问题,层层分析错误,并最终找到解决方案,授之以鱼,且授之以渔,学会这个思路,下次你也行。有收获的话可以点个赞哟。

相关推荐
彭世瑜13 分钟前
ts: TypeScript跳过检查/忽略类型检查
前端·javascript·typescript
FØund40414 分钟前
antd form.setFieldsValue问题总结
前端·react.js·typescript·html
Backstroke fish15 分钟前
Token刷新机制
前端·javascript·vue.js·typescript·vue
小五Five16 分钟前
TypeScript项目中Axios的封装
开发语言·前端·javascript
小曲程序16 分钟前
vue3 封装request请求
java·前端·typescript·vue
临枫54117 分钟前
Nuxt3封装网络请求 useFetch & $fetch
前端·javascript·vue.js·typescript
RAY_CHEN.17 分钟前
vue3 pinia 中actions修改状态不生效
vue.js·typescript·npm
酷酷的威朗普18 分钟前
医院绩效考核系统
javascript·css·vue.js·typescript·node.js·echarts·html5
前端每日三省18 分钟前
面试题-TS(八):什么是装饰器(decorators)?如何在 TypeScript 中使用它们?
开发语言·前端·javascript
小刺猬_98518 分钟前
(超详细)数组方法 ——— splice( )
前端·javascript·typescript