如何使用vue+vite在npm发布一个属于自己的组件库

155 阅读5分钟

作为一个又上进心的程序员,需要累积一定的技术资源,这样跳槽面试的时候也是拥有一定的优势,在前端,如果你有一两件能拿的出手的线上作品,那么你将会打败好多你的竞争者,拿到自己心仪的‘俸禄’,最最最简单的就是编写一个自己的组件库发布到npm,然后为这个组件库编写一个文档,发布到自己的服务器

前期准备

  • 首先需要注册一个npm官网账号,注意邮箱验证。

  • 如果配置了淘宝源,先设置回npm源。

    • 在控制台输入npm config set registry http://registry.npmjs.org 切换源
  • 然后在本地使用npm login登录

  • 如果登录成功使用命令npm whoami则会输出当前登录用户名

搭建组件库

使用vite脚手架搭建一个项目

使用 NPM:

$ npm create vite@latest

使用 Yarn:

$ yarn create vite

使用 PNPM:

$ pnpm create vite

然后按照提示操作即可!

配置为库模式

  • 在项目根目录下新建packages文件夹用来存放组件
  • 在项目根目录下新建docs文件夹用来存放文档
  • 将src目录改名为examples作为开发调试组件的目录
  • 修改vite配置文件vite.config.js,详情如下:
import { defineConfig } from 'vite';
import vue from '@vitejs/plugin-vue';
import path from 'path';
const { resolve } = path;

export default defineConfig({
  plugins: [vue()],
  build: {
    outDir: 'lib', // 文件输出目录,对应package.json中的file字段
    lib: // 库打包模式
    {
      entry: resolve(__dirname, 'packages/index.js'), //指定组件编译入口文件
      name: 'name', // 库的名称
      fileName: 'filename', // 输出的文件名
    },//库编译模式配置
    rollupOptions: {
      // 确保外部化处理那些你不想打包进库的依赖
      external: ['vue'],
      output: {
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          vue: 'Vue',
        },
      },
    },// rollup打包配置
  },
});
  • 修改package.json,详细配置如下:
{
  "name": "packagename", // 包名 ps:不能重复
  "private": false, // 设置为false即公开这个库
  "version": "1.0.0", // 版本号 ps:每次发布的时候版本号必须大于前一版本号
  "author": {
    "name": "作者的名字"
  },
  "keywords": [], // 在npm官网搜索时的关键词
  "files": [
    "lib" //打包的路径
  ],
  //   "type": "module", 
  //这个属性设置为module,打出来两个文件 filename.js和 filename.umd.cjs 
  //对应这里的filename.mjs和filename.umd.js
  "main": "./lib/filename.umd.js", // 指定包的主文件
  "module": "./lib/filename.mjs", // 指定模块文件
  "exports": { // 定义库所暴露的文件
    "./lib/style.css": "./lib/style.css", 
    // 样式最终打包为一个css文件,需单独引入 import 'packagename/lib/style.css'
    ".": {
      "import": "./lib/filename.mjs", //指定使用import 引入时指向的文件
      "require": "./lib/filename.umd.js" // 指定使用require引入时指定的文件
    }
  },
  "scripts": {
    "dev": "vite",
    "build": "vite build", // 打包
    "docs:dev": "vitepress dev docs", //运行文档,文档搭建在文章下面
    "docs:build": "vitepress build docs",
    "register:components": "vitepress-rc"
  },
  "dependencies": {
    "vue": "^3.2.37",
  },
  "devDependencies": {
    "@vitejs/plugin-vue": "^3.1.0",
    "@vitejs/plugin-vue-jsx": "^2.0.1",
    "sass": "^1.54.9",
    "vite": "^3.1.0",
    "vitepress": "1.0.0-alpha.4",
    "vitepress-theme-demoblock": "^1.4.2"
  }
}

到这里ui组件库的整体目录结构为就创建好了,组件开发的流程就不做详细介绍总之需要在打包入口文件将组件暴露出来即可,提供一个思路

export default {
  name: "x-cmp1",
};
</script>

如果是vue3的写法,name需要在组件中单独暴露

import Cmp1 from './Cmp1';

const components = [Cmp1];


export default {
    install: (App) => {
        components.forEach((item) => {
            App.component(item.name, item); //全局注册
        });
    }
}
export const XCmp1 = Cmp1; // 按需导入


打包加发布

  • 运行npm run build 将组件库打包,得到lib文件夹
  • 创建.npmignore文件,里边是不需要发布的文件,大致内容如下
.DS_Store
node_modules
document
/dist

# local env files
.env.local
.env.*.local

# Log files
npm-debug.log*
yarn-debug.log*
yarn-error.log*

# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
*.sw*

