likes
comments
collection
share

🔥超详细:Vite搭建组件库改造300星颜色选择器vcolorpicker

作者站长头像
站长
· 阅读数 64

以下就基于vcolorpicker为案例,讲述使用 vue3+vite 从开发到发布npm的全流程。

vColorPicker 文档 DEMO

一、技术栈

直接使用 vite 创建初始 vue 项目,具体就不提了直接看官方文档就成

  • vite
  • vue3
  • TS
  • @vueuse/core 一些工具方法,非常实用
  • git-cz 用于代码提交规范
  • release-it 用于自动提升版本、打tag、生成变更日志等

二、思路大纲

要想搭建一个组件库,先要有一个大概的思路,后续的开发方向就非常明确了。

  1. 添加代码提交规范
  2. 添加自动提升版本、打tag、生成变更日志等
  3. 规划项目目录结构
  4. 编写组件
  5. 编写示例
  6. 打包配置
  7. 编写模块包声明文件
  8. 发布到npm

三、添加代码提交规范

1. 安装 git-cz 工具包

pnpm i -D git-cz

2. 添加提交脚本命令

package.json文件中添加以下内容

{
  "scripts": {
    "commit": "git-cz"
  }
}

3. 使用 pnpm commit提交代码

代码更改后使用命令提交代码

pnpm commit

使用提交命令后,会提示选择以何种方式提交代码

@zuley ➜ /workspaces/vue-color-picker (2.0 ✗) $ pnpm commit

> vcolorpicker@2.0.0 commit /workspaces/vue-color-picker
> git-cz

? Select the type of change that you're committing: (Use arrow keys or type to search)
❯ 💍  test:       Adding missing tests # 添加测试
  🎸  feat:       A new feature # 新特性
  🐛  fix:        A bug fix # 修复bug
  🤖  chore:      Build process or auxiliary tool changes # 构建过程或辅助工具更改
  ✏️  docs:       Documentation only changes # 仅文档修改
  💡  refactor:   A code change that neither fixes a bug or adds a feature # 即不修复错误也不添加功能的修改
  💄  style:      Markup, white-space, formatting, missing semi-colons... #标记、空格、格式化、缺少分号等...
(Move up and down to reveal more choices) # 上下移动回车选择

回车后下一步输入提交的简短描述

? Write a short, imperative mood description of the change: 
  [-------------------------------------------------------------] 55 chars left
   docs: 修改文档

输入内容后回车,下一步输入提交较详细的描述

? Provide a longer description of the change:
  修改 README.md 文件中的内容

输入内容后回车,下一步输入列出较大的变更,没有就直接跳过

? List any breaking changes
  BREAKING CHANGE: 

回车后,下一步可选择输入要当前提交需要关联的 issues的ID格式如:#4,一般用于修复用户提交的问题

? Issues this commit closes, e.g #123: #4

四、添加自动提升版本、打tag、生成 changelog 等

1. 使用release-it工具初始化

npm init release-it

执行初始化后,提示是否安装依赖,直接选择是。

接着提示是否每次推送代码的时候,都发布到 release

? Publish a GitHub Release with every release? › (Y/n)

然后提示选择将配置添加到独立文件还是 package.json

? Where to add the release-it config? ›  
❯   .release-it.json
    package.json

再安装 changelog 插件

pnpm i @release-it/conventional-changelog -D

紧接着修改 package.jsonrelease-it配置

{
  "release-it": {
    "github": {
      "release": false
    },
    "git": {
      "commitMessage": "release: v${version}"
    },
    "npm": {
      "publish": false
    },
    "hooks": {
      "after:bump": "echo 更新版本成功"
    },
    "plugins": {
      "@release-it/conventional-changelog": {
        "preset": "angular",
        "infile": "CHANGELOG.md"
      }
    }
  }
}

2. 使用 pnpm release构建变更并推送代码

初始化及配置完成后,使用命令构建变更

pnpm release

执行后得到以下输出

@zuley ➜ /workspaces/vue-color-picker (2.0) $ pnpm release

> vcolorpicker@2.0.0 release /workspaces/vue-color-picker
> release-it


🚀 Let's release vcolorpicker (2.0.0...2.0.1)


