vite+ts搭建Vue组件库并发布至npm

1,359 阅读5分钟

前言

哈喽大家好,我们又见面了
上节我们用pnpm搭建好了项目库后,这节我们开始创建一个Vue组件库,完后我们会打包,并做单元测试,然后发布至pnm。

1.使用Vite和TypeScript来创建UI组件库

Vite是一个现代化的构建工具,旨在提供快速的开发体验和实时的热重载。使用Vite,您可以很容易地构建UI组件库,并将其编译为适用于生产环境的代码。在本文中,我们将使用Vite和TypeScript来创建一个简单的UI组件库。

1.首先,我们需要创建一个新的Vite项目。使用以下命令来安装Vite:

npm install -g vite

2.接下来,我们在project下创建一个新的vite项目:

vite create my-component-library

因为我们是要创建一个vue组件库,所以,选项中我们选vue,语言选择TypeScript,然后一路安装下来即可。

3.在创建项目之后,我们需要创建一个名为“lib”的文件夹来存放所有的组件代码。使用以下命令来创建一个新的“lib”文件夹:

mkdir lib

4.在“lib”文件夹下,我们可以创建一个名为“my-button”的新文件夹来存放我们的第一个组件。

cd lib
mkdir my-button
mkdir src
cd src 
touch index.vue

5.在“index.vue”文件中,我们可以编写我们的组件代码。例如,我们可以编写一个简单的按钮组件:

<template>
  <div class="button-wrap">这是一个button</div>
</template>

<script setup lang="ts">
defineOptions({name: 'BLButton',})

const props = defineProps<{
  plain?: string,
  type: {
    type: string,
    default: 'default'
  }
}>()
</script>

<style scoped lang="scss">
.button-wrap {
  background-color: red;
  height: 44px;
  width: 200px;
  font-size: 14px;
}
</style>

6.我们一般会在my-button下创建一个index.ts用来导出button组件

# 在my-button目录下面执行
touch index.ts
# 打开index.ts,导出button按钮
import button from './src/index.vue'
import { App } from 'vue'

export { button } 

export default {
  install(app: App) {
    app.component(button.name, button)
  }
}

到这里一个简单的按钮组件已经开发完成,接下来我们打包

2.打包

1.作为一个组件库,我们必须有一个统一导出文件,所以一般会在lib下面建一个导出文件

#在lib目录下
touch index.ts

然后将所有的组件在该文件统一导出,打包的时候该文件就是索引的入口文件。
2.打包 由于我们要输出的是组件库,所以我们使用vite的库模式打包,具体见官网,打完包后在package.json有几个重要的参数需要我们配置

  "files": ["dist"], // 发布npm时上传的包
  "main": "./dist/XXX.cjs",  // 使用require引用时的包
  "module": "./dist/XXX.js",  // 使用import引用时的包
  "types": "./dist/XXX.d.ts",    // ts声明时的类型
  //定义外部可访问的资源,如果不定义默认所有都可以访问,定义了就只能访问定义的资源
  "exports": {
    ".": {
      "import": "./dist/XXX.js",
      "require": "./dist/XXX.cjs"
    },
    "./dist/style.css": "./dist/style.css"
  },

3.单元测试

前端常见的测试工具有:

  • mocha:Mocha 是一个功能丰富的 JavaScript 测试框架;
  • jest:facebook 出的一款 JavaScript 自动化测试框架,专注于简单性。
  • vitest:尤大团队打造,一个由 Vite 打造的单元测试框架,而且它很快!
    个人更喜欢vitest,有兴趣的同学可以使用其他的 1.首先我们需要安装vitest依赖, 由于测试Vue组件,需要单独的vue提供的测试插件,因此,我们还需要安装
pnpm add vitest -Dw
pnpm add @vue/test-utils

2.创建vitest的配置文件

touch vitest.config.ts

3.配置

import { resolve } from 'path'
import { defineConfig } from 'vitest/config'

export default defineConfig({
  test: {
    globals: true
  },
  resolve: {
    alias: {
      // componentName是package.json中的name
      'componentName': resolve(__dirname, 'packages/MyCompoent/index.ts'),
    },
  },
})

4.接下来我们就可以去对应的子项目下面创建测试文件了,我们到MyComponent下面的lib目录创建对应的测试文件

# 进入lib目录下面
touch index.test.ts

5.创建完测试文件后,我们需要写测试用例,我们使用vitest搭配vue的测试工具,对我们刚才写的组件进行测试,以下是一个简单的测试,我们分别从四个方面入手

import { describe, it, expect } from 'vitest'
import { mount } from '@vue/test-utils';
import { button } from './MyComponent';

describe('button', () => {
  it('是一个Vue实例', () => {
    const wrapper = mount(button);
    expect(wrapper.vm).toBeTruthy();
  });

  it('默认情况下,显示“Hello, World!”', () => {
    const wrapper = mount(button);
    expect(wrapper.text()).toContain('这是一个button');
  });

  it('当用户单击按钮时,触发事件', async () => {
    const wrapper = mount(button);
    const btn = wrapper.find('div');

    await btn.trigger('click');
    expect(wrapper.emitted()).toBeTruthy();
  });

  it('当props中的message更新时,显示新的消息', async () => {
    const wrapper = mount(button, {
      props: {
        type: 'primary'
      }
    })

    await wrapper.setProps({ type: 'default' });
    expect(wrapper.classes()).toEqual(
      expect.arrayContaining(["default"]))
  });
});

在这个过程中由于涉及dom操作,所以必须提前安装happy-dom(happy dom是一个没有图形用户界面的web浏览器的JavaScript实现),用来模拟dom环境
单测完后,我们就可以进行发布了。

4.发布

如果一个monorepo有多个项目,当我们在根目录下执行'npm login'登录完后执行'npm publish',此时发布成功了,但并不是我们想要的结果,因为发布的是整个monorepo的代码,那怎么办呢?

其实最简单的办法是,我们进入某个项目的根目录下执行npm pubish此时就是将当前包发布至npm仓库
那有没有更好的办法呢,当然有。我们可以使用**changesets** ,changesets为我们提供了指令,可以让我指定发布那个包,具体使用就不在这里演示,大家可以自行查询

好了今天的分享到此结束,下一节前端脚手架搞起