Vue3+Ts+Vite开发插件并发布到npm

news/2024/7/10 0:40:19 标签: npm, typescript, vue

依赖版本信息如下:

"vue": "^3.2.45"

"typescript": "~4.7.4"

"vite": "^4.0.0"

"less": "^4.1.3"

"terser": "^5.16.4"

npm: 8.1.0

node: 16.13.0

目标:创建 vue-amazing-ui 组件库,并发布到npm,效果如下图:

目前拥有的组件(面包屑和分页器):

①创建vue3+ts+vite项目:

npm init vue@latest(输入项目名称,并依次选择需要安装的依赖项)

②项目目录结构截图如下:

③在项目根目录新建 packages/ 文件夹用于存放组件 

④在项目根目录中的 vite.config.ts 中写入相关配置项:

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

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

// https://vitejs.dev/config/
export default defineConfig({
  plugins: [vue()],
  resolve: {
    alias: {
      '@': fileURLToPath(new URL('./src', import.meta.url))
    }
  },
  css: {
    preprocessorOptions: {
      less: {
        modifyVars: { // 或者globalVars
          // `themeColor` is global variables fields name
          themeColor: '#1890FF'
        },
        javascriptEnabled: true
      },
    },
  },
  // 配置打包入口
  build: {
    lib: { // 构建为库。如果指定了 build.lib,build.cssCodeSplit 会默认为 false。
      // __dirname的值是vite.config.ts文件所在目录
      entry: resolve(__dirname, 'packages/index.ts'),  // entry是必需的,因为库不能使用HTML作为入口。
      name: 'VueAmazingUI', // 暴露的全局变量
      fileName: 'vue-amazing-ui' // 输出的包文件名,默认是package.json的name选项
    },
    rollupOptions: { // 自定义底层的Rollup打包配置
      // https://rollupjs.org/configuration-options/
      // 确保外部化处理那些你不想打包进库的依赖
      external: ['vue'],
      output: {
        exports: 'named',
        // 在 UMD 构建模式下为这些外部化的依赖提供一个全局变量
        globals: {
          vue: 'Vue'
        }
      }
    },
    /** 设置为 false 可以禁用最小化混淆,或是用来指定使用哪种混淆器。
        默认为 Esbuild,它比 terser 快 20-40 倍,压缩率只差 1%-2%。
        注意,在 lib 模式下使用 'es' 时,build.minify 选项不会缩减空格,因为会移除掉 pure 标注,导致破坏 tree-shaking。
        当设置为 'terser' 时必须先安装 Terser。(yarn add terser -D)
    */
    minify: 'terser', // Vite 2.6.x 以上需要配置 minify: "terser", terserOptions 才能生效
    terserOptions: { // 在打包代码时移除 console.log、debugger 和 注释
      compress: { 
        drop_console: false,
        drop_debugger: true,
        pure_funcs: ['console.log']
      },
      format: {
        comments: false // 删除注释
      }
    }
  }
})

⑤在 packages/ 文件夹下创建UI组件,例如:新建 breadcrumb/ 和 pagination/ 文件夹,截图如下:

⑥在 breadcrumb/ 文件夹下新建 Breadcrumb.vue 组件文件和 index.ts 文件,截图如下: 

 ⑦在Breadcrumb.vue 中编写组件代码:

<script lang="ts">
export default { // 导出组件name
  name: 'Breadcrumb'
}
</script>
<script setup lang="ts">
import { computed } from 'vue'
import { useRouter } from 'vue-router'
export interface Props {
  routes: object[], // router的路由数组,没有 ? 时,即表示 required: true
  height?: number, // 面包屑高度
  separator?: string // 自定义分隔符
}
interface Route {
  path: string,
  query: object,
  name: string
}
const props = withDefaults(defineProps<Props>(), {
  routes: () => [],
  height: 60,
  separator: ''
})

const len = computed(() => {
  return props.routes.length
})

