前言

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" // 许可证,默认即可
}

注:以上代码使用时记得把注释删除,json不能注释

1.3 新建项目文件

根目录下新建index.jsupper.js两个文件分别如下:

// upper.js
let toUpper = (a) => {
return a.toUpperCase();
};
export default toUpper;
// index.js
import toUpper from './upper.js';
export default toUpper;

此时我们的项目就应该只有三个文件,如下:

upper.js用于项目功能逻辑,index.js用于导出功能模块,package.json用于配置相关信息,这样我们就把一个最简单的npm包写好了,接下里进入发布。

1.4 发布

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会看到管理员终端选项,打开这个终端,然后再进行登录,发布即可。

  • 第二个就是名称问题,就是你的包名在npm上已经存在了,所以在package.json中将你的包名改成其他的,这样再发布,应该就没问题了。

发布成功后显示如下:

1.5 用用我们发布的包

随便找个练手项目试试:

cnpm i toupper-case-project -D

安装完成:

说明我们的包是可以下载安装的,然后试试功能,我就直接在vue项目中试试了,大家应该看得懂:

然后运行项目:

搞定!那如果我们后期把这个包改了呢,该怎么做?

1.6 更新包

我们把upper.js文件改一改:

// upper.js
let 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最详细入门讲解

2.1 构建项目(星级评价组件)

我们来封装一个可根据传入的评分数来显示星级的组件,类似这样的:

具体代码请移步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.js
import 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.jsbundle.js其实就相当于我们的插件。

// webpack.config.js
const 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的配置。

.*
*.md
node_modules/
src/

README.md说明(不是必须),大家应该都比我6。

此时我们的目录应该如下:

2.2 安装依赖

以上文件都配置好后就可以运行一下命令安装依赖了:

cnpm install

2.3 打包项目

依赖安装完成后对项目进行打包:

npm run build

2.4 登录并发布(确保当前处于npm源)

打包完成后运行npm login登录后npm publish发布:

发布搞定!,那能不能用呢?我们去试试看。

2.5 试试我们的npm包

  1. 先下载:
cnpm i star-evaluation -D

  1. 项目中引入使用:

运行后显示如下:

搞定,这是不是比之前那个toupper-case-project插件高端那么一丢丢?

 

那有的小伙伴可能会说了:“我平时看到的插件不是这么用的,很多都是直接Vue.use()后就可以用了,而且插件还有事件的。”

 

那我们再改改?

三、 升级包

其实能否使用Vue.use()这个方式来调用组件,取决于是否配置了install方法,我们给Star.vue组件加上看看:

3.1 配置install方法

// index.js
import Star from './Star.vue'; Star.install = Vue => Vue.component(Star.name, Star); // 给Star组件配置install方法,注册该组件 export default Star;

注:这里有个需要注意的地方,就是Star.name是指向我们给Star.vue文件中配置的name属性,别忘了配置它:

这时已经搞定了Vue.use()了,那我们再加上事件交互,就做个点击组件弹出具体的星级数值吧!

3.2 添加事件

具体修改如下:

<!-- 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' // 引入Vue
import 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给个星哈,这样我就可以放心的去搬砖了↓-↓

