发布自己的vue组件库到npm并实现通过命令行安装使用

273 阅读5分钟

建立了自己常用的组件,并将其推到自己的组件库中,大大提高开发效率。最近看了很多自己创建组件库并推到npm的教程,但是都不怎么适合自己,他们的文章中都没有提及到我遇到的一些坑,可能我们遇到的问题不同,我将我的操作分享一下。

如何编写单个的组件我这里就不介绍了,我直接从单个组件如何打包成组件库开始说说:(仿照着element-ui做的)

1.做一个组件库:假设编写的单个组件是在demo1文件夹,此时我们需要再创建一个vue文件夹,执行命令 vue create demo2 (创建单个组件时的选择了sass等,创建demo2时也需要选择)。

2.在vscode打开demo2 , 在根目录新建文件夹 packages , 用于存放封装的所有组件,并将src文件夹改成了examples(不要疑问为什么,仿照了element) , 用于测试我们封装的组件(如果不用测试可以直接删除src文件夹,下面介绍的是需要测试的情况)。

3.src文件夹改了后,npm run serve 无法启动文件,此时更改入口文件即可,找到vue.config.js文件夹(没有在根目录创建),更改里面的配置,代码如下:

const path= require ('path')

module.exports={
  pages:{
    index:{
      //修改项目的入口文件为examples
      entry:'examples/main.js',
      template:'public/index.html',
      filename:'index.html'
    }
  },
  //扩展webpack 配置,使packges加入编译,最终需要打包的文件packges ,注意chainWebpack 的大小写。
  chainWebpack:config=>{
    config.module
    .rule('js')
    .include.add(path.resolve(__dirname,'packages')).end()
    .use('babel')
    .loader('babel-loader')
    .tap(options=>{
      return options
    })
  },
}

此时执行命令:npm run serve 即可。

4.将自己封装的所有组件复制到packges文件夹中,字体图标(封装租件字体图标时使用方法在文章末尾)也要复制粘贴进来,如图:

~ZZ)FBDJZR4(XUM(}5TLEAS.png

5.在packages文件夹中创建index.js ,这是整个包的入口文件:里面的配置:

//整个包的入口文件

//如果导出一个对象 对象就是install,如果导出函数,函数就是install方法  
//参考vue的官网上Vue.use() 中install的使用
// export default {
//     install
// }

//法二:
import button from './MyButton.vue'
//不要忘记引入字体图标
import './font_3424295_9ml5vax0v5v/iconfont.css'
const components=[
    button
]
const install = function(Vue){
    //全局注册所有的组件
    console.log(123);
    components.forEach(item => {
        Vue.component(item.name,item)
    });
}
//判断是否直接全局引入文件,如果是就不用调用Vue.use(),看官网
if(typeof window !== 'undefined'&& window.Vue){
    install(window.Vue)
}

export default {install}

6.在examples文件中测试: 在main.js中引入自己的插件 ,然后直接使用就可以

//引入自己的插件
import myui from  '../packages/index'
Vue.use(myui)

7.测试没问题对packages打包,vue cli中里面有一个构建目标,构建成一个库,所以在demo2文件的package.json 文件中配置命令 + 打包的文件: "lib":"vue-cli-service build --target lib packages/index.js"

"scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "lib":"vue-cli-service build --target lib packages/index.js"  
  },
  1. 打包之前最好先配置一下(不然后面通过命令安装使用时可能把文件名弄错),为推npm做准备
{
  "name": "bancnmy-ui",
  "version": "0.1.0",
  "private": false,  
  "main": "dist/bancnmy-ui.umd.min.js",
  "author": {
    "name": "半城樱花雨"
  },
  "scripts": {
    "serve": "vue-cli-service serve",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint",
    "lib":"vue-cli-service build --target lib packages/index.js"  
  },
}

"name": "bancnmy-ui",表示npm包的名字,独一无二的,"private": false, ,必须不是私有的,"main": "dist/bancnmy-ui.umd.min.js", npm包的入口文件。

然后执行打包命令:npm run lib ,此时如果有报错:error Mixed spaces and tabs no-mixed-spaces-and-tabs ,那就在 .eslintrc.js 文件夹中的 rules 中,手动添加’no-mixed-spaces-and-tabs’,然后定义为0,关闭规则.

