前言

本文主要是讲如何开发一个 vue 组件,做成 npm 包并发布以及使用、维护。

什么是 npm?

在 GitHub 还没有兴起的年代,前端是通过网址来共享代码

比如你想使用 jQuery,那么你点击 jQuery 网站上提供的链接就可以下载 jQuery,放到自己的网站上使用。

当一个网站依赖的代码越来越多,程序员发现这是一件很麻烦的事情:

  1. 去 jQuery 官网下载 jQuery
  2. 去 BootStrap 官网下载 BootStrap
  3. 去 Underscore 官网下载 Underscore
  4. ……

有些程序员就受不了了,一个叫做 Isaac Z. Schlueter 的程序员 (以下简称 Isaaz)给出一个解决方案:用一个工具把这些代码集中到一起来管理吧!

这个工具就是他用 JavaScript (运行在 Node.js 上)写的 npm,全称是 Node Package Manager。所以现在,你可以使用 npm install jquery 来下载 jQuery 代码。现在用 npm 来分享代码已经成了前端的标配。接下来我们来说说,如何制作一个 npm 包。

第一步,准备工作

1. 注册 npm 账号

前往 npm 官网 注册一个账号。

2. 确认包名称

通过命令确认名称是否被占用,操作如下:

1
npm view yqy-packages

yqy-packages 是我期望的包名称,执行该命令之后,如果出现了包的信息,则表示该名称已经被占用,则需要换个名称,如果出现报错 404 则表示改名称没有被占用,然后我们使用没有被占用的名称,创建项目。

3. 确认 vue-cli 版本

vue 脚手架版本区别,大于 3.0 包名是 @vue/cli, 小于 3.0 则包名为 vue-cli。

我们推荐使用 3.0 之前的 vue-cli 版本,首先查看本地是否全局安装了 vue-cli, 如果大于 3.0 或者没有安装,则卸载 @vue/cli, 重新安装 vue-cli, 相关命令如下:

1
2
3
4
5
6
7
8
vue -V
@vue/cli 4.5.13

npm uninstall -g @vue/cli
npm install vue-cli -g

vue -V
2.9.6

4. 初始化项目

npm 包开发时推荐使用 webpack-simple 模板构建项目,只保留基本功能即可。

创建一个文件夹,名称就是上一步骤确认过没有被占用的包名称。然后进入该文件夹内,使用命令初始化为 vue 项目。

1
vue init webpack-simple

一路回车即可,初始化完成之后,会自动生成一个 vue 项目底层文件,然后安装依赖,并预览。

1
2
npm install
npm run dev

第二步,组件的编写和预览

1. 开发组件,在 src 目录下创建 components 文件夹,然后在 components 下创建 yqyPackages.vue, 用于开发组件,假设我们的组件内容如下(这只是一个示例,假设组件需求就是展示传入的内容,实际开发中应该根据实际需求编写组件):

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<template>
<div class="container">
<div>{{propData}}</div>
</div>
</template>

<script>
export default {
name: 'yqy-packages',
data () {
return {}
},
props: {
propData: {
type: String,
default: '我是默认值'
}
}
}
</script>

2. 本地预览,在 app.vue 中引入组件,运行项目看效果,修改 app.vue 内容如下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
<template>
<div>
<yqy-packages :propData='initData'/>
</div>
</template>

<script>
import yqyPackages from './components/yqyPackages'
export default {
data(){
return {
initData: 'hello world'
}
},
components:{
yqyPackages
}
}
</script>

第三步,第三方入口文件和配置

如果上面步骤都顺利的话,运行项目应该是可以看到页面呈现的 hello world, 可以理解为组件已经开发完成,但是目前只是在 app.vue 中使用,我们需要让他可以提供给第三方使用,看看如何操作!

1. 准备入口文件

在项目根目录下,创建 index.js, 编写如下代码:

1
2
3
4
5
6
7
8
9
10
11
import yqyPackages from './src/components/yqyPackages'

// 这一步判断 window.Vue 是否存在,因为直接引用 vue.min.js, 它会把 Vue 绑到 Window 上,我们直接引用打包好的 js 才能正常跑起来。
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.component('yqy-packages', yqyPackages)
}
//这样就可以使用Vue.use进行全局安装了。
yqyPackages.install = function(Vue) {
Vue.component(yqyPackages.name, yqyPackages)
}
export default yqyPackages

2. 修改项目根目录配置文件 webpack.config.js

默认使用 main.js 作为入口,所以可以跑起来呈现 app.vue 的内容来预览调试,但是组件开发完成后提供给第三方使用时,我们只需要组件的代码,也就是 yqyPackages.vue 内编写的代码,而我们上一步准备的入口文件 index.js 就是将这个 yqyPackages.vue 内的代码暴露出去的入口,所以修改配置文件,让入口可以根据开发环境和生成环境的切换而改变。

  • main.js, 是命令 npm run dev 的入口,也就是 app.vue,用于调试、测试我们开发的组件;
  • index.js, 是我们打包到生产环境的入口,第三方引用的入口,对应的就是单纯的 yqyPackages.vue 组件内容;
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
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
// webpack.config.js
var path = require('path')
var webpack = require('webpack')