Changelog:
## [2.0.1](https://github.com/zuley/vue-color-picker/compare/v1.1.0...v2.0.1) (2022-11-26)

✔ echo 更新版本成功

Changeset:
A  CHANGELOG.md
 M package.json

? Commit (release: v2.0.1)? Yes
? Tag (v2.0.1)? Yes
? Push? Yes
🏁 Done (in 249s.)
  1. 自动提升版本号
  2. 自动输出变更日志
  3. 自动提交了输出的变更代码
  4. 自动打好了 tag
  5. 自动将提交推送到了 github

注意:此命令用于发布版本都提交,会自动升级版本号变更日志等。正常代码提交使用常规的推送命令。

五、规划目录结构

1. 目录结构

.
...
|-- examples      // 原 src 目录,改成 examples 用作示例展示
|-- packages      // 新增 packages 用于编写存放组件
...
. 

2. 原 src 目录,改成 examples 用作示例展示

重命名 src目录为examples后项目要能正常运行需修改对应位置的配置如下

修改 vite.config.ts的配置

// vite.config.ts
import { fileURLToPath, URL } from 'node:url'

import { defineConfig } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      // 修改这一行的  src 为 examples
      // '@': fileURLToPath(new URL('./src', import.meta.url))
      '@': fileURLToPath(new URL('./examples', import.meta.url))
    }
  }
})

修改tsconfig.json的配置

{
  "extends": "@vue/tsconfig/tsconfig.web.json",
  // 修改这一行的 src 为 examples
  // "include": ["env.d.ts", "examples/**/*", "examples/**/*.vue"],
  "include": ["env.d.ts", "src/**/*", "src/**/*.vue"],
  "compilerOptions": {
    "baseUrl": ".",
    "paths": {
      // 修改这一行的 src 为 examples
      // "@/*": ["./src/*"]
      "@/*": ["./examples/*"]
    }
  },

  "references": [
    {
      "path": "./tsconfig.config.json"
    }
  ]
}

修改index.html 的引入

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8">
    <link rel="icon" href="/favicon.ico">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Vite App</title>
  </head>
  <body>
    <div id="app"></div>
    <!-- 修改这里的 src 为 examples -->
    <script type="module" src="/examples/main.ts"></script>
  </body>
</html>

3. 新增 packages 用于编写存放组件

新增examples同级目录packages并创建一个main.ts

// packages/main.ts
console.log('我被引入了')
export default {
  x: '我是vColorPicker组件'
}

tsconfig.json中添加此目录的支持

{
  // 添加 "packages/**/*", "packages/**/*.vue"
  "include": ["env.d.ts", "examples/**/*", "examples/**/*.vue", "packages/**/*", "packages/**/*.vue"],
}

examples/main.ts中引入packages/main.ts

import vColorPicker from './../packages/main'
console.log('vColorPicker', vColorPicker)

运行后查看控制台效果

🔥超详细:Vite搭建组件库改造300星颜色选择器vcolorpicker

此时此目录已成功添加

六、编写组件

以上我们已配置好对新目录架构的支持,接下来我们尝试编写组件。以下我们以一个已发布到 npm 的组件为示例。

Github - 颜色选择器:vcolorpicker

1. 创建一个新组件

  1. packages 目录下,所有的单个组件都以文件夹的形式存储,所有这里创建一个目录 color-picker/
  2. color-picker/ 目录下创建 src/ 目录存储组件源码
  3. /color-picker 目录下创建 index.ts 文件对外提供对组件的引用。
.
├── packages
│   ├── color-picker
│   │   ├── index.ts
│   │   └── src
│   │       └── index.vue
│   └── main.ts

修改/packages/color-picker/src/index.vue提供组件具体实现引用

这里要注意的是组件名字无法在<script setup> 中声明,需要另起一个。 参考官方资料:cn.vuejs.org/api/sfc-scr…

<script lang="ts">
// 声明无法在 <script setup> 中声明的选项
export default {
  name: "colorPicker"
}
</script>

<script setup lang="ts">
const props = defineProps<{
  modelValue: string
}>()
const emits = defineEmits<{
  (e: 'update:modelValue', value: string): void
}>()
</script>

