初学案例之用npm发布一个包

现在基本上不了解npm的前端都不能成为一个合格前端开发,在平时都是使用别人写好的npm包,突然想去了解下具体如何去制作一个npm包
这篇文章就是记录自己如何尝试去制作一个npm包并将它发布出去的流程。

一、首先要有一个需求~

前一段时间正好写到一个小的demo工具。

需求是这样的:
项目越来越大的情况下,使用fis每次编译的时间比较长,需要将编译过程改成增量编译,让每次编译都是去编译变化的活动。由于编译工作是fis完成的,最终需要我做的去实现只是一个获取发生变化的文件的工具方法。

在要做这个小工具之后,我们就可以把它做成一个简单npm包,来实现下npm的发布过程

先展示下需求的具体实现

思路是:既然要获取发生变化的文件夹,那么一定要知道原先文件夹合集,和当前文件夹合集,并比较下他们的md5值就可以判断出发生变化的文件夹,筛选出来其中发生变化的传递给编译工具就完成啦

// 需要用的npm包
import fs from 'fs'
import glob from 'glob'
import dirsum from 'dirsum'

/**
 * 文件夹路径 --> 文件夹md5
 * @param {String} dirPath 文件夹路径
 * @return {Promise} 
 */
function dirsum_md5 (dirPath) {
    return new Promise(function (resolve, reject) {
        dirsum.digest(dirPath, 'md5', function (err, hashes) {
            resolve(err ? '' : hashes.hash)
        })
    })
}

/**
 * 获取glob锚点路径 对应的 文件夹对象合集
 * @param {String} anchor 锚点文件的glob路径
 * @return {Array} 文件夹对象的合集
 */
export function toGetProjectDirs (anchor = 'src/**/build.this'){
    // 锚点文件的文件名
    let anchor_file_name = anchor.split('/').slice(-1);
    return Promise.all(glob.sync(anchor).map(async function (projectFile) {
        // 锚点文件 --> 文件夹路径
        let path = projectFile.match('^(.*?)'+anchor_file_name)[1]
        // 文件夹路径 --> 文件夹md5
        let md5 = await dirsum_md5(path)
        // 封装成对象
        return {path,md5}
    }))
}

/**
 * 比较文件夹变化
 * @param {Array} preDirs 旧文件夹对象的合集
 * @param {Array} nowDirs 新文件夹对象的合集
 * @return {Array} 注意:返回的是新文件夹数组的子集
 */
export function toCompareChange (preDirs,nowDirs){
    return nowDirs.filter(function(nowDir){
        let dirs = preDirs.filter(function(preDir){
            return preDir.path === nowDir.path
        })
        return nowDir.md5 !== (dirs.length > 0 ? dirs[0].md5 : '')
    })
}

有了上面的代码就可以实现当前需求,接下来要做的是把上面的代码发布出去,让其他人都可以使用

二、然后一些准备工作

想要发布npm,首先要有一个npm账号

因为你的包是要放在npm上的,所以,没有npm的账号,根本什么活都干不了。
在npm上注册一个账号是很简单的,随便填一下用户名密码邮箱,然后人家就会发个邮件给你,然后就注册成功了。

然后你就可以使用npm publish来发布npm包了,当然首次发布的时候要登录。

输入完用户名,密码,邮箱后没有错误信息就完成了。

$ npm adduser
Username: your name
Password: your password
Email: (this IS public) your email

查询或者登陆别的用户命令

$ npm whoami
$ npm login

npm init

创建一个文件夹,进入之后执行npm init,之后这个文件夹就是你要发布工具的文件夹了。

然后把刚才写好的代码放到文件夹中,这样基本的准备工作就做好了

记得npm install使用到的包

还有就是记得写README.md文件,要不然别人根本不知道你的工具是干什么的和如何去使用。

三、开始发布啦

打包代码

发布的要先对代码进行打包一下,当然你也可以忽略这一步,直接将代码发布出去。
但是!!现在的前端模块规范是越来越多了,所以如果不对自己的代码进行处理的话,别人那道基本是用不了的。

对于npm包的打包,这里推荐使用rollup