不会发布npm包?进来看看?的更多相关文章

  1. 创建并发布npm包

    1.npm官网创建npm账户 npm网站地址:https://www.npmjs.com/ npm网站注册地址:https://www.npmjs.com/signup 2.命令行工具登录npm np ...

  2. 使用cnpm搭建私有NPM仓库 发布npm包

    关于如何使用cnpm搭建私有的npm仓库看这里→ http://blog.fens.me/nodejs-cnpm-npm/ 我本人还没有机会真正实践操作过,公司的npm仓库是我老大搭建的,我这里仅仅记 ...

  3. 前端组件用 Scope 发布 npm 包的方法

    1.引言 多人.多组织或多组件发布 npm 包到同一个仓库时,可能出现命名冲突问题. 为了解决这个问题,npm 引入了“scope”(范围)概念. 在 Angular 项目中,我们通常可以看到“@an ...

  4. 使用Vue-cli3.0创建的项目,如何发布npm包

    使用Vue-cli3.0创建的项目,如何发布npm包 在使用vue进行项目开发时,如果我们想要发布一个包,有时候会有点迷糊,不知道应该怎么修改脚手架的默认设置.这里记录一下一些常见的操作. 创建ind ...

  5. node学习笔记8——发布npm包

    1.注册一个npm账号: 2.在控制台输入 npm login: 依次输入你的账号信息,可通过 npm whoami 来验证是否登录成功 3.初始化包,控制台输入 npm init: 完成之后,可以看 ...

  6. 用@vue/cli发布npm包

    1.环境准备 安装node,npm,@vue/cli 2.初始化项目 用@vue/cli创建新项目 vue create mtest-ui 删除public,main.js,App.vue等无关文件, ...

  7. 基于vue组件,发布npm包

    亲测好用,如出错,请留言 1.项目初始化 使用vue脚手架创建,但vuecli太重,我们使用简单的工程脚手架进行处理,输入命令 vue init webpack-simple my-project n ...

  8. 使用vuecli3发布npm包

    一.使用vuecli3创建项目 vue create svgicon 二.修改目录,开发组件前的准备 把src目录改为examples作为查看组件的演示目录,新建packages目录作为组件编写的目录 ...

  9. 开发并发布npm包,支持TypeScript提示,rollup构建打包

    前言: 工作了几年,想把一些不好找现成的库的常用方法整理一下,发布成npm包,方便使用.也学习一下开发发布流程. 主要用到的工具:npm. 开发库:babel.typescript.rollup.es ...

随机推荐

  1. 探索canvas画布绘制技术

    图片来自KrzysztofBanaś 下面我们开始尝试研究不同的绘图风格和技术 - 边缘平滑,贝塞尔曲线,墨水和粉笔,笔和印章和图案 -等等.事实证明,网上没有太多关于此的内容.在下面的示例中,您请大 ...

  2. webform 使用log4net配置

    效果: web.config配置 <configuration> <configSections> <!--log4net日志记录--> <section n ...

  3. (C# Window Service) Verify that you have sufficient privileges to start system services

    写了个Windows Service, 用Wix 写了个Installer,编译通过,生成了msi 安装文件,但是安装的时候总是提示: Product: KingPro Service -- Erro ...

  4. ArcGIS中的坐标系统定义与投影转换

    坐标系统是GIS数据重要的数学基础,用于表示地理要素.图像和观测结果的参照系统,坐标系统的定义能够保证地理数据在软件中正确的显示其位置.方向和距离,缺少坐标系统的GIS数据是不完善的,因此在ArcGI ...

  5. postman trigger xdebug session in phpstorm

    phpstorm是一款非常棒的php开发调试工具,一般情况下我们使用firefox/chrome的bookmark,开启phpstorm debug侦听,随后点击start debugger, 我们就 ...

  6. 连接到 Azure 上的 SQL Server 虚拟机(经典部署)

    概述 本主题介绍如何连接到运行于 Azure 虚拟机的 SQL Server 实例. 它介绍了一些常规连接方案,并提供了在 Azure VM 中配置 SQL Server 连接的详细步骤. Impor ...

  7. Java中执行.exe文件

    public static void main(String args[]){ try { String command ="notepad"; // 笔记本 Process ch ...

  8. where T : class泛型类型约束

    类型参数约束,.NET支持的类型参数约束有以下五种: where T : struct | T必须是一个结构类型where T : class T必须是一个类(class)类型where T : ne ...

  9. oracle 大表 已有大数据量 建索引防卡 nologging

    create index idx_th_user_info_fans_name on th_user_info(fans_name) nologging;

  10. Maximum Flow and Minimum Cut

    最大流最小割 Introduction Mincut Problem 最小割问题,输入是带权有向图,有一个源点 s(source)和一个汇点 t(target),边的权重在这里称作容量(capacit ...