<template>
  测试组件
  <div class="add" @click="$emit('update:modelValue', 'ddd')">add</div>
</template>

修改/packages/color-picker/index.ts文件,对外提供引用

import type { Plugin } from "vue"
// 导入组件
import colorPicker from "./src/index.vue"

// 为组件提供 install 安装方法,供按需引入
colorPicker.install = function (app, options) {
  app.component(colorPicker.name, colorPicker)
} as Plugin

// 默认导出组件
export default colorPicker

2. 整合所有组件,对外导出,即一个完整的组件库

修改/packages/main.ts文件,对外提供引用

import type { Plugin } from 'vue'
// 导入颜色选择器组件
import colorPicker from './color-picker'

// 存储组件列表
const components = [
  colorPicker
]

// 定义 install 方法,接收 app 作为参数。如果使用 use 注册插件,则所有的组件都将被注册
const install: Plugin['install'] = function (app) {
  // 遍历注册全局组件
  components.map(component => app.component(component.name, component))
}

export default {
  install,
  colorPicker
}

七、编写示例

1、在示例中导入组件库

import { createApp } from 'vue'
import App from './App.vue'
// 导入组件库
import vColorPicker from './../packages/main'

const app = createApp(App)
// 注册组件库
app.use(vColorPicker)

app.mount('#app')

2、在示例中使用组件库的组件

在上一步中使用 app.use() 全局注册后,即可在任意页面直接使用了,而不需另外引入。当然也可以按需引入,这里暂时不展开。

<script setup lang="ts">
import { ref } from 'vue';

const color = ref('')
const headleChangeColor = (val: string) => {
  console.log('颜色改变', val)
}
</script>

<template>
  <colorPicker v-model="color" @update:modelValue="headleChangeColor" />
</template>

八、打包配置

1、package.json中新增一条编译为库的命令

{
  "scripts": {
    "lib": "vite build --mode lib",
  }
}

2、配置vite.config.ts

import { fileURLToPath, URL } from 'node:url'
import { resolve } from 'path'

import { defineConfig } from 'vite'
import type { UserConfigExport } from 'vite'
import vue from '@vitejs/plugin-vue'

export default defineConfig((env) => {
  const defaultConfig: UserConfigExport = {
    plugins: [vue()],
    resolve: {
      alias: {
        '@': fileURLToPath(new URL('./examples', import.meta.url))
      }
    }
  }
  // 当执行 pnpm lib 设置环境变量 --mode lib 时
  if (env.mode === 'lib') {
    defaultConfig.build = {
      lib: {
        entry: resolve(__dirname, 'packages/main.ts'),
        name: 'vcolorpicker',
        fileName: 'vcolorpicker'
      },
      rollupOptions: {
        // 打包忽略 vue
        external: ['vue'],
        output: {
          globals: {
            vue: 'Vue'
          },
          // 输出目录
          dir: 'lib'
        }
      }
    }
  }
  return defaultConfig
})

配置好后,执行 lib 命令,可针对走lib的配置。这里主要必须要加判断,不然针对的就是所有的编译命令。

九、编写模块包声明文件

在根目录或者根据个人需求创建入口 .d.ts,这个主要是其他项目安装本模块时候,指定的声明文件解析。这里只做简单示例,各位根据实际需求就行。

// index.d.ts
import type { App } from 'vue';
declare const _default: {
  install: (app: App<any>) => App<any>;
};
export default _default;

十、发布到npm,方便在项目中引用

到这里我们一个完整的组件库已经开发完成了,接下来就是将其发布到 npm 以供后期使用。

1、package.json中新增一条编译为库的命令

{
  "scripts": {
    "lib": "vite build --mode lib",
  }
}

2、配置 package.json 文件中发布到 npm 的字段

参数说明
name包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
version版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
description包描述
type指定包类型
main定义这个 package 的入口文件位置。显示定义 "type": "module",那么它指向的就是 ES6 模块,如果没有则解释为CommonJS模块
exports同上,处理复杂入口,优先级高于main
types指定TS声明文件入口
keyword关键字,便于用户搜索
author作者
private是否私有,需要修改为 false 才能发布到 npm
license开源协议

参考配置如下