const router = useRouter()
function goRouter (route: Route):void {
  // @ts-ignore (忽略下一行中产生的错误)
  router.push({ path: route.path, query: route.query || {} })
}
</script>
<template>
  <div class="m-breadcrumb" :style="`height: ${height}px;`">
    <div class="m-bread" v-for="(route, index) in routes" :key="index">
      <a
        :class="['u-route',{ active: index===len-1 }]"
        @click="index === len - 1 ? ($event:any) => $event.preventDefault() : goRouter(route)"
        :title="route.name">
        {{ route.name || '--' }}
      </a>
      <template v-if="index !== len - 1">
        <span v-if="separator" class="u-separator">{{ separator }}</span>
        <svg v-else class="u-arrow" viewBox="64 64 896 896" data-icon="right" aria-hidden="true" focusable="false"><path d="M765.7 486.8L314.9 134.7A7.97 7.97 0 0 0 302 141v77.3c0 4.9 2.3 9.6 6.1 12.6l360 281.1-360 281.1c-3.9 3-6.1 7.7-6.1 12.6V883c0 6.7 7.7 10.4 12.9 6.3l450.8-352.1a31.96 31.96 0 0 0 0-50.4z"></path></svg>
      </template>
    </div>
    <div class="assist"></div>
  </div>
</template>
<style lang="less" scoped>
.m-breadcrumb {
  .m-bread {
    display: inline-block;
    vertical-align: middle;
    .u-route {
      height: 22px;
      font-size: 16px;
      font-weight: 400;
      line-height: 22px;
      color: #333;
      display: inline-block;
      vertical-align: middle;
      max-width: 240px;
      overflow: hidden;
      white-space: nowrap;
      text-overflow: ellipsis;
      cursor: pointer;
      &:hover {
        color: @themeColor;
      }
    }
    .active {
      color: @themeColor;
      cursor: default;
    }
    .u-separator {
      display: inline-block;
      vertical-align: middle;
      margin: 0 6px;
    }
    .u-arrow {
      .u-separator();
      margin: 0 5px;
      width: 12px;
      height: 12px;
    }
  }
  .assist {
    height: 100%;
    width: 0;
    display: inline-block;
    vertical-align: middle;
  }
}
</style>

⑧在 breadcrumb/index.ts 中导出组件

import type { App } from 'vue'
import Breadcrumb from './Breadcrumb.vue'

// 使用install方法,在app.use挂载
Breadcrumb.install = (app: App) => {
  app.component(Breadcrumb.name, Breadcrumb)
}

export default Breadcrumb

⑨在 packages/index.ts 文件中对整个组件库进行导出:

import type { App } from 'vue'
import Pagination from './pagination'
import Breadcrumb from './breadcrumb'

// 所有组件列表
const components = [
  Pagination,
  Breadcrumb
]

// 定义 install 方法
const install = (app: App): void => {
  // 遍历注册所有组件
  components.forEach(component => app.component(component.name, component))
}

const VueAmazingUI = {
  install
}

export { // 方便按需导入
  Pagination,
  Breadcrumb
}

export default VueAmazingUI

⑩在 src/main.ts 中导入刚创建的组件,检测是否正常可用

import { Pagination, Breadcrumb } from '../packages/index'
// import { Pagination, Breadcrumb } from '../dist/vue-amazing-ui.js'
// import '../dist/style.css'
const app = createApp(App)
app.use(Pagination).use(Breadcrumb)

app.mount('#app')

⑪在终端执行 npm init 初始化包,选填并配置package.json:

