如何用vue-cli 3.0 打包一个组件并发布到NPM站点

用VUE有一段时间了,但还从来没用过类似iview或者或者elementUI这样的库,一方面样式与公司的不相符,一方面公司的页面相对简单。
最主要的还是自己写组件的话可以更好的理解和学习VUE,在公司写的组件也不少了,就想着能不能自己也把这些组件发布出来,方便自己以后使用。
琢磨了半天,总算发布出去了,这里记录一下发布的过程,怕以后又忘了。

1.安装nodeJS

下载nodeJS安装包并按照提示安装,安装之后输入一下命令检查是否安装正确。

1
2
node -v
v10.16.4

2.安装vue-cli 3.0,安装之后可以输入vue –version来检查是否安装正确。

1
2
3
npm install -g @vue/cli
vue --version
3.4.1

3.利用vue create 初始化一个项目.

花的时间有点长,耐心等待,要是不想用命令行也可以用UI的方式,vue-cli 3.0居然提供了UI的方式。详情请戳这里

1
vue create hello-word

为了简单方便,命令行使用默认方式安装

安装完成之后运行

1
npm run serve

运行结束之后会看到如下的输出,这个时候就可以通过localhost:8080来访问这个项目了

项目初始化的目录结构如下,没错没有webpack.config.js,因为在vue-cli 3.0里面通过vue.config.js文件来设置webpack的相关配置,后面会讲到。

到此为止准备工作就算结束了。

4.开始构建自己的组件代码

按照惯例(我也不知道为啥大家都要这么做),添加packages目录存放自己的组件代码,修改src目录为examples表明这个目录是用来演示组件是如何使用的,
因为我们要打包的仅仅是组件而已。
修改src目录前记得先停掉npm serve,不然文件占用无法修改。
在packages目录下添加自己的组件目录my-first-components.
在my-first-conponents目录下新建src目录,并在src目录下新建my-first-components.vue文件。
回到src目录,新建index.js文件用于export这个组件
回到packages目录下,新建index.js文件,这个文件负责export所有的组件,因为我们还可以将多个组件一起打包出来
还有重要的一点,我们修改的默认的入口文件目录从src变成了examples,所以需要新建vue.config.js文件来制定新的入口,内容如下

1
2
3
4
5
6
7
8
9
10
module.exports = {
// 修改 src 为 examples
pages: {
index: {
entry: 'examples/main.js',
template: 'public/index.html',
filename: 'index.html'
}
}
}

到此为止,文件准备工作结束,完整结构如下:

5.my-first-components.vue文件内容

这里我们只是写一个最基本的组件,只是输出传入的内容。

1
2
3
4
5
6
7
8
9
10
11
12
13
<template>
<div>
{{msg}}
</div>
</template>
<script>
export default{
name:"myFirstComponents",
props:{
msg:String
}
};
</script>

6.my-first-components目录下index.js的内容

目的是export这个组件给其他地方引用

1
2
3
4
5
import myFirstComponents from './src/my-first-components.vue'
myFirstComponents.install = function (Vue) {
Vue.component(myFirstComponents.name, myFirstComponents);
};
export default myFirstComponents

7.packages 目录下index.js的内容

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
// 导入所有组件
import myFirstComponents from './my-first-components/index.js'

const components = [myFirstComponents]
const install = function(vue) {
/* istanbul ignore if */
if (install.installed) return;
/*eslint-disable*/
components.map((component) => {
vue.component(component.name, component); //component.name 此处使用到组件vue文件中的 name 属性
});
};
/* istanbul ignore if */
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue);
};

export {
install,
myFirstComponents
}

8.在app.vue中引用这个组件.

我们注释掉之前的HelloWord组件,这样UI的输出更清晰然后引入自己的组件,传入自己的字符

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
<template>
<div id="app">
<img alt="Vue logo" src="./assets/logo.png">
<!-- <HelloWorld msg="Welcome to Your Vue.js App"/>-->
<myFirstComponents msg="============================="></myFirstComponents>
</div>
</template>