rules: {
    'no-console': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-debugger': process.env.NODE_ENV === 'production' ? 'warn' : 'off',
    'no-mixed-spaces-and-tabs':0
  }

打包完成后生产dist文件:

H{ITYYYWIGVH{V83H@LXFN8.png

9.将使用笔记复制一份在 README.md 文件夹中,

2_1[S(0]`7H%Y%8%OO2XTV4.png

10.可以将自己的代码推到GitHub上去。

11.重点来了,发布到 npm 上去

  • 除了上面必须配置的:"name": "bancnmy-ui",表示npm包的名字,独一无二的,"private": false, ,必须不是私有的,"main": "dist/bancnmy-ui.umd.min.js", npm包的入口文件。以外还可以:"keywords": [ "ui", "组件库" ], "author": "半城樱花雨", 等等;

  • 在根目录创建文件.npmignore ,如同gitignore(里面配置的都是一些忽略的文件),配置:

# 忽略以下东西不被npm上传,所有文件都不要,只要dist文件
examples/
packages/
public/

vue.config.js
babel.config.js
*.map
  • npm上传:

    1.如果使用nrm命令的得保证源是npm的源(这里不讲)。

    2.我是用的 npm (前提必须得有 npm 账号密码) : A.执行命令:npm login 回车 => 输入账号 +回车 => 输入密码(密码是不可见的)+ 回车 => 邮箱 +回车;

    B.执行命令 npm publish (删除已上传的包: npm unpublish  包名  -force  ;如下:npm unpublish chenmy-ui -force)

    注意发包时遇到的坑这个人总结的不错 ,补充一点:

    ① npm unpublish 命令只能删除 72 小时以内发布的包

    ② npm unpublish 删除的包,在 24 小时内不允许重复发布(但是可以换 npm包 的名字继续发,哈哈)

    ③ 发布包的时候要慎重,尽量不要往npm 上发布没有意义的包!

    上传npm包成功:

GM90VTW0MDX0NNNVGCNIHUM.png

如果后期自己又更改完善之前的组件后,要更改版本 packages.json 中 "version": "0.1.0",

12.使用自己发布的包

下载执行命令:npm install bancnmy-ui -s

main.js中全局引入: (注意样式的引入路径,此处容易错

//引入npm包和样式
import myui from 'bancnmy-ui'
import 'bancnmy-ui/dist/bancnmy-ui.css'

Vue.use(myui)

13.这里讲讲字体图标在封装组件时的使用情况:

  • 阿里巴巴矢量图下载字体图标,放到静态文件中:

Y}VPU3LK2`W8R9HES)TP{E5.png

  • 封装组件中:
         <!-- icon 传过来的值是什么就显示该字体图标 -->
         <!-- v-if="icon" 表示有了icon 才会显示图标 -->
    <i class="iconfont" :class="icon" v-if="icon"></i>
  • 使用组件中,这里是关键:icon="icon-shanchu",icon的值是从iconfont.css文件中而来
   <div class="row">
      <!-- icon的值是从iconfont.css 而来  icon="icon-shanchu"-->
    <my-button  circle type='primary' icon="icon-shanchu"></my-button>
    <my-button  circle type='success' icon="icon-duigou"></my-button>
    <my-button  circle type='info'    icon="icon-youjian"></my-button>
    <my-button  circle type='danger'  icon="icon-star"></my-button>
  </div>
  • iconfont.css 文件:
@font-face {
  font-family: "iconfont"; /* Project id 3424295 */
  src: url('iconfont.woff2?t=1653391255245') format('woff2'),
       url('iconfont.woff?t=1653391255245') format('woff'),
       url('iconfont.ttf?t=1653391255245') format('truetype');
}

.iconfont {
  font-family: "iconfont" !important;
  font-size: 16px;
  font-style: normal;
  -webkit-font-smoothing: antialiased;
  -moz-osx-font-smoothing: grayscale;
}

.icon-yanjing:before {
  content: "\e8c7";
}

.icon-cancel-test:before {
  content: "\e61b";
}

.icon-shanchu:before {
  content: "\e8c1";
}

.icon-duigou:before {
  content: "\ebe6";
}

.icon-youjian:before {
  content: "\eb44";
}

.icon-star:before {
  content: "\e60b";
}