Rollup打包Vue组件库问题汇总
打包类库时 Rollup 是不二选择,如果是常规的 Web 应用的话,Webpack 则更为合适。
最近,我用 Rollup 在为一个 Vue 项目打包组件库时就遇到了几个问题,今天把这些问题和解决方案汇总下来,希望对你也有所帮助。
1. 填写配置时智能提示
Rollup 的配置文件是 .js
文件,也就导致在配置文件中没有像 TS 文件那样的类型提示。而 Rollup 的配置项也不少,如果能在填写配置时有智能提示那就方便多了。
而 Rollup 随附了 TypeScript 类型定义,所以,我们可以使用 JSDoc 类型提示来利用 IDE 的智能感知功能达到这一目的:
// rollup.config.js
/**
* @type {import('rollup').RollupOptions}
*/
const config = {
/* 你的配置 */
};
export default config;
或者使用 defineConfig
辅助函数也行:
// rollup.config.js
import { defineConfig } from 'rollup';
export default defineConfig({
/* 你的配置 */
});
2. 配置文件作为 ES 模块加载
看下面的配置示例:
// rollup.config.js
/**
* @type {import('rollup').RollupOptions}
*/
const config = {
input: 'src/index.js',
output: {
file: 'dist/index.js',
format: 'es',
}
}
export default config
这是我们常见的 ES Module,但是 Rollup 在使用这个配置文件时一定会报错的,因为 Rollup 默认会将配置文件作为 CommonJS 模块加载。我们看一下加载 ES Module 会报什么错:
Rollup 的错误提示写的很清楚,这也是我喜欢 Rollup 的原因之一。它给了三个方案:
-
将 js 格式的配置文件改为 .mjs
格式即可。在《Node 项目如何支持 ES Module?》一文中有介绍,感兴趣的话可以看看。 -
在项目的 package.json
文件中添加"type": "module"
字段也行。意思是 Node.js 默认会将所有.js
文件作为 ES6 模块加载。 -
在使用 Rollup 命令行工具时添加 --bundleConfigAsCjs
参数也可以。这个参数的意思是 Rollup 会将配置文件作为 CommonJS 模块加载。
常见的做法是第二种,只需要在 package.json
文件中加上 "type": "module"
就能解决这个报错问题。
3. 支持打包 ts 文件
在组件库中,大家都习惯用 TypeScript 来编写,但是 Rollup 默认是不支持 TypeScript 的,它只认识 .js
文件,如果让 Rollup 去打包 .ts
文件就会报错:
我们都知道 Webpack 有它的插件系统,Rollup 同样也有。这种情况就得借助 Rollup 的插件来解决了。
这里有个坑 ~
官方插件列表有好多个 TypeScript 插件,你可能会用这个官方提供的 TS 插件:
呵呵,刚开始我也是用的这个插件,但是有问题!应该用 typescript2,也就是下面这个:
而且,Rollup 官方用的也是这个 typescript2。。。
用了这个 ts 插件之后 Rollup 就能认识 ts 文件了:
4. 支持打包 .vue 文件
前面提到,Rollup 只认识 .js
文件,打包 .vue
文件一定会有问题的:
我们还是去 Rollup 的插件列表找找看,发现确实有这样一个插件:
这个插件确实没问题,但是,它的文档中第一句话是这样写的:
显然,插件虽然能工作,但是它已经不维护了,推荐我们用 Vite
和 @vitejs/plugin-vue
。
如果是 Vue3 项目的话,初始化的时候这两个依赖已经安装好了,直接在配置文件中导入应用即可:
这样就可以打包 .vue
文件了。
5. 定位模块
如果在 .vue
文件中添加一些 js 逻辑的话,Rollup 打包可能会输出一些警告信息,如下:
解决方法也很简单,使用 Rollup 官方的 @rollup/plugin-node-resolve
插件即可。该插件用于解决定位和解析模块,以便在 node_modules
中使用第三方模块。
6. 解析 .vue 文件中的样式
组件中不可避免地要编写一些样式,如果 Rollup 直接打包带有样式的组件,Rollup 也会报错:
要解决这个问题,只需要引入对应的样式插件即可。Rollup 插件列表中有很多解析样式的插件,如果你的组件中是纯 CSS 的话,那么我推荐你用 rollup-plugin-css-only
这个插件。如果你用的是 Less 或者 Scss 等预处理器,选择好对应的插件就行了。
7. ts 解析 .vue 文件
当时,这个问题困扰了我许久。
我们在编写组件库时通常要支持两种格式,一个是 esm 格式,另一个是 umd 格式。前者有模块按需加载的特性,后者可以通过 CDN 在全局引入。两种格式各有优劣,对开发者来说,通常都推荐引入 esm 格式的组件库,也就是通过 npm 或者 yan 管理器安装的方式使用。
在 esm 格式的组件库中,会提供一个入口文件访问所有组件,在每个组件所在的目录也会提供一个该组件的入口文件。一方面可以让开发者在使用时可以全局注册组件,也可以在业务中按需引入需要的组件。
这就需要在 .ts 文件中引入 .vue 文件,然后就报错了:
这个问题这是弄了我好久才解决~
在组件目录中,index.ts 是组件的入口文件,它们是同级的,类似于这样:
可以看到,import 语句没有任何问题——它们在同级目录下。那为什么 Rollup 打包的时候会报错说找不到模块呢?根本原因还是因为 ts 不认识 .vue 模块。要解决这个问题需要:
-
在项目中添加一个声明文件,声明 .vue
文件的模块:// shims-vue.d.ts declare module "*.vue" { import { DefineComponent } from "vue"; const component: DefineComponent<{}, {}, any>; export default component; }
-
如果打包还是报错,检查 tsconfig.json 配置文件,看看 includes
或files
字段包含了上面的声明文件,如果没有包含,那就加上。 -
如果你发现在 tsconfig.json 配置文件中是通过项目引用来包含的,那么你就需要在 Rollup 的 typescript 插件中稍作调整才行。 像这样的项目引用的方式,Rollup 是不会读取到子项目中的配置内容的。在 Rollup 插件 typescript 中需要”覆写“一下。一种方法是通过
tsconfig
字段指定要使用的子项目配置文件:另一种就是覆盖项目中默认的配置:
8. 导出类型定义文件
在使用组件库时,肯定要提供类型的声明文件的。在 typescript 插件中将 compilerOptions.declaration
设置为 true 即可。
有一点需要注意,因为是 Vue 组件库,那么 Rollup 打包的时候应该把 Vue 排除出去。一来,把 vue 打包到最终文件体积会非常大;二来也没必要将 vue 打包进去。要做到这一点,可以在 Rollup 中配置 external
字段:
/** @type {import('rollup').RollupOptions} */
const config = {
input: 'src/index.ts',
output: {
file: file('esm'),
format: 'es'
},
external: ['vue']
}
9. 小结
以上是 Rollup 在打包 Vue 组件库时可能会遇到的一些问题和解决方案。
前面提到,组件库还应该提供 umd 格式的产出文件。我在打包 umd 文件时确实也碰到了几个小问题,但是都比较容易解决,这里就不罗列了。
如果你想要给自己的项目抽象组件库的话,上面的几个问题应该能帮你节省至少半天的时间。至于开发组件库的其他问题,比如提交前的代码校验、格式化,甚至代码库的单元测试、CI/CD 等,这些就是另外的问题了,以后有机会我们讨论。