# 以下是新增的
# 要忽略目录和指定文件
.vscode
examples/
packages/
public/
xuidocs/
vite.config.js
*.map
*.html
  • 运行npm publish 发布,如果包名重复,则会报没有权限之类的错误,这时修改包名重新发布即可

给组件库编写文档

文档使用vitepress来搭建,内置到我们的组件仓库

安装依赖

所需依赖已经在上面package.json中列出,直接yarn即可安装
vitepress-theme-demoblock这个依赖是核心

配置文档项目

目录结构如下

image.png .vitepress目录下是对文档的一些配置
theme目录下是对文档主题的一些配置
register-components.js不用自己去创建,运行npm run register:components即可自动生成
index.js是对文档项目的一些预处理,内容如下:

import Theme from 'vitepress/theme';
import packagename from 'xuan-vue-ui';
import 'xuan-vue-ui/lib/style.css';
import 'vitepress-theme-demoblock/theme/styles/index.css'
import { registerComponents } from './register-components'
export default {
  ...Theme,
  enhanceApp({ app }) {
    app.use(packagename); //全局注册我们的组件库
    registerComponents(app); // 将vitepress-theme-demoblock插件的组件全局注册
  }
}

config.js是对文档的一些配置,内容如下:

import VTD from 'vitepress-theme-demoblock';
export default {
    // 网站标题
    title: 'xuan-vue-ui',
    lang: 'zh_cn',
    // 网站描述
    description: '一个基于vue3的自用ui组件库',
    // 打包目录
    base:'/xuidocs/', // baseUrl
    outDir:'../xuidocs', //输出路径
    dest: './xuidocs',
    plugins: [],
    head: [
        // 添加图标
        ['link', { rel: 'icon', href: '/xuidocs/favicon.ico' }]
    ],
    themeConfig: {
        logo: '/logo1.png',
        // 展示搜索框 这里需要自己去申请algolia的账号获取appId和appKey
        algolia: {
            appId: "",
            apiKey: '',
            indexName: 'vite-press',
            searchParameters: {
                faeFilters: ['tags: guide, api']
            }
        },
        //社交账号
        socialLinks:[

            {
                icon: 'github',
                link: 'https://github.com/zhangyongxuan/xuan-ui.git',
            },
        ],
        nav: [
            {
                text: '首页',
                link: '/',
            },
            // {
            //     text: '指南',
            //     link: '/development/',
            // },
            {
                text: '组件',
                link: '/components/',
            }

        ],
        // 侧边栏
        sidebar: {
            '/components/': [
                {
                    text: '开发指南',
                    items: [
                        {
                            text: '快速上手',
                            link: '/components/'
                        }
                    ],

                },
                {
                    text: '组件',
                    items: [
                        {
                            text: '视频字符化组件',
                            link: '/components/video-to-char'
                        }
                    ],
                }
            ],
            '/development/': [

            ]
        },
        lastUpdatedText: 'Updated Date',
        footer: {
            message: '自用组件',
            copyright: 'Copyright © 2019-2022 Xuan-vue-ui'
          }
    },
    /*这里使用vitepress-theme-demoblock插件去处理得到的markdown字符串,将特定语法块包裹的
    内容,按照效果加源码的形式展现出来
     */
    markdown: {
        config: (md) => {
            const {
                demoBlockPlugin
            } = VTD;
            md.use(demoBlockPlugin);
        },
        // lineNumbers:true
    }
}

vitepress中,约定大于配置,

index.md为文档的首页,内容如下:

---
layout: home

hero:
  name: xuan-vue-ui
  text: 一个自用vue组件库
  tagline: 前端的小前端的白
  image:
    src: /logo1.png
    alt: xuan-ui
  actions:
    - theme: brand
      text: 快速使用
      link: /components/
    - theme: alt
      text: Gitee
      link: https://gitee.com/zhangyongxuan/xuan-ui
    - theme: alt
      text: GitHub
      link: https://github.com/zhangyongxuan/xuan-ui.git

features:
  - icon: ⚡️
    title: 多种好玩的组件
    details: 视频字符画、图片字符画、文字粒子化组件等各种有趣的组件
  - icon: 🖖
    title: 开箱即用
    details: 两行代码导入,即可在页面使用
  - icon: 🛠️
    title: 基于Vue3
    details: 基于Vue3拥有强大的定制化配置
---

重点是vitepress-theme-demoblock插件的使用,这个插件将组件库文档中的视图、代码结合的展示形态封装成了组件,只要在Markdown文件中用特定语法包裹内容,在渲染时即可展示为相应的形式。

基础使用方法如下:

image.png

效果如图所示:

image.png

部署

Jenkins部署前端项目