{
  "name": "vue-amazing-ui",
  "version": "0.0.0",
  "private": false,
  "type": "module",
  "files": [
    "dist"
  ],
  "main": "./dist/vue-amazing-ui.umd.cjs",
  "module": "./dist/vue-amazing-ui.js",
  "exports": {
    ".": {
      "import": "./dist/vue-amazing-ui.js",
      "require": "./dist/vue-amazing-ui.umd.cjs"
    }
  },
  "scripts": {
    "dev": "vite --port 9000 --open --force",
    "build": "run-p type-check build-only",
    "preview": "vite preview",
    "build-only": "vite build --watch",
    "type-check": "vue-tsc --noEmit",
    "lint": "eslint . --ext .vue,.js,.jsx,.cjs,.mjs,.ts,.tsx,.cts,.mts --fix --ignore-path .gitignore"
  },
  "dependencies": {
    "vue": "^3.2.45"
  },
  "devDependencies": {
    "@rushstack/eslint-patch": "^1.1.4",
    "@types/node": "^18.11.12",
    "@vitejs/plugin-vue": "^4.0.0",
    "@vue/eslint-config-typescript": "^11.0.0",
    "@vue/tsconfig": "^0.1.3",
    "eslint": "^8.22.0",
    "eslint-plugin-vue": "^9.3.0",
    "less": "^4.1.3",
    "npm-run-all": "^4.1.5",
    "terser": "^5.16.4",
    "typescript": "~4.7.4",
    "vite": "^4.0.0",
    "vue-tsc": "^1.0.12"
  },
  "description": "This template should help get you started developing with Vue 3 in Vite.",
  "repository": {
    "type": "git",
    "url": "git+https://github.com/themusecatcher/vue-amazing-ui.git"
  },
  "keywords": [
    "Vue3",
    "TS",
    "Vite",
    "UI",
    "components"
  ],
  "author": "theMuseCatcher",
  "license": "ISC",
  "bugs": {
    "url": "https://github.com/themusecatcher/vue-amazing-ui/issues"
  },
  "homepage": "https://github.com/themusecatcher/vue-amazing-ui#readme"
}

name: 包名,该名字是唯一的。可在 npm 官网搜索名字,不可重复。

version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同

private:是否私有,需要修改为 false 才能发布到 npm

description: 关于包的描述。

main: 入口文件,需指向最终编译后的包文件。

keywords:关键字,以空格分离希望用户最终搜索的词。

author:作者

license: 开源协议

type: module:如果 package.json 不包含 "type": "module",Vite 会生成不同的文件后缀名以兼容 Node.js。.js 会变为 .mjs 而 .cjs 会变为 .js

files: ["dist/*"]:检测dist打包目录的所有文件

vite build --watch:当启用 --watch 标志时(启用 rollup 的监听器),对 vite.config.ts 的改动,以及任何要打包的文件,都将触发重新构建

vite --port 9000 --open --force:指定端口9000,启动时打开浏览器,强制优化器忽略缓存并重新构建。

⑫执行编译命令

yarn build(或num run build)

执行结果如下图:

 ⑬在项目根目录创建 .npmignore 文件,设置忽略发布的文件,类似 .gitignore 文件

只有编译后的 dist 目录、package.json、README.md是需要被发布的
# 忽略目录
.DS_Store
.vscode/
node_modules
packages/
public/
src/

# 忽略指定文件
.eslintrc.cjs
.gitignore
.nomignore
.env.d.ts
index.html
tsconfig.config.json
tsconfig.json
vite.config.ts
yarn.lock

⑭编写README.md文件(使用markdown格式)

参考文档: http://markdown.p2hp.com/index.html
# vue-amazing-ui

## 安装插件

```
npm install vue-amazing-ui
或:yarn add vue-amazing-ui
```

## 引入并注册插件

```
import VueAmazingUI from 'vue-amazing-ui'
import '../node_modules/vue-amazing-ui/dist/style.css'

app.use(VueUi)

// 或者
import { Pagination, Breadcrumb } from 'vue-amazing-ui'
import '../node_modules/vue-amazing-ui/dist/style.css'

app.use(Pagination).use(Breadcrumb)
```

## 在项目中使用(示例)

```
<Breadcrumb :routes="routes" :height="60" />
```

⑮登录npm

如果没有npm账号,可以去npm官网( npm) 注册一个账号

注册成功后在本地查看npm镜像:

npm config get registry

输出:http://registry.npmjs.org 即可

如果不是则需要设置为npm镜像:

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

然后在终端执行:

npm login

依次输入用户名,密码,邮箱

输出Logged in as…即可

npm whoami // 查看当前用户是否已登录

⑯发布组件到npm

在终端执行:npm publish

