教你开源一个优雅的npm包

一、注册npm账号

前往https://www.npmjs.com注册一个账号。

npmjs

二、制作npm包

1.建立一个仓库,这里以cat-jsutils为例
cat-jsutils

这里需要注意下名称,因为如果被占用,无法使用npm install直接安装。
判断是否被占用,可使用npm search xxx来判断

未占用

cenghaihandeMacBook-Pro:cat-jsutils catchzeng$ npm search cat-jsutils
No matches found for "cat-jsutils"

已占用

cenghaihandeMacBook-Pro:cat-jsutils catchzeng$ npm search jsutils
NAME                      | DESCRIPTION          | AUTHOR          | DATE       | VERSION  | KEYWORDS
jsutils                   | Utilities for…       | =sethyuan       | 2016-04-25 | 0.6.1    | util js javascript node.js node nodejs utils u
fwsp-jsutils              | JavaScript Utils -…  | =emadum =cjus   | 2017-04-04 | 1.0.10   | flywheelsports javascript utils
@mreck/jsutils            | JavaScript…          | =mreck          | 2018-04-14 | 2.0.0    |
sbiger-jsutil             | Javascript common…   | =sbiger         | 2016-12-26 | 1.3.32   | javscript utilities ES6 ES5 js util
m-jsutils                 | js utils             | =limi58         | 2017-07-23 | 1.0.1    | utils
jsutilities               | Javascript common…   | =jcde           | 2016-07-08 | 1.0.6    |
jsutils2                  | "Various utility…    | =milesman34     | 2017-11-22 | 2.0.0    |
org.mineot.jsutil         | Javascript Util…     | =mineot         | 2018-01-26 | 0.0.5    | javascript js jsutil util i18next translation
h-jsutils                 | javascript utils     | =haven09        | 2018-01-11 | 1.0.0    | js javascript utils
jsutility                 | A collection of…     | =deepaksibar    | 2016-08-27 | 0.0.0    | css
jsutil                    | A utilities package… | =gm12306        | 2013-03-20 | 0.1.3    | util mixin extend
@ikyhdst/jsutils          | Utility files for…   | =ikyhdst        | 2018-01-17 | 0.0.1    |
rb-jsutils                |                      | =dhanna         | 2016-06-29 | 0.9.0    |
@moodxd/jsutil-openable   | JavaScript Utility…  | =moodxd         | 2017-03-08 | 1.0.3    |
@moodxd/jsutil-stickable  | JavaScript Utility…  | =moodxd         | 2017-03-08 | 1.0.3    |
2.Clone仓库到本地 & cd到cat-jsutils,执行npm init
cenghaihandeMacBook-Pro:Github catchzeng$ cd cat-jsutils/
cenghaihandeMacBook-Pro:cat-jsutils catchzeng$ npm init
This utility will walk you through creating a package.json file.
It only covers the most common items, and tries to guess sensible defaults.

See `npm help json` for definitive documentation on these fields
and exactly what they do.

Use `npm install <pkg>` afterwards to install a package and
save it as a dependency in the package.json file.

Press ^C at any time to quit.
package name: (cat-jsutils)
version: (1.0.0)
description: js utils
entry point: (index.js)
test command:
git repository: (https://github.com/CatchZeng/cat-jsutils)
keywords: util utils js javascript node utility utilities
author: CatchZeng
license: (ISC) MIT
About to write to /Users/catchzeng/Documents/Code/Github/cat-jsutils/package.json:

{
  "name": "cat-jsutils",
  "version": "1.0.0",
  "description": "js utils",
  "main": "index.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/CatchZeng/cat-jsutils.git"
  },
  "keywords": [
    "util",
    "utils",
    "js",
    "javascript",
    "node",
    "utility",
    "utilities"
  ],
  "author": "CatchZeng",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/CatchZeng/cat-jsutils/issues"
  },
  "homepage": "https://github.com/CatchZeng/cat-jsutils#readme"
}
3.新建index.js【根据上一步的entry point: (index.js)指定】,组织代码结构,这里以cat-jsutils为例
屏幕快照 2018-04-17 下午6.13.24.png
//number.js

function isNum(value) {
    return (typeof value === 'number') && !isNaN(parseFloat(value)) && isFinite(value); 
}

module.exports = {
    isNum,
}
//string.js

function isString(value) {
    return typeof value === 'string' || value instanceof String;
}
...
...
module.exports = {
    isString,
    contains,
    containsAny,
    containsAll,
};
//index.js
var utils = {};

utils.string = require('./src/string');
utils.number = require('./src/number');