理由吗,就是简单、高效、全面。

举个简单的rollup配置文件的例子,执行rollup -c就可以实现编译。

export default {
    input: 'src/index.js',
    plugins: [ 
      
    resolve({
        jsnext: true,  // 该属性是指定将Node包转换为ES2015模块
        // main 和 browser 属性将使插件决定将那些文件应用到bundle中
        main: true,  // Default: true 
        browser: true // Default: false
    }),
    commonjs({
    }),
    json(),
    babel({
        exclude: 'node_modules/**',  // 排除node_modules 下的文件
        runtimeHelpers: true
    }),
    // replace({
    //     include: 'src/index.js', // 指定可以使用变量的文件路径
    //     exclude: 'node_modules/**',
    //     ENV: JSON.stringify(process.env.NODE_ENV || 'development'),
    //     HOST: JSON.stringify('http://111/111')
    // })
   ],
    output: [{
      file: 'dist/index.js',
      name:'SongPackage',
      format: 'umd'
    },{
      file: 'dist/index.es.js',
      format: 'es'
    },{
      file: 'dist/index.amd.js',
      format: 'amd'
    },{
      file: 'dist/index.cjs.js',
      format: 'cjs'
    }]
};

这样就会把常用的模块规范都编译出来了

下面我们看下各个模块规范编译出来的效果是

// 假设源文件代码
export default {};
// AMD
define(function () { 'use strict';
  var index = {};
  return index;
});
// CommonJS
'use strict';
var index = {};
module.exports = index;
// ES 
var index = {};
export default index;
// UMD 通用
(function (global, factory) {
    typeof exports === 'object' && typeof module !== 'undefined' ? module.exports = factory() :
    typeof define === 'function' && define.amd ? define(factory) :
    (global.SongPackage = factory());
}(this, (function () { 'use strict';
var index = {};
return index;
})));

默认可以设置指向UMD,用户也可以根据自己的项目选择其他的引入。

终于进入要发布了

module开发完毕后,剩下的就是发布啦,进入项目根目录,输入命令。

首先要设置一个版本号

npm社区版本号规则采用的是semver(语义化版本),主要规则版本格式:主版本号.次版本号.修订号,版本号递增规则如下:

  • 主版本号:当你做了不兼容的 API 修改,
  • 次版本号:当你做了向下兼容的功能性新增,
  • 修订号:当你做了向下兼容的问题修正。
    先行版本号及版本编译信息可以加到“主版本号.次版本号.修订号”的后面,作为延伸。
$ npm publish

这里有时候会遇到几个问题

问题1:

npm ERR! no_perms Private mode enable, only admin can publish this module:

这里注意的是因为国内网络问题,许多小伙伴把npm的镜像代理到淘宝或者别的地方了,这里要设置回原来的镜像。

$ npm config set registry=http://registry.npmjs.org

问题2:

npm ERR! you do not have permission to publish "your module name". Are you logged in as the correct user?

提示没有权限,其实就是你的module名npm上已经被占用啦,这时候你就去需要去npm搜索你的模块名称,如果搜索不到,就可以用,并且把package.json里的name修改过来,重新npm publish,看到如下信息就表示安装完成了,songpackage就是我的模块名。

+ songpackage@0.1.0

更新版本,发布

$ npm version 0.1.1
$ npm publish
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 170,566评论 25 707
  • 1、npm是什么? NPM (node package manager),通常称为node包管理器。顾名思义,它的...
    徐国军_plus阅读 6,977评论 1 6
  • 什么是 NPM npm之于Node,就像pip之于Python,gem之于Ruby,composer之于PHP。 ...
    ihoey阅读 6,203评论 2 36
  • 我是那种一上车就准备睡觉度过的人,但现在一点也睡不着。 小时候晕车的很严重,长大后却因为种种无可奈何需要坐车,便开...
    条形码0908阅读 254评论 0 0
  • 站在路上,看人来人往,那些从旁穿梭而过的身影,是那样匆忙,想从茫茫人海,找寻你的身影,打马而过的那些人,仿佛是你的...
    fk3ifcod阅读 99评论 0 0