Rollup打包Vue组件库问题汇总

2023-08-0711:30:59WEB前端开发Comments1,672 views字数 3404阅读模式

打包类库时 Rollup 是不二选择,如果是常规的 Web 应用的话,Webpack 则更为合适。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

最近,我用 Rollup 在为一个 Vue 项目打包组件库时就遇到了几个问题,今天把这些问题和解决方案汇总下来,希望对你也有所帮助。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

1. 填写配置时智能提示

Rollup 的配置文件是 .js 文件,也就导致在配置文件中没有像 TS 文件那样的类型提示。而 Rollup 的配置项也不少,如果能在填写配置时有智能提示那就方便多了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

而 Rollup 随附了 TypeScript 类型定义,所以,我们可以使用 JSDoc 类型提示来利用 IDE 的智能感知功能达到这一目的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

// rollup.config.js
/**
 * @type {import('rollup').RollupOptions}
 */
const config = {
 /* 你的配置 */
};
export default config;

或者使用 defineConfig 辅助函数也行:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

// rollup.config.js
import { defineConfig } from 'rollup';

export default defineConfig({
 /* 你的配置 */
});

2. 配置文件作为 ES 模块加载

看下面的配置示例:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

// 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 会报什么错:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup 的错误提示写的很清楚,这也是我喜欢 Rollup 的原因之一。它给了三个方案:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

  1. 将 js 格式的配置文件改为 .mjs 格式即可。在《Node 项目如何支持 ES Module?》一文中有介绍,感兴趣的话可以看看。
  2. 在项目的 package.json 文件中添加 "type": "module" 字段也行。意思是 Node.js 默认会将所有 .js 文件作为 ES6 模块加载。
  3. 在使用 Rollup 命令行工具时添加 --bundleConfigAsCjs 参数也可以。这个参数的意思是 Rollup 会将配置文件作为 CommonJS 模块加载。

常见的做法是第二种,只需要在 package.json 文件中加上  "type": "module" 就能解决这个报错问题。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

3. 支持打包 ts 文件

在组件库中,大家都习惯用 TypeScript 来编写,但是 Rollup 默认是不支持 TypeScript 的,它只认识 .js 文件,如果让 Rollup 去打包 .ts 文件就会报错:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

我们都知道 Webpack 有它的插件系统,Rollup 同样也有。这种情况就得借助 Rollup 的插件来解决了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

这里有个坑 ~文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

官方插件列表有好多个 TypeScript 插件,你可能会用这个官方提供的 TS 插件:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

呵呵,刚开始我也是用的这个插件,但是有问题!应该用 typescript2,也就是下面这个:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

而且,Rollup 官方用的也是这个 typescript2。。。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

用了这个 ts 插件之后 Rollup 就能认识 ts 文件了:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

4. 支持打包 .vue 文件

前面提到,Rollup 只认识 .js 文件,打包 .vue 文件一定会有问题的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

我们还是去 Rollup 的插件列表找找看,发现确实有这样一个插件:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

这个插件确实没问题,但是,它的文档中第一句话是这样写的:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

显然,插件虽然能工作,但是它已经不维护了,推荐我们用 Vite 和 @vitejs/plugin-vue文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

如果是 Vue3 项目的话,初始化的时候这两个依赖已经安装好了,直接在配置文件中导入应用即可:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

这样就可以打包 .vue 文件了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

5. 定位模块

如果在 .vue 文件中添加一些 js 逻辑的话,Rollup 打包可能会输出一些警告信息,如下:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

解决方法也很简单,使用 Rollup 官方的 @rollup/plugin-node-resolve 插件即可。该插件用于解决定位和解析模块,以便在 node_modules 中使用第三方模块。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

6. 解析 .vue 文件中的样式

组件中不可避免地要编写一些样式,如果 Rollup 直接打包带有样式的组件,Rollup 也会报错:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