{
  "name": "vcolorpicker",
  "version": "2.0.11",
  "type": "module",
  "description": "基于 Vue3 的颜色选择器",
  "main": "./lib/vcolorpicker.js",
  "module": "./lib/vcolorpicker.js",
  "types": "./index.d.ts",
  "exports": {
    ".": {
      "import": "./lib/vcolorpicker.js",
      "require": "./lib/vcolorpicker.mjs"
    },
    "./lib/*": "./lib/*"
  },
  "keywords": [
    "vcolorpicker",
    "colorpicker",
    "color-picker",
    "vue-color-picker"
  ],
  "author": "zuley",
  "license": "MIT",
  "homepage": "https://github.com/zuley/vue-color-picker",
  "private": false,
}

3、添加 .npmignore 文件,设置忽略发布文件

我们发布到 npm 中,只有编译后的 lib 目录、package 目录 等才是需要被发布的。所以我们需要设置忽略目录和文件。

# 忽略目录
examples/
public/
dist/
.vscode/
.devcontainer/

# 忽略指定文件
vite.config.ts
pnpm-lock.yaml
index.html
env.d.ts
CHANGELOG.md
.gitignore
*.map

4、登录到NPM

首先需要到 npm 上注册一个账号,注册过程略。

如果配置了淘宝镜像,先设置回npm镜像:

npm config set registry http://registry.npmjs.org 

然后在终端执行登录命令,输入用户名、密码、邮箱即可登录。

# 执行登录命令
npm login
# 输入用户名
Username: 用户名
Password: 密码
Email: (this IS public) 邮箱
npm notice Please check your email for a one-time password (OTP)
Enter one-time password: 邮箱中接收的一次性密码

5、发布到NPM

执行发布命令,发布组件到 npm

npm publish

执行过程如下

npm notice 
npm notice 📦  vcolorpicker@2.0.1
npm notice === Tarball Contents === 
npm notice 26B    README.md              
npm notice 4.3kB  lib/favicon.ico        
npm notice 1.8kB  lib/style.css          
npm notice 10.1kB lib/vcolorpicker.mjs   
npm notice 7.7kB  lib/vcolorpicker.umd.js
npm notice 1.6kB  package.json           
npm notice 328B   tsconfig.json          
npm notice === Tarball Details === 
npm notice name:          vcolorpicker                            
npm notice version:       2.0.1                                   
npm notice filename:      vcolorpicker-2.0.1.tgz                  
npm notice package size:  8.9 kB                                  
npm notice unpacked size: 25.8 kB                                 
npm notice shasum:        dcb708dc942082e78e0a84c251f528bc7762fc29
npm notice integrity:     sha512-2HbIL9dBAP4eK[...]Y/6J5cHwcu3cQ==
npm notice total files:   7                                       
npm notice 
npm notice Publishing to https://registry.npmjs.org/
+ vcolorpicker@2.0.1

6、发布成功

发布成功后稍等几分钟,即可在 npm 官网搜索到。

7、使用新发布到组件库

pnpm i vcolorpicker -S

使用

// 在 main.ts 引入并注册
import { createApp } from 'vue'
import vColorPicker from 'vcolorpicker'
import 'vcolorpicker/lib/style.css'

const app = createApp(App)
app.use(vColorPicker)

// 在组件中使用
<template>
  <colorPicker v-model="color" @change="headleChangeColor"></colorPicker>
</template>

<script lang="ts" setup>
import { ref } from 'vue';

const color = ref('#ff0000')

const headleChangeColor = (color: string) => {
  console.log(`颜色值改变事件:${color}`)
}
</script>

十一、项目地址

Github 地址:https://github.com/zuley/vue-color-picker

npm 地址:https://www.npmjs.com/package/vcolorpicker

DEMO 演示:http://vue-color-picker.rxshc.com

十二、参考

Moule 的加载实现:https://es6.ruanyifeng.com/#docs/module-loader

TypeScript声明文件:https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html

Vite官方文档:https://cn.vitejs.dev/guide/

详解:Vue cli3 库模式搭建组件库并发布到 npm:https://juejin.cn/post/6844903687668629518

转载自:https://juejin.cn/post/7174768123223932984
评论
请登录