手把手,如何搭建一个通用组件库,并发布到npm?

639 阅读3分钟

最近在造轮子,准备封装一套自己的组件库,手把手系列文章就是造轮子的一些经验总结,

组件库参考了element-plus, iview, naive-ui等源码。

感兴趣的小伙伴可以关注一下,也可以留言想看什么组件的源码。


今天搭建一套通用的组件库框架。

开始之前,先说说为什么要写这样一篇文章。

1.是我自己在搭建的时候,遇到了挺多的坑,可以把这些踩坑的经历分享出来。

2.网上有一些搭建组件库的文章,要么是没有生成ts文件的,要么是基于webpack的,而且没有demo,只有代码片段。(实在不好快速测试)

所以,基于以上原因,分享一个vue+vite+ts+按需打包的方案。

1.创建vue项目

先安装vue官方脚手架,创建一个ui项目。

npm init vue@latest

image.png

因为我们这个是三方的组件库,所以除了vue Router, Pina, Cypress这三个之外,其他全部选择yes即可。

代码提交前的格式检测这些我就不写了,感兴趣的可以搜一下,有很多相关的文章。(主要是不配也没啥影响)

2.先写个简单的组件

import { defineComponent } from 'vue'
import { buttonProps, type ButtonProps } from './button-type'
export default defineComponent({
  name: 'BuButton',
  props: buttonProps,
  setup(props: ButtonProps, { slots }) {
    return () => <div>{slots.default && slots.default()}</div>
  }
})

组件为啥要用tsx写,后面再说。

组件目录结构如下。

image.png

index.ts为组件入口。

import type { App } from 'vue'
import BuButton from './src/button'
// 具名导出
export { BuButton }

// 导出插件
export default {
  install(app: App) {
    app.component('bu-button', BuButton)
  }
}

这个组件基本没有任何内容,就是接受一个插槽(props定义了,但是并未使用)。

3.写打包入口文件

在src下,新疆一个index.ts,把button导出一下。

这里是整个ui库的入口。

import type { App } from 'vue'
import ButtonPlugin, { BuButton } from './components/button'
export { BuButton }

const installs = [ButtonPlugin]

export default {
  install(app: App) {
    installs.forEach((p) => app.use(p))
  }
}

4.打包配置

vite打包成库,在官方文档是有介绍的,直接拷贝一下配置,改一下入口文件。

  build: {
    lib: {
      // Could also be a dictionary or array of multiple entry points
      entry: resolve(__dirname, 'src/index.ts'),
      name: 'MyLib',
      formats: ['es', 'cjs'],
      // the proper extensions will be added
      fileName: 'my-lib'
    },
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: ['vue'],
      output: {
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          vue: 'Vue'
        }
      }
    }
  }

然后执行npm run build,就可以打包了。

image.png

但是,没有ts文件。

打包ts

vite并不支持直接打包.d.ts文件,所以需要使用三方的插件。

// yarn add vite-plugin-dts -D

import dts from 'vite-plugin-dts';
export default defineConfig({
  plugins: [
    vue(),
    vueJsx(),
    dts()
  ]
}

此时,会报but '--jsx' is not set.的错误。(只有jsx语法会报错,模板语法正常)

修改一下配置,tsConfigFilePath指定为tsconfig.app.json,执定为tsconfig.json也会报错。(找了好久)

    dts({
      tsConfigFilePath: "./tsconfig.app.json"
    }),

再次打包,类型文件就有了。

image.png

上传npm

修改package.json文件。

private不能是true,私有的不能上传。配置main,module,types等信息。

如果已经登录了,直接npm publish发布。

否则需要先执行npm login。

ps(因为我的已经发布过了,就不截图了。因为也比较简单,如果有问题,可以参考一下若川大佬的文章。juejin.cn/post/714587…)

此时,一个完整的ui库就有了。

待完善

但是,但是,我们很容易能看出来,这个库还是要啥啥没有呀。

1.没有样式

2.文档系统也没有

3.组件也不能按需加载

这三部分明天聊,如果你想提前先体验一番,也可以访问bubu-ui下载查看。

如果看完有收获,欢迎点赞、评论、分享支持。你的支持和肯定,是我写作的动力