发布成功后即可在npm官网搜索到该组件,如下图;并可以通过 npm install vue-amazing-ui(或yarn add vue-amazing-ui)进行安装

 ⑰在要使用的项目中安装并注册插件:

yarn add vue-amazing-ui

然后在 main.ts 文件中引入并注册:

import VueAmazingUI from 'vue-amazing-ui'
// 或者 import { Pagination, Breadcrumb } from 'vue-amazing-ui'
import '../node_modules/vue-amazing-ui/dist/style.css'

app.use(VueAmazingUI)

在要使用组件的页面直接使用即可:

<Breadcrumb :routes="routes" :height="60" />

http://www.niftyadmin.cn/n/87995.html

相关文章

Android Studio的笔记--socket通信

Android socket通信Socket协议android socket 代码清单文件开启服务服务端&#xff1a;TCPServerService客户端&#xff1a;TCPClientServicelogSocket Socket 作为一种通用的技术规范&#xff0c;首次是由 Berkeley 大学在 1983 为 4.2BSD Unix 提供的&#xff0c;后来逐渐演化…

MES助力灯具照明行业从制造到”智造”

现如今&#xff0c;LED照明行业产品更新换代太快&#xff0c;一个产品一两年不更新一下外观、材料&#xff0c;就会被对手超越。这直接导致LED产品标准化程度不够高&#xff0c;LED下游制造类厂家智能化生产程度普遍偏低。 加之大多属于劳动密集型产业&#xff0c;传统的依靠买…

[MySQL]基本数据类型及表的基本操作

哈喽&#xff0c;大家好&#xff01;我是保护小周ღ&#xff0c;本期为大家带来的是 MySQL 数据库常用的数据类型&#xff0c;数据表的基本操作&#xff1a;创建、删除、修改表&#xff0c;针对修改表的结构进行了讲解&#xff0c;随后是如何向数据表中添加数据&#xff0c;浅浅…

华为OD机试真题Python实现【 磁盘容量】真题+解题思路+代码(20222023)

磁盘容量 题目 磁盘的容量单位常用的有M、G、T 他们之间的换算关系为1T =1024G,1G=1024M 现在给定n块磁盘的容量,请对他们按从小到大的顺序进行稳定排序 例如给定5块盘的容量 5 1T 20M 3G 10G6T 3M12G9M 排序后的结果为 20M 3G 3M12G9M 1T 10G6T 注意单位可以重复出现 上述…

活动预告 | GAIDC 全球人工智能开发者先锋大会

大会主题——“向光而行的 AI 开发者” 2023 全球人工智能开发者先锋大会&#xff08;GAIDC&#xff09; 由世界人工智能大会组委会、上海市经济和信息化委员会、上海市人才工作领导小组办公室及中国&#xff08;上海&#xff09;自由贸易试验区临港新片区管理委员会指导&…

Linux 环境变量

Linux 环境变量能帮你提升 Linux shell 体验。很多程序和脚本都通过环境变量来获取系统信息、存储临时数据和配置信息。在 Linux 系统上有很多地方可以设置环境变量&#xff0c;了解去哪里设置相应的环境变量很重要。 认识环境变量 bash shell 用环境变量&#xff08;environme…

nodejs基于vue论坛交流管理系统

可定制框架:ssm/Springboot/vue/python/PHP/小程序/安卓均可开发目录 目录 1 绪论 1 1.1课题背景 1 1.2课题研究现状 1 1.3初步设计方法与实施方案 2 1.4本文研究内容 2 2 系统开发环境 4 3 系统分析 6 3.1系统可行性分析 6 3.1.1经济可行性 6 3.1.2技术可行性 6 3.1.3运行可行…

一起学习用Verilog在FPGA上实现CNN----(八)integrationFC设计

1 integrationFC设计 LeNet-5网络结构全连接部分如图所示&#xff0c;该部分有2个全连接层&#xff0c;1个TanH激活层&#xff0c;1个SoftMax激活层&#xff1a; 图片来自附带的技术文档《Hardware Documentation》 integrationFC部分原理图&#xff0c;如图所示&#xff0c;…