Vite 打包 TS 类型声明文件目前没有可用的 plugin。有人在 issue 中提出希望 Vite 内部支持在库模式打包时导出声明文件,但 Vite 官方表示不希望因此增加维护的负担和结构的复杂性
因此在 Vite 开发中,我们要想一些其他办法来生成声明文件
必要的配置
不管使用什么方法,生成类型声明文件,最根本的还是通过 TypeScript 本身的特性及配置项去提取 .d.ts 文件,再使用一些手段将文件写到打包路径下
需要设置 declaration, emitDeclarationOnly 为 true
新建 tsconfig.types.json 文件,写入以下内容,这个配置文件仅用来提取类型声明文件时使用
{
"extends": "./tsconfig.json",
"compilerOptions": {
"declaration": true,
"emitDeclarationOnly": true,
},
"include": ["src"]
}
几种思路
- 使用
ts compiler编译出来 - 使用
Rollup.js生成.d.ts文件 - 使用
Gulp.js生成.d.ts文件 - 使用
ts-morph生成.d.ts文件 最终选择了使用ts-morph生成.d.ts文件
原因在于 Rollup.js、Gulp.js 都是很好的、相当强大的工具,但是正因为其五脏俱全,我们不选择它
我们要做的事情就是提取类型声明文件,没有其他,而 ts-morph 只做了这件事,很好的满足这一点
使用 ts compile 直接编译
tsc -p ./tsconfig.types.json'
直接使用 tsc 无疑是一种很便捷的方式。但是会带来一个问题是如果你在打包时改变了项目的目录结构,或者想要做到按需引入,这个时候 tsc 就没法满足我们的需求了。
与此同时,我们没有机会体验工程化带来的便利。
比如,我们可能需要在项目 package.json 下新加
build:types: "tsc -p ./tsconfig.types.json"
这样以便其能够参与到项目的持续构建、集成中去
使用 Rollup.js 生成 .d.ts 文件
在开发 rollup 插件时,我们主要借助一些插件:如 rollup-plugin-typescript2、rollup-plugin-dts 等,来实现根据源码生成 .d.ts 声明文件
yarn add rollup-plugin-typescript2 typescript tslib --dev
// rollup.config.js
import typescript from 'rollup-plugin-typescript2'
...
export default {
input: './main.ts',
plugins: [
typescript({
compilerOptions: {
declaration: true,
emitDeclarationOnly: true
}
})
]
}
经过尝试,vite 内置 rollup,但是其 rollupOptions 配置项只支持单配置项。在前面文章中我们已经使用 rollup 来实现库按需打包。所以没法使用 rollup 插件
使用 Gulp.js 生成 .d.ts 文件
Gulp.js 是一个自动化构建工具,开发者可以使用它在项目开发过程中自动执行常见任务。Gulp.js 是基于 Node.js 构建的,利用 Node.js 流的威力,你可以快速构建项目并减少频繁的 IO 操作
yarn global add gulp-cli
then
yarn add gulp@4 --dev
yarn add gulp-typescript typescript --dev
const gulp = require('gulp');
const ts = require('gulp-typescript');
...
gulp.task('declaration', function () {
const tsProject = ts.createProject('tsconfig.types.json');
return tsProject.src().pipe(tsProject()).pipe(gulp.dest('lib/'));
});
exports.default = gulp.series('cjs', 'es', 'declaration');
使用 ts-morph 生成 .d.ts 文件
ts-morph 是一个 TypeScript 编译器 API 包装器。提供一种更简单的方式来以编程方式导航和操作 TypeScript 和 JavaScript 代码
直接开撸,新建 buildTypes.ts 文件
const path = require('path')
// https://www.npmjs.com/package/ts-morph
const { Project } = require('ts-morph')
const outDir = 'lib/es'
const main = async () => {
// 这部分内容具体可以查阅 ts-morph 的文档
// 这里仅需要知道这是用来处理 ts 文件并生成类型声明文件即可
const project = new Project({
tsConfigFilePath: path.resolve(__dirname, 'tsconfig.types.json'),
})
const diagnostics = project.getPreEmitDiagnostics()
// 输出解析过程中的错误信息
console.log(project.formatDiagnosticsWithColorAndContext(diagnostics))
// 将解析完的文件写到打包路径
project.emit()
// 将解析完的文件写到内存中,便于读取文件路径
const result = project.emitToMemory()
// 将文件路径打印到控制台
console.log(
result._files.map((file) => file.filePath.slice(file.filePath.indexOf(outDir)))
)
console.info(
`\nSuccess emit declaration file!\n
The project has generate ${result._files.length} typescript declaration files\n`
)
}
main()
在项目 packages.json 中新增以下配置
"types": "lib/es/index.d.ts",
"scripts": {
"build:types": "ts-node buildTypes.ts",
}
这样,我们就可以在引用项目时,根据引用进行对应的类型提示了
参考文档
Rollup.js 官方文档
Gulp.js 中文官方文档
rollup-plugin-typescript2
rollup-plugin-dts
ts-morph