[toc]
这篇文章主要记录了从零发布一个 vue 的 NPM 包 (包含一个简单的指令和一个 vue 组件) 的实践过程及些许心得.
初始化项目
这里我们通过 @vue/cli 拉取简单配置的模板来初始化一个 2.X 的项目, 不了解的同学可以看下 vueCli3 官方文档
vue init webpack-simple vue-directive-kit
初始化的项目目录如下
├── README.md
├── index.html
├── package.JSON
├── src
│ ├── App.vue
│ ├── assets
│ └── main.JS
└── webpack.config.JS
接下来做一些改动. src 目录改为 examples 用于本地开发及案例展示, 新增一个 packages 目录用于存放组件源码及导出文件.
├── 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:
- 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 中传入
- "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 文件中写如下你内容. 当然这个是为了演示内容很简单, 其实这个文件就是真实的组件了.
- <template>
- <div>
- <h1 > 我是一个组件</h1>
- </div>
- </template>
- <script>
- export default {
- name: 'componentName',
- data () {
- return { }
- }
- }
- </script>
在 packages/componentName/src/index.JS 中注册并导出单个组件
- // 引入组件
- import componentName from './componentName/src'
- componentName.install = Vue => Vue.component(componentName.name, componentName);
- if (typeof Windows !== 'undefined' && Windows.Vue) {
- Windows.Vue.use(componentName);
- }
- export default componentName;
编写指令
我们增加一个名称为 testDirective 的指令.
创建'packages/testDirective/src/testDirective.js'文件:
- 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 Windows !== 'undefined' && Windows.Vue) {
- Windows.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 Windows !== 'undefined' && Windows.Vue) {
- install(Windows.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 本地查看效果
image
看起来本地测试已经没有问题, 可以打包发布了.
不过在打包发布之前, 需要先做一些准备工作.
发布前准备
generator-standard-readme
一个标准的 NPM 包或者开源项目都会一个有完善且好看的 README 帮用户快速了解你的项目. 通过 generator-standard-readme 可以快速生成一个 README 模板
- NPM install --global yo generator-standard-readme
- yo standard-readme
image
完善 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
先打包
NPM run lib
登录 NPM, 输入 NPM 注册的用户名, 密码及邮箱
NPM login
发布
NPM publish
不出意外的话, 登录 NPM 就可以看到你发布的包了. 发布的包在 72 小时内是可以删除的, 过了 72 小时就永远无法删除了, 所以记得不要随意发一些没有意义的包.
如果需要卸载, 在发布后 72 小时内执行:
NPM unpublish <pkg>[@<version>]
来源: http://www.jianshu.com/p/a088d544ee28