module.exports = utils;
4.在package.json中指定版本号,并提交代码到github上
{
  "name": "cat-jsutils",
  "version": "1.0.1",
  "description": "js utils",
  "main": "index.js",
  ...
}

三、发布npm包

到项目跟目录下,执行publish命令

cenghaihandeMacBook-Pro:cat-jsutils catchzeng$ npm publish
+ cat-jsutils@1.0.1
cenghaihandeMacBook-Pro:cat-jsutils catchzeng$

发布成功后就可以在https://www.npmjs.com上看到自己的项目

四、更新版本

更新package.json中的版本号,并提交代码到github上,重新publish npm包即可

{
  "name": "cat-jsutils",
  "version": "1.0.2",
  "description": "js utils",
  "main": "index.js",
  ...
}
cenghaihandeMacBook-Pro:cat-jsutils catchzeng$ npm publish
+ cat-jsutils@1.0.2
cenghaihandeMacBook-Pro:cat-jsutils catchzeng$

五、变优雅

何为优雅,先看下express这个仓库比我们自己的仓库优雅在哪里

express

1.Logo

这么吗,我不是设计师,有美感的朋友自己设计一个吧,这里我随便做一个了。

logo

2.npm version badge

npm

增加这个其实只要在README中增加

[![NPM version](https://img.shields.io/npm/v/仓库名.svg)](https://www.npmjs.com/package/仓库名)

以cat-jsutils为例子

[![NPM version](https://img.shields.io/npm/v/cat-jsutils.svg)](https://www.npmjs.com/package/cat-jsutils)

3.CI状态

关于持续集成理论部分,可以看之前的文章持续集成 -- 理论篇。一般开源项目会选用travis-ci

CI

使用github账号登录travis-ci,然后打开需要持续集成的项目


travis-ci

在项目中增加.travis.yml文件,用于配置持续集成的构建步骤。这里以cat-jsutils为例,里面只执行了单元测试

language: node_js
node_js:
- stable
script: npm run test

说明:cat-jsutils的测试使用的是mocha+chai+istanbul,详见package.json

{
  "name": "cat-jsutils",
  "version": "1.0.1",
  "description": "js utils",
  "main": "index.js",
  "scripts": {
    "test": "mocha",
    "coverage": "istanbul cover _mocha -- -R spec --timeout 5000 --recursive",
    "coverage:check": "istanbul check-coverage"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/CatchZeng/cat-jsutils.git"
  },
  "keywords": [
    "util",
    "utils",
    "js",
    "javascript",
    "node",
    "utility",
    "utilities"
  ],
  "author": "CatchZeng",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/CatchZeng/cat-jsutils/issues"
  },
  "homepage": "https://github.com/CatchZeng/cat-jsutils#readme",
  "devDependencies": {
    "chai": "^4.1.2",
    "istanbul": "^0.4.5",
    "mocha": "^5.1.0"
  }
}

提交.travis.yml后变会触发构建,可以到travis-ci查看构建过程。

travis-ci
屏幕快照 2018-04-17 下午8.12.34.png

点击构建成功的图标就会弹出地址


屏幕快照 2018-04-17 下午8.15.35.png

将该地址放到README上即可。以cat-jsutils为例子

[![travis ci](https://api.travis-ci.org/CatchZeng/cat-jsutils.svg?branch=master)](https://travis-ci.org/CatchZeng/cat-jsutils)

4.测试覆盖率

显示测试覆盖率,我们需要借助coveralls
同样的使用github账户登录coveralls,然后开启对应的项目

coveralls

点击details,查看repo_token并复制,后面会使用到。


屏幕快照 2018-04-17 下午8.23.38.png

安装coveralls

npm i coveralls -D

安装travis

gem install travis

执行encrypt,COVERALLS_TOKEN就是刚才复制的repo_token

travis encrypt COVERALLS_TOKEN=JGOXXXXXXXXXXXXXqKVJ --add

执行之后会发现.travis.yml下多出env,这个环境变量能帮助我们将测试覆盖率安全上传到coveralls

env:
  global:
  - secure: nHaHZZDNmW3Fx3YPvBEc2E0a0kjsVhKUssi4GpWYcFDiJe6ufHAVjukHnV4RQOlSgRgp1q+5v9KJFeQbkcR9vSNQhtkjzHW//AbNGIOCZFyvmb3j/FH1hFxGqK129IC9tDHn1JeRSr5qSKK+TFTwINWQHCGAdA32PY+swuNT30UGrhBHtw3UaN8Hgu9xRH8g8UpqAMcGyX0rCnYCzPD2gYBEOo3zqEQvNvttu2YeSxvBXpU8doJuZLu7yvrRhvD3DGg3r/BWX7UDZtX16gZCdw3N9EnMWqgdaos7blE3eSKeHj89OHhiXeRSqHN7RKyUAp9dDmW1M63onsNvEpoho4ULCVTiVvX+Y25c+gZML3boeBlm3KOdwYKOCKhQLj/DIY5ojQd33jFBdBoouWW5ZG2cpfg8iq/Jyg2OoJFvJRjG04/T85a+l89wMnZKMDDl8zRgsnDhZho69EQmTz9WeBCvL2Bg87+n2Mg909InEw1D1PskGPkyD02zR7newOU+gJM2zK3pUYxt6O4EHUukoYL9XS14ogYIsrYFWqls0BHnTQXWKf+DQckL+H4+nZxdEPF6fEaebI8jgH9pgQiCHqMAKaQNsLApZRQ58DXLv78nZ/Sd/e/WmEgPfXZcrhTiLC8/yistVy3N5EKYHCjg6sB5RMO4BRNAsq0rnR3v1rA=

加入cover脚本

"cover": "istanbul cover --report lcov node_modules/mocha/bin/_mocha -- -R spec test/*.js"

看下最后的.travis.yml文件和 package.json

language: node_js
node_js:
- stable
script: npm run test
after_script: npm run cover && cat coverage/lcov.info | node_modules/coveralls/bin/coveralls.js
env:
  global:
  - secure: nHaHZZDNmW3Fx3YPvBEc2E0a0kjsVhKUssi4GpWYcFDiJe6ufHAVjukHnV4RQOlSgRgp1q+5v9KJFeQbkcR9vSNQhtkjzHW//AbNGIOCZFyvmb3j/FH1hFxGqK129IC9tDHn1JeRSr5qSKK+TFTwINWQHCGAdA32PY+swuNT30UGrhBHtw3UaN8Hgu9xRH8g8UpqAMcGyX0rCnYCzPD2gYBEOo3zqEQvNvttu2YeSxvBXpU8doJuZLu7yvrRhvD3DGg3r/BWX7UDZtX16gZCdw3N9EnMWqgdaos7blE3eSKeHj89OHhiXeRSqHN7RKyUAp9dDmW1M63onsNvEpoho4ULCVTiVvX+Y25c+gZML3boeBlm3KOdwYKOCKhQLj/DIY5ojQd33jFBdBoouWW5ZG2cpfg8iq/Jyg2OoJFvJRjG04/T85a+l89wMnZKMDDl8zRgsnDhZho69EQmTz9WeBCvL2Bg87+n2Mg909InEw1D1PskGPkyD02zR7newOU+gJM2zK3pUYxt6O4EHUukoYL9XS14ogYIsrYFWqls0BHnTQXWKf+DQckL+H4+nZxdEPF6fEaebI8jgH9pgQiCHqMAKaQNsLApZRQ58DXLv78nZ/Sd/e/WmEgPfXZcrhTiLC8/yistVy3N5EKYHCjg6sB5RMO4BRNAsq0rnR3v1rA=
{
  "name": "cat-jsutils",
  "version": "1.0.1",
  "description": "js utils",
  "main": "index.js",
  "scripts": {
    "test": "mocha",
    "coverage": "istanbul cover _mocha -- -R spec --timeout 5000 --recursive",
    "coverage:check": "istanbul check-coverage",
    "cover": "istanbul cover --report lcov node_modules/mocha/bin/_mocha -- -R spec test/*.js"
  },
  "repository": {
    "type": "git",
    "url": "git+https://github.com/CatchZeng/cat-jsutils.git"
  },
  "keywords": [
    "util",
    "utils",
    "js",
    "javascript",
    "node",
    "utility",
    "utilities"
  ],
  "author": "CatchZeng",
  "license": "MIT",
  "bugs": {
    "url": "https://github.com/CatchZeng/cat-jsutils/issues"
  },
  "homepage": "https://github.com/CatchZeng/cat-jsutils#readme",
  "devDependencies": {
    "chai": "^4.1.2",
    "coveralls": "^3.0.0",
    "istanbul": "^0.4.5",
    "mocha": "^5.1.0"
  }
}

5.小结

至此,我们完成了提交代码-》travis-》mocha单元测试-》istanbul覆盖率-》coveralls-》github显示npm版本、ci、覆盖率状态。

6.README

完善的README会让开源变得更加优雅。
加入Installation、Usgae、API等描述能帮助使用者更会上手,详细请参考README.md

六、总结

本文从npm包的制作、发布到优化,讲述了如何较好地开源npm包,当然还有需要不足。欢迎感兴趣的朋友一起讨论、优化。
最后附上测试项目地址: http://github.com/CatchZeng/cat-jsutils

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