Skip to content

封装发布一款Vue组件的正确姿势

引言

之前在开发维护一些开源库改造的项目时接触到了许多封装好的的Vue组件库,觉得工程结构清晰明了,也比较实用,特此记录下来,接下来会从0开始构建一个Vue组件并发布到NPM仓库(官方库或者私仓都行)

步骤

1、创建初始化Vue Cli项目

Vue Cli官方文档

详细步骤:自定义创建/选择Vue2版本/添加Scss/Sass预编译语言

2、修改工程目录

  • src目录修改为example目录,在组件开发阶段用来调试

  • 添加packages目录用来存放组件库源代码,并且packages目录下要存在一个统一入口文件index.js用来实现Vueinstall方法

  • 项目根目录下添加README.md文件,作为工程的文档与说明(一般创建项目自带)

3、添加配置文件

工程根目录下添加vue.config.js,并配置一些必备的打包配置:

配置参考官方文档

vue.config.js

js

module.exports = {
    // es-lint
    lintOnSave: false,
    // 项目部署资源目录
    publicPath: "./",
    // 修改 src 目录 为 examples 目录
    pages: {
        index: {
            entry: 'example/main.js',
            template: 'public/index.html',
            filename: 'index.html',
            chunks: ['chunk-vendors', 'chunk-common', 'index'],
        }
    },
    // 关闭productSourceMap 加速生产打包速度
    productionSourceMap: false,
    // 强制内联CSS
    css: { extract: true },
    // 扩展 webpack 配置
    chainWebpack: config => {
        // 生产环境则关闭控制台打印信息,避免影响到项目本身
        if (process.env.NODE_ENV === "production") {
            config.optimization.minimizer("terser").tap((arg) => {
                arg[0].terserOptions.compress.drop_console = true;
                return arg;
            });
        }

        // babel babel-polyfill相关配置
        config.module
            .rule('js')
            .include
            .add('/packages')
            .end()

            .use('babel')
            .loader('babel-loader')
            .tap(options => {
                // 修改它的选项...
                return options
            })

        config.entry.app = ['babel-polyfill', './example/main.js'];

    }
}

4、创建组件并添加统一的安装方法

添加测试组件 packages\map-plugin\index.vue

vue
<template>
    <h2>map-plugin</h2>
</template>

<script>
export default{
    name: "map-model-plugin"
}
</script>

添加组件统一安装入口,实现Vueinstall(组件注册方法)packages\index.js

js
import components from "./map-plugin/index"

// 定义 install 方法,接收 Vue 作为参数。如果使用 use 注册插件,则组件将被注册
const install = function (Vue) {
    // 判断是否安装
    if (install.installed) return
    // 注册全局组件
    components.map(component => Vue.component(component.name, component))
}

// 判断是否是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
    install(window.Vue)
}

export default {
    // 导出的对象必须具有 install,才能被 Vue.use() 方法安装
    install,
    // 以下是具体的组件列表
    ...components
}

packages\map-plugin\index.js

js
import MapPlugin from "./index.vue"

MapPlugin.install = function(Vue){
    Vue.component(MapPlugin.name,MapPlugin)
}

export default [ MapPlugin ]

5、配置package.json

详细配置官方文档

这一步也比较关键,package.jsonpackage.json 文件其实就是对项目或者模块包的描述,里面包含许多元信息。

package.json

json
{
  "name": "map-model-plugin",
  "version": "0.1.1",
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lib": "vue-cli-service build --target lib --name map-model-plugin --dest lib packages/index.js",
    "pub": "npm version patch && npm publish --registry=https://dev.tyky.com.cn:9444/repository/npm-hosted/"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "sass": "^1.26.5",
    "sass-loader": "^8.0.2",
    "three": "0.151.0",
    "vue-template-compiler": "^2.6.11"
  },
  "private": false,
  "description": "大厅3D地图展示插件",
  "main": "lib/map-model-plugin.umd.min.js",
  "directories": {
    "lib": "lib"
  },
  "files": [
    "lib"
  ],
  "author": "zhaochao",
  "license": "MIT",
  "keywords": [
    "three-js",
    "3D",
    "Vue"
  ]
}

关键点:

  • 1、添加组件打包命令lib并指定组件打包的名称、入口等信息

  • 2、添加pub组件发布命令,支持一键发布到npm私仓或者官方仓库,楼主这里指定的是公司仓库

  • 3、private修改为true,私有仓库发布会失败

  • 4、指定main入口,即当你执行npm publish的时候,发布到npm仓库后,用户通过npm install 组件名下载到的文件,即是main指定的入口,一般是前面提到的组件统一入口index.js打包后的入口

其他常用属性详解:

  • description:该组件的描述介绍信息
  • files:该组件发布后,用户可以在npm仓库组件下看到的源代码目录
  • author:作者信息
  • license: 开源协议
  • keywords:关键字,便于检索
  • repository:仓库信息
  • bugsbug反馈地址
  • homepage:官网首页

6、修改示例工程

接下来修改一下示例工程,便于开发调试 example\app.vue

vue
<template>
  <div id="app">
    <map-model-plugin/>
  </div>
</template>

<script>

export default {
  name: 'App',
  components: {
  }
}
</script>

<style lang="scss">
body,*{
  padding: 0;
  margin: 0;
}
</style>

example\main.js

js
import Vue from 'vue'
import App from './App.vue'

import MapModelPlugin from "../packages/index"

Vue.config.productionTip = false

// 使用组件
Vue.use(MapModelPlugin)

new Vue({
  render: h => h(App),
}).$mount('#app')

到这该示例组件已经搭建完成,此时的工程目录结构如下:

│  .browserslistrc
│  .gitignore
│  babel.config.js
│  list.txt
│  package.json
│  README.md
│  vue.config.js
│  yarn.lock

├─example
│  │  App.vue
│  │  main.js
│  │  
│  ├─assets
│  │      logo.png
│  │      
│  └─components
│          HelloWorld.vue

├─lib
│      demo.html
│      map-model-plugin.common.js
│      map-model-plugin.umd.js
│      map-model-plugin.umd.min.js

├─packages
│  │  index.js
│  │  
│  └─map-plugin
│          index.js
│          index.vue

└─public
        favicon.ico
        index.html

总结

  • 本地调试时我们只需要执行yarn serve

  • 需要打包发布到npm仓库时我们需要执行:npm run lib 然后 npm run pub

以上即是整个封装发布一款Vue组件的流程

上次更新于: