[toc]javascript
这篇文章主要记录了从零发布一个vue的npm包(包含一个简单的指令和一个vue组件)的实践过程及些许心得。html
这里咱们经过@vue/cli拉取简单配置的模板来初始化一个2.X的项目,不了解的同窗能够看下vueCli3官方文档vue
vue init webpack-simple vue-directive-kit
复制代码
初始化的项目目录以下java
├── README.md
├── index.html
├── package.json
├── src
│ ├── App.vue
│ ├── assets
│ └── main.js
└── webpack.config.js
复制代码
接下来作一些改动。src
目录改成examples
用于本地开发及案例展现,新增一个packages
目录用于存放组件源码及导出文件。webpack
├── README.md
├── examples
│ ├── App.vue
│ └── main.js
├── index.html
├── package.json
├── packages
│ ├── componentName // 单个组件
│ │ ├── index.js
│ │ └── src
│ │ └── componentName.vue
│ └── index.js // 导出文件
└── webpack.config.js
复制代码
因为文件名称作了改动,webpack的打包配置也要作对应修改。默认webpack.config.js
会导出一个对象,这里咱们改成导出一个函数,而后由函数把配置对象导出,这样能够接受一个经过package.json
传过来的参数env
,同时修改entry
及output
:git
module.exports = env => {
return {
entry: env.lib ? "./packages/index.js" : "./examples/main.js",
output: {
// 打包文件的生成路径
path: path.resolve(__dirname, env.lib ? "./lib" : "./dist"),
publicPath: env.lib ? "/lib/" : "/dist/",
// 打包后生成的文件名
filename: env.lib ? "vue-directive-kit.js" : "build.js",
/** * library指定的就是你使用require时引入的模块名 * 这里即是require(“vue-directive-kit”) */
library: env.lib ? "vue-directive-kit" : "",
/** * libraryTarget能够指定打包文件中代码的模块化方式,默认为var,常见有以下几种: * commonjs/commonjs2: 将你的library暴露为CommonJS模块 * amd: 将你的library暴露为amd模块 * umd: 将你的library暴露为全部的模块定义下均可运行的方式 * 其中AMD和UMD须要指定library,若是不声明组件库则不能正常运行, * 这是为了在浏览器上经过script标签加载时,用AMD模块方式输出的组件库能够有明确的模块名 */
libraryTarget: env.lib ? "umd" : "var",
/** * 当使用了 libraryTarget: "umd", * 设置umNamedDefine为true时, * 会对 UMD 的构建过程当中的 AMD 模块进行命名。不然就使用匿名的 define。 */
umdNamedDefine: env.lib ? true : false,
},
};
};
复制代码
上面的配置能够知道,咱们须要经过env来控制打包类型。env
须要在package.json
中传入github
"scripts": {
// 本地开发运行npm run dev
"dev": "cross-env NODE_ENV=development webpack-dev-server --env --open --hot",
"build": "cross-env NODE_ENV=production webpack --env --progress --hide-modules",
// 须要发布的时候执行npm run lib打包
"lib": "cross-env NODE_ENV=production webpack --env.lib --progress --hide-modules"
},
复制代码
在packages/componentName/src/componentName.vue
文件中写以下你内容。固然这个是为了演示内容很简单,其实这个文件就是真实的组件了。web
<template>
<div>
<h1>我是一个组件</h1>
</div>
</template>
<script> export default { name: 'componentName', data () { return { } } } </script>
复制代码
在packages/componentName/src/index.js
中注册并导出单个组件npm
// 引入组件
import componentName from './componentName/src'
componentName.install = Vue => Vue.component(componentName.name, componentName);
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use(componentName);
}
export default componentName;
复制代码
咱们增长一个名称为testDirective
的指令。 建立'packages/testDirective/src/testDirective.js'文件:json
export default {
bind: () => {
console.log(`directive bind`);
},
inserted: (el, binding) => {
console.log(`el:`, el);
},
}
复制代码
建立packages/testDirective/index.js
文件:
// 引入组件
import testDirective from './src/testDirective'
const install = Vue => {
Vue.directive('testDirective', testDirective);
};
if (typeof window !== 'undefined' && window.Vue) {
window.Vue.use({install});
}
export default {
install
};
复制代码
编辑出口文件packages/index.js
,将packages
目录下全部的指令及组件统一注册导出:
// 导入颜色选择器组件
import componentName from './componentName/src/componentName.vue'
import testDirective from './testDirective/src/testDirective'
// 存储组件列表
const components = [
componentName,
]
// 存储指令映射
export const directives = {
testDirective,
}
// 定义 install 方法,接收 Vue 做为参数。若是使用 use 注册插件,则全部的组件都将被注册
const install = function (Vue) {
// 遍历注册全局组件
components.map(component => Vue.component(component.name, component))
// 遍历注册指令
Reflect.ownKeys(directives).map(name => Vue.directive(name, directives[name]))
}
// 判断是不是直接引入文件
if (typeof window !== 'undefined' && window.Vue) {
install(window.Vue)
}
export default {
// 导出的对象必须具备 install,才能被 Vue.use() 方法安装
install,
// 如下是具体的组件列表
componentName,
...directives,
}
复制代码
到这里,咱们的包里就包含了一个名为componentName
的组件和一个名为testDirective
的指令,本地测试一下,先在examples/main.js
中引入
// 单独引入指令文件
// import pkgName from '../packages/test-directive/index'
// 总体引入包
import pkgName from '../packages/index'
Vue.use(pkgName)
复制代码
在examples/App.vue
中使用
<template>
<div id="app">
<h1 v-test-directive>Test Directive</h1>
<component-name></component-name>
</div>
</template>
复制代码
而后运行yarn dev
本地查看效果
看起来本地测试已经没有问题,能够打包发布了。 不过在打包发布以前,须要先作一些准备工做。
一个标准的npm包或者开源项目都会一个有完善且好看的README帮用户快速了解你的项目。经过generator-standard-readme
能够快速生成一个README模板
npm install --global yo generator-standard-readme
yo standard-readme
复制代码
package.json
文件为package.json
增长一些发布npm包所须要的基本字段:
/**
* npm包名,要符合几个规则:
* 1. name的长度必须小于等于214个字符。
* 2. name不能以"."(点)或者"_"(下划线)开头。
* 3. name中不能包含大写字母。
* 4. name最终将被用做URL的一部分、命令行的参数和文件夹名。所以,name不能含有非URL安全的字符。
*/
"name": "vue-directive-kit",
"description": "A collection of vue directives.",
"version": "1.0.1",
"author": "slevin <575720013@qq.com>",
"license": "MIT",
// 是否私有,默认为true,改成false
"private": false,
// 是一个字符串的数组。它能够帮助人们在使用npm search时找到这个包
"keywords": [
"vue",
"vue-directive-kit",
"vue-directive"
],
/**
* files字段是一个被项目包含的文件名数组
* 若是你在里面放一个文件夹名,那么这个文件夹中的全部文件都会被包含进项目中(除非是那些在其余规则中被忽略的文件)。
* 你还能够在包的根目录或子目录下提供一个".npmignore"文件来忽略项目包含文件,即便这些文件被包含在files字段中
* 某些文件老是被包含的,不管是否在规则中指定了它们:
* package.json
* README (and its variants)
* CHANGELOG (and its variants)
* LICENSE / LICENCE
*/
"files": [
"lib/vue-directive-kit.js",
"package.json",
"README.md"
],
/**
* main字段用来指定入口文件
*
*/
"main": "lib/vue-directive-kit.js",
/**
* 指明你的代码被托管在何处,也就是远程仓库的地址
*/
"repository": {
"type": "git",
"url": "git@github.com:slevin57/vue-directive-kit.git"
}
复制代码
随便找一个项目,安装这个包进行测试。这里咱们就在根目录下再初始化一个vue基本项目用来测试包的使用,而后把npm包文件放到测试项目根路径执行安装,同时安装项目依赖。
vue init webpack-simple test
mv xxx.tgz ./test
cd test
npm i xxx.tgz && npm i
复制代码
在main.js
中像正常引入第三方包那样操做就能够。测试完成后记得删掉test目录。 准备操做及测试都作完后就能够打包发布了。
先打包
npm run lib
复制代码
登陆npm,输入npm注册的用户名、密码及邮箱
npm login
复制代码
发布
npm publish
复制代码
不出意外的话,登陆npm就能够看到你发布的包了。发布的包在72小时内是能够删除的,过了72小时就永远没法删除了,因此记得不要随意发一些没有意义的包。 若是须要卸载,在发布后72小时内执行:
npm unpublish <pkg>[@<version>]
复制代码
参考代码: github.com/slevin57/vu…