[VueCli3]Vue组件如何发布到Npm

工作中经常会遇到很多相同的功能开发,这种情况下大家都会有ctrl+c+v,这样会导致大量冗余的代码,有经验的开发者会把它抽成组件,统一封装,如果其它同事也需要呢,那就可以把组件发布到npm上。

使用VUE-CLI3方式开发组件

第一步:创建项目并编写myToast组件

开始编写一个 toast 组件

myToast.vue

创建一个目录myToast,先编写组件内容,具体代码如下:

<template>
  <transition name="alert-fade">
    <div id="toast"
         v-show="visible"
         class="dialog-tips dialog-center">
      {{message}}
    </div>
  </transition>
</template>
<script>
export default {
  data () {
    return {
      visible: false,
      message: ''
    }
  }
}
</script>
<style lang="scss" scoped>
.alert-fade-enter-active,
.alert-fade-leave-active {
  transition: opacity 0.3s;
}
.alert-fade-enter,
.alert-fade-leave-to {
  opacity: 0;
}
.dialog-tips {
  position: fixed;
  z-index: 100;
  min-width: 100px;
  padding: 15px;
  border-radius: 15px;
  white-space: nowrap;
  background-color: rgba(0,0,0,1);
  box-shadow: 0px 8px 30px 0 rgba(0, 0, 0, 0.363);
  text-align: center;
  color: #fff;
  font-size: 15px
}
.dialog-center {
  top: 20%;
  left: 50%;
  transform: translate(-50%, -50%);
}
</style>

index.js
接着编写组件入口文件index.js

import myToast from './myToast.vue'
const toast = {}
toast.install = Vue => {
    // 扩展 vue 插件
    const ToastCon = Vue.extend(myToast)
    const ins = new ToastCon()
    // 挂载 dom
    ins.$mount(document.createElement('div'))
    // 添加到 body 后面
    document.body.appendChild(ins.$el)
    // 给 vue 原型添加 toast 方法
    Vue.prototype.$toast = (msg, duration = 3000) => {
        // 我们调用的时候 赋值 message
        // 将 visible 设置为 true
        // 默认 3s 之后 设置 为 false 关闭 toast
        ins.message = msg
        ins.visible = true
        setTimeout(() => {
            ins.visible = false
        }, duration)
    }
}
export default toast

在该组件中,需要先引入之前的组件文件,并编写插件需要的install方法,在方法中添加$toast方法到vue实例对象上,这样在所有vue实例中都可以调用了。

组件引入

import Vue from 'vue'
import App from './App.vue'
import router from './router'
import toast from './components/myToast'
Vue.use(toast)

Vue.config.productionTip = false

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

组件使用
打开views/Home.vue文件,引入全局组件

<template>
  <div class="home">
    <img alt="Vue logo" src="../assets/logo.png">
    <button v-on:click="greet">Greet</button>
    <HelloWorld msg="Welcome to Your Vue.js App"/>
  </div>
</template>

<script>
// @ is an alias to /src
import HelloWorld from '@/components/HelloWorld.vue'

export default {
  name: 'Home',
  components: {
    HelloWorld
  },
  methods: {
    greet(){
        this.$toast('my toast test!')
    }
  }
}
</script>

效果如下:


image-20210512105824539.png

第二步:重构项目 for component build

创建一个项目,之后将 src 目录改成 examples 这样会导致项目跑不起来,为啥是因为 vue-cli3 内置配置了自动回去找 src 文件夹,然后再新建一个 packages 文件夹,这样就把目录准备好了,如图所示


v2-2557bc4cf47b1b74496f07ff1763de5b_720w.png

下面解决项目跑不起来的问题,主要在 vue.config.js 配置项目的入口文件

const path = require('path')
function resolve(dir) {
  return path.join(__dirname, dir)
}
module.exports = {
  // 修改 src 为 examples
  pages: {
    index: {
      entry: "examples/main.js",
      template: "public/index.html",
      filename: "index.html"
    }
  },
  // 组件样式内联
  css: {
    extract: false
  },
  // 扩展 webpack 配置,使 packages 加入编译
  chainWebpack: config => {
    config.resolve.alias
      .set('@', resolve('examples'))
      .set('~', resolve('packages'))
    config.module
      .rule('eslint')
      .exclude.add(path.resolve('lib'))
      .end()
      .exclude.add(path.resolve('examples/docs'))
      .end()
      
    config.module
      .rule('js')
      .include
      .add('/packages/')
      .end()
      .include.add(/examples/)
      .end()
      .use('babel')
      .loader('babel-loader')
      .tap(options => {
        // 修改它的选项...
        return options
      })
  }
};

注意:这里可以不用把src改名,上面的配置也只需要css内联处理,如下:

// 组件样式内联
  css: {
    extract: false
  }

第三步:配置 package.json

主要是配置包导出入口 main,还有打包成 lib

