在npm上发布自己的vue组件库(使用npm install 或者 CDN的方式引用)
一、npm publish
发布包到npm库的命令是npm publish
npm publish发布包,需要先配置webpack.json文件,如果没有webpack.json文件,可以通过npm init命令初始化一个
package.json的部分字段简介如下
name:发布的包名,默认是上级文件夹名。不得与现在npm中的包名重复。包名不能有大写字母/空格/下滑线! version:你这个包的版本,默认是1.0.0。对于npm包的版本号有着一系列的规则,模块的版本号采用X.Y.Z的格式,具体体现为: 1、修复bug,小改动,增加z。 2、增加新特性,可向后兼容,增加y 3、有很大的改动,无法向下兼容,增加x description:项目简介 mian:入口文件,默认是index.js scripts:包含各种脚本执行命令 test:测试命令。 author:自己的账号名 license:开源文件协议 private:是否私有
如果要发布的话需要把private字段设为false
发布的包的资源可以通过https://unpkg.com/$name@$version/找到。
比如我发布了一个包,name是zxz-ui,version是1.0.0,那么我就可以在 https://unpkg.com/zxz-ui@1.0.0/ 找到我发布的包里面的资源
我们可以通过创建文件npmignore或者 pkg.files来设置上传时过滤某些文件和文件夹,如果我们不设置的话,有些文件和文件夹也是会默认忽略上传的,比如node_modules文件夹、package-lock.json文件等
二、我们如何通过npm引用组件的
先看一下node.js中的模块调用的规则 https://nodejs.org/api/modules.html#modules_accessing_the_main_module
主要注意以下两部分
require(X) from module at path Y 1. If X is a core module, a. return the core module b. STOP 2. If X begins with '/' a. set Y to be the filesystem root 3. If X begins with './' or '/' or '../' a. LOAD_AS_FILE(Y + X) b. LOAD_AS_DIRECTORY(Y + X) 4. LOAD_NODE_MODULES(X, dirname(Y)) 5. THROW "not found" LOAD_AS_FILE(X) 1. If X is a file, load X as JavaScript text. STOP 2. If X.js is a file, load X.js as JavaScript text. STOP 3. If X.json is a file, parse X.json to a JavaScript Object. STOP 4. If X.node is a file, load X.node as binary addon. STOP LOAD_INDEX(X) 1. If X/index.js is a file, load X/index.js as JavaScript text. STOP 2. If X/index.json is a file, parse X/index.json to a JavaScript object. STOP 3. If X/index.node is a file, load X/index.node as binary addon. STOP LOAD_AS_DIRECTORY(X) 1. If X/package.json is a file, a. Parse X/package.json, and look for "main" field. b. If "main" is a falsy value, GOTO 2. c. let M = X + (json main field) d. LOAD_AS_FILE(M) e. LOAD_INDEX(M) f. LOAD_INDEX(X) DEPRECATED g. THROW "not found" 2. LOAD_INDEX(X) LOAD_NODE_MODULES(X, START) 1. let DIRS = NODE_MODULES_PATHS(START) 2. for each DIR in DIRS: a. LOAD_AS_FILE(DIR/X) b. LOAD_AS_DIRECTORY(DIR/X) NODE_MODULES_PATHS(START) 1. let PARTS = path split(START) 2. let I = count of PARTS - 1 3. let DIRS = [GLOBAL_FOLDERS] 4. while I >= 0, a. if PARTS[I] = "node_modules" CONTINUE b. DIR = path join(PARTS[0 .. I] + "node_modules") c. DIRS = DIRS + DIR d. let I = I - 1 5. return DIRS
以iview为例,我们npm i iview下载iview组件库后,通过import iView from 'iview'引用它,其实就是通过import iView from './node_modules/iview'引用它,然后./node_modules/iview是一个文件夹,会按照LOAD_AS_DIRECTORY(X)中的规则寻找,先是找到./node_modules/iview/package.json这个文件,然后找到其中的main字段,最后通过main字段找到./node_modules/iview/dist/iview.js这个文件。
iview.js这个文件是通过webpack打包得到的,直接看代码基本上是看不懂的,我们看看它是怎么打包出来的。
先找到iview.js的webpack配置文件
https://github.com/iview/iview/blob/2.0/build/webpack.dist.dev.config.js
…… process.env.NODE_ENV = 'production'; module.exports = merge(webpackBaseConfig, { devtool: 'source-map', entry: { main: './src/index.js' }, output: { path: path.resolve(__dirname, '../dist'), publicPath: '/dist/', filename: 'iview.js', library: 'iview', libraryTarget: 'umd', umdNamedDefine: true }, …… });
上面是在生产环节下打包iview.js的配置,我们找到它的入口文件
https://github.com/iview/iview/blob/2.0/src/index.js
import Affix from './components/affix'; …… const components = { Affix, …… }; const iview = { ...components, iButton: Button, …… }; const install = function(Vue, opts = {}) { if (install.installed) return; …… Object.keys(iview).forEach(key => { Vue.component(key, iview[key]); }); …… }; // auto install if (typeof window !== 'undefined' && window.Vue) { install(window.Vue); } const API = { …… install, …… }; …… module.exports.default = module.exports = API; // eslint-disable-line no-undef
这里说明一下,我是用组件内部的name属性做的组件标签名
5. 配置webpack.config.js
var path = require('path') var webpack = require('webpack') const NODE_ENV = process.env.NODE_ENV module.exports = { //入口这里一个是测试组件时npm run dev的入口文件,一个是npm run build的入口文件 entry: NODE_ENV === 'development' ? './src/main.js' : './index.js', output: { path: path.resolve(__dirname, './dist'), publicPath: '/dist/', //输出的文件夹 filename: 'filename.js',//输出的文件名 library: 'objectname', //引用js文件时创建的全局变量名 libraryTarget: 'umd', umdNamedDefine: true }, …… }
……
20
配置package.json
{ "name": "package-name", "description": "描述", "version": "1.0.0", "author": "XXXXXXXXXXX", "license": "MIT", "private": false, "main": "dist/filename.js", …… }
npm run build npm publish 使用 //npm导入 npm i package-name import xxx from 'package-name' Vue.use(xxx)
//cdn导入
<script src="//vuejs.org/js/vue.min.js"></script> <script src="//https://unpkg.com/package-name@1.0.0/dist/filename.js"></script>
如果想把css单独抽离出来还需要更新webpack、webpack-cli,和安装optimize-css-assets-webpack-plugin、uglifyjs-webpack-plugin等包。
webpack配置:https://github.com/pma934/zxz-ui/blob/master/webpack.config.js