vue二次封装element组件并发布到npm上

1,074 阅读5分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 6 月更文挑战」的第2天, 点击查看活动详情

先看完再操作,先看完再操作!!!

前提:之前公司做的某个项目中需要用到三栏穿梭框(也就是中间是源数据,数据能够在三个穿梭框中穿梭),因为搜查了一下网上都没有适合的组件使用,于是基于elementui中的transfer穿梭框代码弄了一个三栏穿梭框的组件,如下图所示

image.png

考虑到之后可能还会需要用到,如果之后其他项目需要,再去找该项目中复制粘贴就显得有点麻烦和不太方便,所以打算将这个组件发布到npm上,于是参考了一下网上的方法发布到npm上。

1. vue init webpack 项目名称(如果 vue create是没有webpack配置的,因为我参考的博客是有webpack的,所以我选择这样子新建项目)

image.png

2.在与src同级下创建packages文件夹,创建具体的组件并写上注脚信息,详细参考该博客【如果不是基于某个ui框架,全部都是自己写的组件内容,我建议看这个博客】,因为下面都是以三栏穿梭框组件为例,下面transferThree中的结构直接基于elementui框架中的node\_modules\element-ui\packages\transfer来二次开发(所以所谓的index.js脚本我这里是不用写的),如下图

image.png

vue-transfer—three
           |— build // 构建配置
                |— webpack.base.conf.js  // 基础构建配置
                |— webpack.prod.conf.js  // 打包(正式环境)的构建配置
                ...
           |— packages  // 组件内容
                |— transferThree  // 具体的组件(这个组件原始是在node_modules\element-ui\packages\transfer复制过去,再修改里面代码成三栏的)
                   |— src
                       |-main.vue
                       |-transfer-panel.vue
                   |— index.js  // 该组件的组测脚本
           |— src
              |— ...
              |— index.js  // 自定义组件的打包脚本(组件库的入口)
              |— main.js  // 项目的本地运行和构建项目脚本
           |— package.json 
           |— README.md

这里的packages\transferThree\index.js(就是node\_modules\element-ui\packages\transfer 下的)

    import Transfer from './src/main';
    /* istanbul ignore next */
    Transfer.install = function(Vue) {
      Vue.component(Transfer.name, Transfer);
    };
    export default Transfer;

3.创建组件库入口脚本index.js(与src下的main.js平级)

    // index.js (在src下方,与main.js平级)
    import transferThree from '../packages/transferThree/index';
     
    const components = [transferThree]
     
    const install = function(Vue,opts={}) {
        components.forEach(component => {
          Vue.component(component.name, component)
        })
    }
     
    if (typeof window !== 'undefined' && window.Vue) {
        install(window.Vue)
    }
     
    export default {
        install,
        transferThree
    }

如果依赖第三方UI库, 要引入,这里我是基于elementUI的,所以在使用该组件的时候需要引入

    // 如果依赖第三方UI库, 要引入,这里我是基于elementUI的,所以需要引入
    import Vue from 'vue'
    import ElementUI from 'element-ui'
    Vue.use(ElementUI)
    import 'element-ui/lib/theme-chalk/index.css'

4.修改webpack.base.conf.js

export default {
        entry: process.env.NODE_ENV === 'production' ? './src/index.js' : './src/main.js',
        output: {
            path: config.build.assetsRoot,
            filename: 'index.min.js',
            publicPath: process.env.NODE_ENV === 'production'
              ? config.build.assetsPublicPath
              : config.dev.assetsPublicPath,
            library: 'Application', // 指定的就是你使用require时的模块名
            libraryTarget: 'umd',  // 指定输出格式
            umdNamedDefine: true // 会对 UMD 的构建过程中的 AMD 模块进行命名。否则就使用匿名的 define
        }
    }
    

5.修改 webpack.prod.conf.js

// 这里主要修改 plugins中间的配置 主要就保留以下两个插件即可
plugins: {
    // 关于js的压缩插件
    new UglifyJsPlugin({
      uglifyOptions: {
        compress: {
          warnings: false
        }
      },
      sourceMap: false,
      parallel: true
    }),
    // 关于css的压缩
    new ExtractTextPlugin({
      filename: 'index.min.css'
    }),
}

6.修改package.json文件

{
  "name": "@chorkiu/vue-transfer-three",
  "version": "0.0.1",
  "description": "transferThree component",
  "author": "XX <XX@qq.com>",
  "private": false, // 公开的
  "main": "dist/index.min.js", // 打包后文件入口
  "files": ["dist","packages"], // npm发布的文件包含
  "keywords": ["vue","components","element","transfer"],
  // "homepage": "",
  // "bugs": {
  //   "url":""
  // },
  // "repository": {
  //   "type": "git",
  //   "url":""
  // },
}

7.编辑打包,测试插件

// 编译打包
npm run build

// 测试插件
npm pack
// npm pack之后项目根目录会生成一个tgz文件,这里是chorkiu-vue-transfer-three-0.0.1.tgz

//npm pack之后生成的插件
npm install 绝对路径\chorkiu-vue-transfer-three-0.0.1.tgz
//如果用vscode,可以选中tgz文件右击选择复制路径即可)

8.项目引入插件并测试

安装插件之后,查看node_module有该文件

image.png

App.vue测试,因为这里我是基于elementui,并且webpack配置的时候运行入口文件是main.js,所以这里我main.js还需引入elementui的(我查了很多相关的,不知道是哪一步出错,反正如果像他们那样子直接这样写,例如: import transferThree from '@chorkiu/vue-transfer-three' 我会报错,感觉这里我这里的index.min.js没有生效,但之后我看了node_modules,发现我写多几层也能用,所以就先这样解决)

<template>
  <div id="app">
    <transferThree></transferThree>
  </div>
</template>

<script>
    import transferThree from '@chorkiu/vue-transfer-three/packages/transferThree' 
    export default {
      name: 'App',
      components: {
        transferThree
      }
    }
</script>

9.最后打开浏览器测试引入插件是否正常显示我们的插件

噔噔蹬蹬!!!完美呈现了!之后就是上传到到npm的问题了

image.png

10.发布自定义插件到npm

(1)登录npm(如果没有npm账户就先注册一个,login之后需要填username,password等,按着步骤操作即可 )

npm login

(2)发布到npm上(由于起名的时候添加了@name/包名,会默认为私有包,私有包是需付费的,所以如果起名的时候像我那样,那就要加后缀改成公开的)

npm publish  // 正常的只要这样子即可

npm publish --access public // packages.json的name命名格式是@your-name/包名,需要加后缀变公开的

这样就发布成功了!!!

这里面还有一个小小插曲是npm login有问题,报E426上面所说的因为name导致的私有包问题等问题,都卡着卡着解决了!

!!!注意注意:因为我name是@name/包名 ,虽然发布的时候添加--access public发布成功,但是之后我从npm 下载是失败的,反正最后的最后,我的package.json里面的name不再是@name/包名 这种形式,而是直接包名的!!!还有就是package.json中的name和你该项目文件名不能重复,不然你安装npm pack出来的那个.tgz文件是会提示报错的!!!

参考过的原博客:

vue自定义封装组件,并发布到npm上 (完整说明)

下面这两个链接其实解决的是同一个问题,方法几乎一样,只是这两个中都有写错的bug,综合才是正确的解决方法,后续我会归纳一下

npm publish 发布遇到错误 E426、E403

发布npm包时遇到的一些坑