// 新增环境变量
const NODE_ENV = process.env.NODE_ENV

module.exports = {
// entry: './src/main.js', // 修改入口文件
entry: NODE_ENV === 'development' ? './src/main.js' : './index.js',
output: {
path: path.resolve(__dirname, './dist'),
publicPath: '/dist/',
filename: 'build.js'
},
module: {
rules: [
{
test: /\.css$/,
use: [
'vue-style-loader',
'css-loader'
],
}, {
test: /\.vue$/,
loader: 'vue-loader',
options: {
loaders: {
}
// other vue-loader options go here
}
},
{
test: /\.js$/,
loader: 'babel-loader',
exclude: /node_modules/
},
{
test: /\.(png|jpg|gif|svg)$/,
loader: 'file-loader',
options: {
name: '[name].[ext]?[hash]'
}
}
]
},
resolve: {
alias: {
'vue$': 'vue/dist/vue.esm.js'
},
extensions: ['*', '.js', '.vue', '.json']
},
devServer: {
historyApiFallback: true,
noInfo: true,
overlay: true
},
performance: {
hints: false
},
devtool: '#eval-source-map'
}

if (process.env.NODE_ENV === 'production') {
module.exports.devtool = '#source-map'
// http://vue-loader.vuejs.org/en/workflow/production.html
module.exports.plugins = (module.exports.plugins || []).concat([
new webpack.DefinePlugin({
'process.env': {
NODE_ENV: '"production"'
}
}),
new webpack.optimize.UglifyJsPlugin({
sourceMap: true,
compress: {
warnings: false
}
}),
new webpack.LoaderOptionsPlugin({
minimize: true
})
])
}

第四步,npm 平台发布

1. 修改 package.jsonprivate 字段,privatetrue 的时候不能发布到 npm, 需设置成 false,默认是 true

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
32
33
{
"name": "yqy-packages",
"description": "A Vue.js project",
"version": "1.0.0",
"author": "LiuKun <308880147@qq.com>",
"license": "MIT",
"private": false,
"scripts": {
"dev": "cross-env NODE_ENV=development webpack-dev-server --open --hot",
"build": "cross-env NODE_ENV=production webpack --progress --hide-modules"
},
"dependencies": {
"vue": "^2.5.11"
},
"browserslist": [
"> 1%",
"last 2 versions",
"not ie <= 8"
],
"devDependencies": {
"babel-core": "^6.26.0",
"babel-loader": "^7.1.2",
"babel-preset-env": "^1.6.0",
"babel-preset-stage-3": "^6.24.1",
"cross-env": "^5.0.5",
"css-loader": "^0.28.7",
"file-loader": "^1.1.4",
"vue-loader": "^13.0.5",
"vue-template-compiler": "^2.4.4",
"webpack": "^3.6.0",
"webpack-dev-server": "^2.9.1"
}
}

2. 命令行登录 npm 账号

1
2
3
4
5
6
7
npm login
Username: 填写 npm 用户名
Password: 填写 npm 登陆密码
Email: (this IS public) : 填写 npm 账户联系邮箱

# 出现下面这句表示登录成功
Logged in as **** on https://registry.npmjs.org/.

3. 发布 npm 包,每次发布的时候 packa.json 里面的 version 不能一样,不然不能发布出去,手动改下版本就行

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
npm publish

npm notice
npm notice 📦 yqy-packages@1.0.0
npm notice === Tarball Contents ===
npm notice 72B .babelrc
npm notice 147B .editorconfig
npm notice 206B index.html
npm notice 544B index.js
npm notice 100B src/main.js
npm notice 1.8kB webpack.config.js
npm notice 842B package.json
npm notice 327B README.md
npm notice 6.8kB src/assets/logo.png
npm notice 270B src/App.vue
npm notice 338B src/components/yqyPackages.vue
npm notice === Tarball Details ===
npm notice name: yqy-packages
npm notice version: 1.0.0
npm notice package size: 9.4 kB
npm notice unpacked size: 11.5 kB
npm notice shasum: 7f52f85068b37e81eb9b05eaf832d427b0a7b810
npm notice integrity: sha512-wiws7/01Gk2WI[...]H/y2CHE/f/8Pw==
npm notice total files: 11
npm notice
+ yqy-packages@1.0.0

4. 在 vue 项目中使用 npm 包

安装依赖

1
npm install yqy-packages

在 main.js 全局引入

1
2
3
// main.js
import yqyPackages from 'yqy-packages'
Vue.use(yqyPackages)

在页面中使用

1
<yqy-packages propData="这是一个测试文本"></yqy-packages>

5. 更新包

npm 包项目源代码更新之后,修改版本号,重新打包发布即可。