<script>
import HelloWorld from './components/HelloWorld.vue'
import {myFirstComponents} from './../packages/index'

export default {
name: 'app',
components: {
HelloWorld,
myFirstComponents
}
}
</script>

<style>
#app {
font-family: 'Avenir', Helvetica, Arial, sans-serif;
-webkit-font-smoothing: antialiased;
-moz-osx-font-smoothing: grayscale;
text-align: center;
color: #2c3e50;
margin-top: 60px;
}
</style>

UI上就能看到组件生效了

9.开始打包,添加lib命令

在package.json中添加如下脚本

1
2
3
"script": {
"lib": "vue-cli-service build --target lib --name myFirstComponents --dest lib packages/index.js"
}

然后执行命令:

1
npm run lib

build之后的结果如下

10.修改package.json准备上传到NPM server

  • name: 包名,该名字是唯一的。可在 npm 官网搜索名字,如果存在则需换个名字。
  • version: 版本号,每次发布至 npm 需要修改版本号,不能和历史版本号相同。
  • description: 描述。
  • main: 入口文件,该字段需指向我们最终编译后的包文件。
  • keyword:关键字,以空格分离希望用户最终搜索的词。
  • author:作者
  • private:是否私有,需要修改为 false 才能发布到 npm
  • license: 开源协议
    这里我们添加的内容如下:
    1
    2
    3
    4
    5
    6
    "name": "my-first-components",
    "version": "0.1.0",
    "private": false,
    "description": "first vue componets test",
    "main": "lib/myFirstComponents.umd.js",
    "keyword": "",

11.修改.npmignore 文件,就不需要发布的文件过滤掉

添加以下目录文件

1
2
3
4
5
examples/
packages/
public/
babel.config.js
vue.config.js

12.本地测试npm包

package.json文件修改完毕之后可以在本地执行命令npm pack,会在项目根目录生成一个my-first-components-0.1.0.tgz的压缩包
然后在另外一个项目里面安装这个包

1
npm install d:\xxx\xxx\my-first-components-0.1.0.tgz

然后在App.vue里面引用这个组件,如果显示正常就说明打包没有问题

1
2
3
4
5
6
7
8
9
import {myFirstComponents} from 'my-first-components'

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

13.发布到NPM server

首先需要去NPM上注册一个账号,如果已有账号请忽略。
然后在组件目录下登录

1
npm login

输入用户名密码,然后执行

1
npm publish

就可以发布成功,我发布的时候遇到两个问题,第一个错误是npm ERR! 400 Bad Request - PUT https://registry.npmjs.org/myFirstComponents - “myFirstComponents” is invalid for new packages
因为开始的时候我在package.json里面写的name是myFirstComponents,看来npm name不支持这种驼峰的写法,后来换成了”name”: “my-first-components”之后就可以了。
第二个错误是npm ERR! publish Failed PUT 403 You do not have permission to publish “npmtest”. Are you logged in as the correct user?
这个原因基本都是因为你的npm包的名字被别人注册了,换一个名字就可以了
发布之后去NPM server的网站,登录之后看看自己的packages,就能够找到了。

14. 在自己的项目npm安装这个发布的组件

为了在本项目里面引用刚才发布的组件需要将package.json文件里面的name修改一下,不然会提示

1
2
3
npm ERR! Refusing to install package with name "my-first-components" under a package
npm ERR! also called "my-first-components". Did you name your project the same
npm ERR! as the dependency you're installing?

比如将name修改为”name”: “my-first-components-test”,然后执行

1
npm install my-first-components

然后在项目的App.vue里面修改引用方式

1
2
import {myFirstComponents} from './../packages/index' //以前是这样的写法,现在修改为下面的写法
import {myFirstComponents} from 'my-first-components'//新的引入方式

然后执行

1
npm run serve

如果能够正常显示,说明组件发布成功啦。