不会发布npm包?进来看看?
npm(Node Package Manager),一个Node的包管理器,平时我们常用的公共模块(插件)或者叫做包大多都放在上面,所以接下来要封装的插件,我们就简单称它为npm包,本文从就从这个简单的例子开始,逐步对它进行封装-发布-更新-扩展-使用,进而到得一个相对完整的npm包,下面开始。
一、一个最简单的npm包1.1 新建文件夹可以找个地方直接建个文件夹,最好语义化一点,这样以后也方便管理,我们这里用终端建文件夹:
mkdir toupper-case-project // 这里我们建了一个名为toupper-case-project的文件夹
(对命令行还不太熟的小伙伴可以看看我这篇博客命令行不会?看这里)
1.2 初始化项目在项目根目录下使用一下命令
npm init
这时终端会提示你输入诸如包名,版本号等信息,如下:
当然,你可以一路回车下来,或者你使用npm init -y
就可以生成默认的package.json
文件,效果都是一样的,然后我们得到以下文件,简单说明一下:
// package.json{ "name": "toupper-case-project", // 包名称,默认和你文件夹同名,可改,但是需要去npm官网搜素这个名称是否已存在,因为包名不能重复 "version": "1.0.0", // 项目默认版本号,可改,如果项目后期更新再发布,则需要修改版本号 "description": "", // 项目描述,选填,可利于SEO "main": "index.js", // 你的包的主要入口路径,就是别人安装了你的包后系统会去这个路径找你的代码 "scripts": { // 脚本命令,后面会讲到,现在使用默认的就行 "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", // 作者,选填 "license": "ISC" // 许可证,默认即可}
1.3 新建项目文件注:以上代码使用时记得把注释删除,json不能注释
根目录下新建index.js
和upper.js
两个文件分别如下:
// upper.jslet toUpper = (a) => { return a.toUpperCase();};export default toUpper;
// index.jsimport toUpper from './upper.js';export default toUpper;
此时我们的项目就应该只有三个文件,如下:
upper.js
用于项目功能逻辑,index.js
用于导出功能模块,package.json
用于配置相关信息,这样我们就把一个最简单的npm
包写好了,接下里进入发布。
1.注册npm账号
前往npm官网注册一个账号,记好账户名、密码和邮箱(邮箱收到邮件后一定要进行验证)。
2.源切换
这是个坑,估计很多小伙伴都踩过,毕竟国内npm
的速度令人感动,所以大家都运行过一条熟悉的命令:
npm install -g cnpm --registry=https://registry.npm.taobao.org
但是发布时我们一定要把源切换回npm
,而不是淘宝源,当然,直接运行下面这个命令即可解决:
npm config set registry=http://registry.npmjs.org
但是老这样切来切去有点low啊,这时候nrm
就派上用场了,nrm
是什么?简单点说nrm
就是专门用来管理和快速切换私人配置的registry的一个工具。
cnpm i nrm -g
安装好后使用nrm ls
命令会显示如下:
*
号在哪个地方就说明现在的源是哪个(我现在处在taobao源),也许你刚开始不显示号,但不管显不显示,直接运行nrm use npm
,然后再npm ls
,这时候就发现`指在
npm`源上了,此时就可以进行下一步了。
3.登录
npm login
然后会提示你输入用户名、密码(是密文的,你看不见,直接输就行)和邮箱,登录成功后会显示:
4.试着发布npm包
在项目根目录下运行npm publish
即可发布,顺利的话就直接成功了,当然也可能会遇到问题:
第一个就是权限问题,也许报这样的错误npm ERR! Error: EPERM: operation not permitted
,这时候就得使用管路员权限来进行发布了,window + x
会看到管理员终端选项,打开这个终端,然后再进行登录,发布即可。
package.json
中将你的包名改成其他的,这样再发布,应该就没问题了。发布成功后显示如下:
1.5 用用我们发布的包随便找个练手项目试试:
cnpm i toupper-case-project -D
安装完成:
说明我们的包是可以下载安装的,然后试试功能,我就直接在vue项目中试试了,大家应该看得懂:
然后运行项目:
搞定!那如果我们后期把这个包改了呢,该怎么做?
1.6 更新包我们把upper.js
文件改一改:
// upper.jslet toUpper = (a) => { return 'Hello' + a.toUpperCase();};export default toUpper;
然后记得把package.json
中的版本号也改了,正常来说加1即可,
将"version": "1.0.0"
改为"version": "1.0.1"
现在运行npm publish
就可以直接把新的包覆盖上去:
然后我们在练手项目中怎么更新这个包呢?
方法一(直接更新):cnpm update toupper-case-project
(有时可能更新不完全)
cnpm i toupper-case-project -D
(这个比较靠谱)然后运行项目:
完美!这就是一个最简单的npm包,是不是没有想象中的那么触不可及?但说实话,这个包确实挺low,你看别人的包还经过打包啊、测试啊、还能在vue中直接Vue.use()方式来使用,而且还有交互。那下面我们就来试试。
二、基于webpack和vue的npm包直接使用vue-cli的话会带上许多我们不需要的模块,太笨重,所以我们直接撸一个,如果对webpack
还不太熟悉的,可以看看我这篇webpack4.x最详细入门讲解
我们来封装一个可根据传入的评分数来显示星级的组件,类似这样的:
具体代码请移步github,请反手给个 ★ Star ^_~,下面开始:
首先新建一个名为star-evaluation
的项目文件夹;
然后根据以下结构建立项目文件:
|——src| |——images| | |——star24_half@2x.png| | |——star24_off@2x.png| | |——star24_on@2x.png| |——index.js| |——Star.vue|——.npmignore // 用于忽略不需要上传到npm的文件|——package.json|——README.md|——webpack.config.js
各文件如下:
Star.vue
具体代码如下,主要就是将传过来的数值处理后遍历出不同的class
类名,然后添加到span
上。
<!-- Star.vue --><template> <div class="star"> <span class="star-item" v-for="(itemClass, index) in itemClasses" :key="index" :class="itemClass"></span> </div></template><script>// 星星长度const LENGTH = 5;// 星星状态const CLS_ON = 'on';const CLS_HALF = 'half';const CLS_OFF = 'off';export default { data () { return { } }, props: { score: { type: Number } }, computed: { itemClasses () { let result = []; // 如果小数大于或等于0.5则变为0.5,否则为0 let score = Math.floor(this.score * 2) / 2; // 全星 let integer = Math.floor(score); // 半星 let hasHalf = score % 1 !== 0; // 遍历全星 for (let i = 0; i < integer; i++) { result.push(CLS_ON); } // 处理半星 if (hasHalf) { result.push(CLS_HALF); } // 补齐,如果星数小于5,则一直循环判断填入数据,直到满足条件 while (result.length < LENGTH) { result.push(CLS_OFF); } return result; } }}</script><style lang="scss" scoped> .star{ font-size: 0; .star-item{ display: inline-block; width: 10px; height: 10px; margin-right: 3px; background-repeat: no-repeat; background-size: 10px 10px; &:last-child{ margin-right: 0; } } /* 三种图片类型*/ .on{ background-image: url(./images/star24_on@2x.png); } .half{ background-image: url(./images/star24_half@2x.png); } .off{ background-image: url(./images/star24_off@2x.png); } }</style>
// index.jsimport Star from './Star.vue';export default Star;
package.json
的依赖配置如下:
{ "name": "star-evaluation", "version": "1.0.0", "description": "A plugin which use stars number to evaluate", "main": "dist/bundle.js", "scripts": { "build": "webpack --mode production", "dev": "webpack-dev-server --open --mode development" }, "repository": { "type": "git", "url": "git+https://github.com/Better-Alan/star-evaluation.git" }, "keywords": ["star", "evaluation"], "author": "BetterMan", "license": "ISC", "devDependencies": { "babel-core": "^6.26.3", "babel-loader": "^7.1.5", "babel-preset-env": "^1.7.0", "css-loader": "^1.0.0", "file-loader": "^2.0.0", "node-sass": "^4.9.4", "sass-loader": "^7.1.0", "style-loader": "^0.23.1", "url-loader": "^1.1.2", "vue": "^2.5.17", "vue-hot-reload-api": "^2.2.4", "vue-html-loader": "^1.2.4", "vue-loader": "^15.4.2", "vue-router": "^3.0.1", "vue-style-loader": "^3.0.3", "vue-template-compiler": "^2.5.9", "webpack": "^4.23.1", "webpack-cli": "^3.1.2" }}
webpack.config.js
配置如下,用于将/src
中的内容打包到/dist
(打包时会自动生成/dist
文件夹)中的bundle.js
,bundle.js
其实就相当于我们的插件。
// webpack.config.jsconst path = require('path'); // 路径处理模块const { VueLoaderPlugin } = require('vue-loader');module.exports = { entry: { index: path.join(__dirname, "/src/index.js") // 入口 }, output: { path: path.join( __dirname, "/dist"), // 打包后的文件存放的地方 publicPath: '/dist/', // 设置公共路径 filename: "bundle.js", // 打包后输出文件的文件名 libraryTarget: 'umd' // 将你的library暴露为所有的模块定义下都可运行的方式,它将可在 CommonJS, AMD 环境下运行 }, module: { rules: [ { test: /\.vue$/, // vue-loader loader: 'vue-loader' }, { test: /\.css$/, // 正则匹配以.css结尾的文件 use: ['style-loader', 'css-loader'] }, { test: /\.(scss|sass)$/, // 正则匹配以.scss和.sass结尾的文件 use: ['style-loader', 'css-loader', 'sass-loader'] // 需要用的loader,一定是这个顺序,因为调用loader是从右往左编译的 }, { test: /\.(png|jpg|svg|gif)$/, // 图片loader use: ['url-loader'] }, { test: /\.js$/, exclude: /node_modules|vue\/dist|vue-router\/|vue-loader\/|vue-hot-reload-api\//, loader: 'babel-loader' } ] }, plugins: [ new VueLoaderPlugin() ]}
.npmignore
(别忘了前面的点)文件用于忽略不需要上传到npm的文件,规则和.gitignore
一样。如果你的项目内有.gitignore
但没有.npmignore
,则会使用.gitignore
的配置。
.**.mdnode_modules/src/
README.md
说明(不是必须),大家应该都比我6。
此时我们的目录应该如下:
2.2 安装依赖以上文件都配置好后就可以运行一下命令安装依赖了:
cnpm install
2.3 打包项目
依赖安装完成后对项目进行打包:
npm run build
2.4 登录并发布(确保当前处于npm源)
打包完成后运行npm login
登录后npm publish
发布:
发布搞定!,那能不能用呢?我们去试试看。
2.5 试试我们的npm包先下载:cnpm i star-evaluation -D
运行后显示如下:
搞定,这是不是比之前那个toupper-case-project
插件高端那么一丢丢?
那有的小伙伴可能会说了:“我平时看到的插件不是这么用的,很多都是直接Vue.use()
后就可以用了,而且插件还有事件的。”
那我们再改改?
其实能否使用Vue.use()
这个方式来调用组件,取决于是否配置了install
方法,我们给Star.vue
组件加上看看:
// index.jsimport Star from './Star.vue';Star.install = Vue => Vue.component(Star.name, Star); // 给Star组件配置install方法,注册该组件 export default Star;
注:这里有个需要注意的地方,就是
Star.name
是指向我们给Star.vue
文件中配置的name
属性,别忘了配置它:
这时已经搞定了Vue.use()
了,那我们再加上事件交互,就做个点击组件弹出具体的星级数值吧!
具体修改如下:
<!-- Star.vue --><template> <!-- 绑定showNumber方法 --> <div class="star" @click="showNumber"> <span class="star-item" v-for="(itemClass, index) in itemClasses" :key="index" :class="itemClass"></span> </div></template><script>...export default { name: 'Star', // 别忘加上这个属性 ... methods: { showNumber() { this.$emit('showNumber', '我是弹出的信息'); // 将自定义方法showNumber暴露出去,且将参数传出 } }}</script>...
3.3 打包-发布-使用
依旧老套路,修改版本号-打包-发布,然后我们在练手项目中cnpm i star-evaluation -D
再安装一次,因为有时npm update star-evaluation
方法不太靠谱,更新不完全。
然后我们在练手项目中使用Vue.use()
方式和试试事件,在所要使用插件的文件中使用方式如下:
<template> <div class="hello"> <!-- 子组件所传出的自定义showNumber方法调用当前showMessage方法 --> <Star @showNumber="showMessage" :score="2.6"/> </div></template><script>import Vue from 'vue' // 引入Vueimport Star from 'star-evaluation'; // 引入Star插件Vue.use(Star) // 使用Star插件// 以上的引入和注册一般是在main.js中统一完成,这个大家应该都比较熟悉export default { // 因为使用了Vue.use(Star)方式,所以这里不需要使用components: {Star}来注册插件 methods: { // 点击组件触发此方法 showMessage(mes) { alert(mes); } }}</script><style scoped></style>
然后我们npm run dev
重启启用项目,点击组件显示如下:
搞定!是不是也没那么难?
最后本来只打算简单的写下基本步骤的,没想到写(啰嗦)了这么长,有写得不合适的地方请多多指教,如果能对你有所帮助,也麻烦github给个星哈,这样我就可以放心的去搬砖了↓-↓
掘金
博客园
声明:本站所有文章资源内容,如无特殊说明或标注,均为采集网络资源。如若本站内容侵犯了原著者的合法权益,可联系本站删除。