{
  "name": "big-bear-toast",
  "version": "0.1.0",
  "main": "packages/myToast/index.js",
  "scripts": {
    "lib": "vue-cli-service build --target lib --name toast --dest lib packages/myToast/index.js",
    "serve": "vue-cli-service serve --hot",
    "build": "vue-cli-service build",
    "lint": "vue-cli-service lint"
  },
  "dependencies": {
    "core-js": "^3.6.5",
    "vue": "^2.6.11",
    "vue-router": "^3.2.0"
  },
  "devDependencies": {
    "@vue/cli-plugin-babel": "~4.5.0",
    "@vue/cli-plugin-router": "~4.5.0",
    "@vue/cli-service": "~4.5.0",
    "node-sass": "^6.0.0",
    "sass-loader": "^10.2.0",
    "vue-template-compiler": "^2.6.11"
  }
}

vue-cli-service build

Usage: vue-cli-service build [options] [entry|pattern]

Options:

--mode 指定环境模式 (default: production)

--dest 指定输出目录 (default: dist)

--modern 构建两个版本的 js 包:一个面向支持现代浏览器的原生 ES2015+ 包,以及一个针对其他旧浏览器的包。

--target 允许您以项目库或Web组件的形式在项目内部构建任何组件 app | lib | wc | wc-async (default: app) ???

--name lib或者web组件库的名称 (default: "name" in package.json or entry filename)

--no-clean 在构建项目之前不要删除输出目录(dist)

--report 生成report.html以帮助分析包内容

--report-json 生成report.json来帮助分析包内容

--watch 监听 - 当有改变时 自动重新打包~

第四步:在根目录创建packages

在根目录创建packages并把myToast移动到这里,然后把main.js中路径改下,如下

image-20210512110547045.png

执行打包生成lib

npm run lib

接着把生成的包引入到main.js中,如下
image-20210512113558054.png

第五步:注册npm账号

首先要登录npm官网进行注册

https://www.npmjs.com/signup

按照上边的要求输入的全名、用户名、邮箱、密码进行注册

输入完成后点击下边的注册就可以创建自己的npm账号成功

值得注意的地方是,如果你的 npm 镜像是 淘宝镜像或者其他的镜像,此时应该切换会 npm

npm install -g cnpm --registry=https://registry.npm.taobao.org

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

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

第六步:npm 登录及发布

输入命令npm login如下:

image-20210512111507028.png

组件发布,在项目根目录执行

npm publish

项目中 package.json 配置了 private: true要改为false或者删除该项目.

image-20210512120007192.png

发布成功!

组件测试

安装发布的组件

注意:要新建一个工程,不能在原发布工程中install

npm i big-bear-toast

image-20210512122206126.png

第七步:完善插件说明文档

主要是修改README.md,大概内容如下:

image.png

常见问题收集

接下来就是遇到的问题了,每个问题都包含报错信息,请善用ctrl + f搜索,下文报错中涉及到自己包名的我都替换为了your-package

邮箱未验证

npm ERR! publish Failed PUT 403 npm ERR! code E403 npm ERR! you must verify your email before publishing a new package: https://www.npmjs.com/email-edit : your-package

这个是注册后没有验证邮箱,登录自己邮箱找到对应的邮件确认就好了。注意别选错了,注册 npm 时会发给你两个邮件,我当时就是眼瞎没有看到第二个。如果验证邮件过期的话登录自己的 npm 主页重新发一个就好了。

没有权限发布

npm ERR! publish Failed PUT 403 npm ERR! code E403 npm ERR! You do not have permission to publish "your-package". Are you logged in as the correct user? : your-package

你的包和别人的包重名了,npm 里的包不允许重名,所以去 npm 搜一下,改个没人用的名字就可以了。

需要登录

npm ERR! code ENEEDAUTH npm ERR! need auth auth required for publishing npm ERR! need auth You need to authorize this machine using npm adduser

后面已经注明了,输入npm adduser重新登录就可以了,过程和npm login一样,这个问题在你切换了 npm 源之后或登录过期后都有可能发生。

只有管理员才有权限发布

npm ERR! publish Failed PUT 403 npm ERR! code E403 npm ERR! [no_perms] Private mode enable, only admin can publish this module [no_perms] Private mode enable, only admin can publish this module: your-package

这个是你的源设置成第三方源的时候才有可能发生,比如设置了淘宝源就可能会导致该问题。只要把源改回默认的就可以了,如下:

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

包名过于类似

npm ERR! publish Failed PUT 403 npm ERR! code E403 npm ERR! Package name too similar to existing packages; try renaming your package to '@hopgoldy/auto-git' and publishing with 'npm publish --access=public' instead : your-package

如果npm上已经有了不少和你的包名类似的包,就会出现这个问题,在package.json中修改你的包名就可以了

无法发布到私有包

npm ERR! publish Failed PUT 402 npm ERR! code E402 npm ERR! You must sign up for private packages :

这个当你的包名为@your-name/your-package时才会出现,原因是当包名以@your-name开头时,npm publish会默认发布为私有包,但是 npm 的私有包需要付费,所以需要添加如下参数进行发布:

npm publish --access public

参考: https://zhuanlan.zhihu.com/p/93027809

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,529评论 5 475
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,015评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,409评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,385评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,387评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,466评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,880评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,528评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,727评论 1 295
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,528评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,602评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,302评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,873评论 3 306
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,890评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,132评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,777评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,310评论 2 342

推荐阅读更多精彩内容