要解决这个问题,只需要引入对应的样式插件即可。Rollup 插件列表中有很多解析样式的插件,如果你的组件中是纯 CSS 的话,那么我推荐你用 rollup-plugin-css-only 这个插件。如果你用的是 Less 或者 Scss 等预处理器,选择好对应的插件就行了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

7. ts 解析 .vue 文件

当时,这个问题困扰了我许久。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

我们在编写组件库时通常要支持两种格式,一个是 esm 格式,另一个是 umd 格式。前者有模块按需加载的特性,后者可以通过 CDN 在全局引入。两种格式各有优劣,对开发者来说,通常都推荐引入 esm 格式的组件库,也就是通过 npm 或者 yan 管理器安装的方式使用。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

在 esm 格式的组件库中,会提供一个入口文件访问所有组件,在每个组件所在的目录也会提供一个该组件的入口文件。一方面可以让开发者在使用时可以全局注册组件,也可以在业务中按需引入需要的组件。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

这就需要在 .ts 文件中引入 .vue 文件,然后就报错了:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

这个问题这是弄了我好久才解决~文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

在组件目录中,index.ts 是组件的入口文件,它们是同级的,类似于这样:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

可以看到,import 语句没有任何问题——它们在同级目录下。那为什么 Rollup 打包的时候会报错说找不到模块呢?根本原因还是因为 ts 不认识 .vue 模块。要解决这个问题需要:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

  1. 在项目中添加一个声明文件,声明 .vue 文件的模块:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html
    // shims-vue.d.ts
    declare module "*.vue" {
      import { DefineComponent } from "vue";
      const component: DefineComponent<{}, {}, any>;
      export default component;
    }
    
  2. 如果打包还是报错,检查 tsconfig.json 配置文件,看看 includes 或 files 字段包含了上面的声明文件,如果没有包含,那就加上。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html
  3. 如果你发现在 tsconfig.json 配置文件中是通过项目引用来包含的,那么你就需要在 Rollup 的 typescript 插件中稍作调整才行。Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

    像这样的项目引用的方式,Rollup 是不会读取到子项目中的配置内容的。在 Rollup 插件 typescript 中需要”覆写“一下。一种方法是通过 tsconfig 字段指定要使用的子项目配置文件:Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

    另一种就是覆盖项目中默认的配置:Rollup打包Vue组件库问题汇总文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

8. 导出类型定义文件

在使用组件库时,肯定要提供类型的声明文件的。在 typescript 插件中将 compilerOptions.declaration 设置为 true 即可。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

有一点需要注意,因为是 Vue 组件库,那么 Rollup 打包的时候应该把 Vue 排除出去。一来,把 vue 打包到最终文件体积会非常大;二来也没必要将 vue 打包进去。要做到这一点,可以在 Rollup 中配置 external 字段:文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

/** @type {import('rollup').RollupOptions} */
const config = {
  input: 'src/index.ts',
  output: {
    file: file('esm'),
    format: 'es'
  },
  external: ['vue']
}

9. 小结

以上是 Rollup 在打包 Vue 组件库时可能会遇到的一些问题和解决方案。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

前面提到,组件库还应该提供 umd 格式的产出文件。我在打包 umd 文件时确实也碰到了几个小问题,但是都比较容易解决,这里就不罗列了。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

如果你想要给自己的项目抽象组件库的话,上面的几个问题应该能帮你节省至少半天的时间。至于开发组件库的其他问题,比如提交前的代码校验、格式化,甚至代码库的单元测试、CI/CD 等,这些就是另外的问题了,以后有机会我们讨论。文章源自菜鸟学院-https://www.cainiaoxueyuan.com/gcs/52774.html

  • 本站内容整理自互联网,仅提供信息存储空间服务,以方便学习之用。如对文章、图片、字体等版权有疑问,请在下方留言,管理员看到后,将第一时间进行处理。
  • 转载请务必保留本文链接:https://www.cainiaoxueyuan.com/gcs/52774.html

Comment

匿名网友 填写信息

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定