发布一个npm包,构建自己的第三方库
前言
小生在需要发布自己npm包时,见网上诸多教程,皆无法满足所思需求;不是太简单,就是缺三少四,故前往各大厂商之GitHub,耐心翻阅其源码,始有心得;特此做博客以记,与诸君共勉。
如果你需要进行快速搭建自己的第三方库,请移步:npm-plugins-building-shell 或者 借用shell,快速搭建一个npm插件库。
申请一个npm 账号 以及创建好相关 github 项目
前往申请 npm 账号: https://www.npmjs.com/
此处本人创建的 github 项目名字为my-npm-libs,你需要另外重新起个名字。
本地创建 npm 项目
我们需要创建自己npm项目。
mkdir my-npm-libs # 创建文件夹,注意此处的名字和你上面创建的GitHub项目名称保持一致
cd my-npm-libs # 进入文件
# 此处使用 -y 可以跳过后面让你填写内容操作,所有内容都是用默认值就好,有需要的话回头可以在package.json 文件中进行修改
npm init -y # 默认配置
这里我们选择的是默认配置npm init -y
,如果,你需要进行更详细的配置请使用:
npm init
使用npm init
的结果如图:
查看npm init文档,以查看更多详细内容。
npm 项目目录
mkdir examples lib src test # 创建所需目录
touch .babelrc .gitignore README.md # 创建所需文件
touch examples/index.html src/index.js test/index.js
目录如下:
.
├── examples/ // 目录: 放置案例文件
│ ├── index.html // 文件: 案例运行结果
├── lib/ // 目录: 放置 script 引用的文件
├── src/ // 目录: 库目录
│ ├── index.js // 文件: 库内容
├── test/ // 目录: 放置单元测试文件
│ ├── index.js // 文件: 测试内容
.babelrc
.gitignore
package.json
README.md
相关配置(请按照顺序进行配置)
src/index.js 库内容
我们的包需要支持如下三种引用方式:
import引用
import ... from '...'
require引用
const ... = require('...')
标签引用
此处我们使用自己写的,获取数据类型的方法:
// 获取数据类型
(function (root, globalName, factory) {
if (typeof define === 'function' && define.amd) {
// AMD:
define([], factory);
} else if (typeof module === 'object' && module.exports) {
// Node:
module.exports = factory();
// Use module export as simulated ES6 default export:(将模块导出用作模拟ES6默认导出)
module.exports.default = module.exports;
} else {
// Browser:
window[globalName] = factory();
}
}(this, 'dataType', function () {
'use strict';
return function dataType (data) {
return ({}).toString.call(data).match(/\s([a-zA-Z]+)/)[1].toLowerCase();
}
}));
babel配置
由于,目前绝大部分的浏览器只支持ES5,故此我们需要把ES5以上的语法�转换为ES5,我们需要引用babel。不了解babel的请移步babel 官网。
如果你不需要进行语法转换则跳过此babel配置步骤。
我们需要配置babel,这里由于babel的更新babel的配置基本分为两类:
1.babel6.X
以及其以下版本
2.babel7.X
以及其以上版本
babel6.X以及其以下版本的配置
安装 Babel 命令行工具(babel-cli
)以及一种 Babel preset
:
npm install --save-dev babel-cli babel-preset-env
创建一个 .babelrc
文件(或者使用你的 package.json
文件):我们上面已经创建过了的话,此处不必再进行创建。
{
"presets": ["env"]
}
由于 Babel 只进行语法转换(如箭头函数),你可以使用 babel-polyfill
来支持新的全局变量,如 Promise
或新的原生方法,如 String.padStart(left-pad)
。它使用了 core-js
和 regenerator
。
安装 babel-polyfill
:
npm install --save-dev babel-polyfill
运行此命令将所有代码从 src
目录编译到 lib
:
./node_modules/.bin/babel src --out-dir lib
babel7.X以及其以上版本的配置
安装 Babel 命令行工具(@babel/cli
)、Babel核心以及一种 @babel preset
:
npm install --save-dev @babel/core @babel/cli @babel/preset-env
在项目的根目录中创建名为 babel.config.js
的配置文件:
const presets = [
["@babel/env", {
targets: {
edge: "17",
firefox: "60",
chrome: "67",
safari: "11.1"
},
useBuiltIns: "usage"
}]
]; // 上面的浏览器列表只是用于展示的示例。你必须根据想要支持的浏览器进行调整。
@babel/polyfill
模块包括 core-js
和自定义 regenerator runtime
来模拟完整的 ES2015+
环境。
这意味着你可以使用像 Promise
或 WeakMap
这样的新内置函数,像 Array.from
或 Object.assign
这样的静态方法,像 Array.prototype.includes
这样的实例方法,以及 generator
函数(提供给你使用 regenerator
插件)。
安装@babel/polyfill
:
npm install --save @babel/polyfill
运行此命令将所有代码从 src
目录编译到 lib
:
./node_modules/.bin/babel src --out-dir lib
.gitignore的配置
.DS_Store
node_modules/
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Editor directories and files
.idea
.vscode
*.suo
*.ntvs*
*.njsproj
*.sln
package.json的配置
{
"name": "my-npm-libs",
"description": "发布一个npm包,构建自己的第三方库",
"version": "1.0.1",
"author": "nongshuqiner ",
"license": "MIT",
"main": "src/index.js",
"files": [
"examples",
"lib",
"src",
"test"
],
"private": false,
"scripts": {
"test": "mocha --recursive",
"examples": "open ./examples/index.html",
"build": "./node_modules/.bin/babel src --out-dir lib"
},
"keywords": [
"my-npm-libs"
],
"homepage": "https://github.com/nongshuqiner/my-npm-libs.git",
"repository": {
"type": "git",
"url": "git+https://github.com/nongshuqiner/my-npm-libs.git"
},
"devDependencies": {
"babel-cli": "^6.26.0",
"babel-polyfill": "^6.26.0",
"babel-preset-env": "^1.7.0",
"chai": "^4.2.0",
"mocha": "^5.2.0"
}
}
examples/index.html的配置
在配置 examples/index.html
前需要运行如下命令:
./node_modules/.bin/babel src --out-dir lib
# 或者,由于我们在 package.json 中,已经配置了,故此也可以使用下面这个命令构建
npm run build
examples/index.html的内容:
my-npm-libs
var a = [1, 2, 3, 4, 1, 5, 1, 7],a的数据类型是什么?
我们可以通过如下命令进行案例查看:
npm run examples
README.md的配置
# XXX(组件名)
## 概述
...
## Install(安装)
npm install --save ...
## Usage(使用)
...
... 其他内容 ...
## Donation
...
## Contact me(联系我)
...
## License
[MIT](http://opensource.org/licenses/MIT) Copyright (c) 2018 - forever Naufal Rabbani
test 单元测试
至于单元测试你可以另外请自行选择相关库进行测试,也可以按照我的习惯进行测试。
在测试前你需要了解一下mocha,chai这两个库,这里放上教程你可以看看:测试框架 Mocha 实例教程
安装 mocha
和 chai
:
npm install --save-dev mocha chai
test/index.js:
// 断言库 chai.js
var expect = require('chai').expect;
var dataType = require('../src/index');
// 测试脚本里面应该包括一个或多个describe块,称为测试套件(test suite)
describe('基本数据类型', function () {
// 每个describe块应该包括一个或多个it块,称为测试用例(test case)
// 基本数据类型
it('undefined-类型检测测试', () => {
// 断言
expect(dataType(undefined)).to.equal('undefined');
});
it('null-类型检测测试', () => {
expect(dataType(null)).to.equal('null');
});
it('string-类型检测测试', () => {
expect(dataType('abc')).to.equal('string');
});
it('boolean-类型检测测试', () => {
expect(dataType(true)).to.equal('boolean');
});
it('number-类型检测测试', () => {
expect(dataType(1)).to.equal('number');
});
});
describe('引用数据类型', function () {
it('array-类型检测测试', () => {
expect(dataType([1])).to.equal('array');
});
it('object-类型检测测试', () => {
expect(dataType({})).to.equal('object');
});
it('function-类型检测测试', () => {
expect(dataType(function () {})).to.equal('function');
});
});
describe('其他数据类型', function () {
it('date-类型检测测试', () => {
expect(dataType(new Date())).to.equal('date');
});
it('regex-类型检测测试', () => {
expect(dataType(new RegExp("\\w+"))).to.equal('regexp');
});
});
通过命令行测试:
npm run test
结果如下:
$ npm run test
> [email protected] test /Users/yanmo/Public/mynpm/my-npm-libs
> mocha --recursive
基本数据类型
✓ undefined-类型检测测试
✓ null-类型检测测试
✓ string-类型检测测试
✓ boolean-类型检测测试
✓ number-类型检测测试
引用数据类型
✓ array-类型检测测试
✓ object-类型检测测试
✓ function-类型检测测试
其他数据类型
✓ date-类型检测测试
✓ regex-类型检测测试
10 passing (12ms)
至此一个基本的简单的npm第三方库构建完成。下面我们进行其他的发布工作。
发布 npm 包
进入项目根目录,登录刚刚申请的npm 账号。登录完成以后执行提交。
npm login # 登陆
npm publish # 发布
发布npm包的时候需要注意把npm仓库镜像库,从国内的淘宝源切换到npm国外源,不然无法提交。
这里我做了一个shell
文件,用以简化你的提交操作,你在根目录下新建一个文件npm-publish.sh
,内容如下:
#!/usr/bin/env bash
echo "\033[0;32m?\033[0m \033[36m请输入你的新发布的版本号(ex:1.0.0):\033[0m"
read version
# 处理 package.json
sed -i -e "s/\"version\": \(.*\)/\"version\": \"$version\",/g" 'package.json'
if [ -f "package.json-e" ];then
rm 'package.json-e'
fi
echo '\033[36m版本号修改成功\033[0m'
npm config get registry # 检查仓库镜像库
npm config set registry=http://registry.npmjs.org # 设置仓库镜像库: 淘宝镜像https://registry.npm.taobao.org
echo '\033[36m请进行登录相关操作:\033[0m'
npm login # 登陆
echo "-------\033[36mpublishing\033[0m-------"
npm publish # 发布
npm config set registry=https://registry.npm.taobao.org # 设置为淘宝镜像
echo "\033[36m 完成 \033[0m"
exit
然后,可以通过如下命令运行:
sh npm-publish.sh
执行效果如图:
当你的npm包发布后,可以通过如下格式的内容访问到你的包:
unpkg.com/:package@:version/:file
访问结果如图:
这也意味着你可以通过标签的形式访问你的包,我猜你需要了解:UNPKG。
git提交
git init
git add -A
git commit -m "first commit"
git remote add origin XXX
git push -u origin master
Usage(使用)
发布成功后就可以使用了。使用有两种形式,一种是 npm
安装,一种是 引用。
npm 安装:
npm install --save my-npm-libs
import myNpmLibs from 'my-npm-libs'
var a = [1, 2, 3, 4, 1, 5, 1, 7]
console.log(myNpmLibs(a)) // array
// 或者
const myNpmLibs = require('my-npm-libs')
var a = [1, 2, 3, 4, 1, 5, 1, 7]
console.log(myNpmLibs(a)) // array
使用
run(运行)
# git clone ...
git clone https://github.com/nongshuqiner/my-npm-libs.git
# enter
cd my-npm-libs
# install dependencies
npm install
# open examples HTML
npm run examples
# 运行此命令将所有代码从 src 目录编译到 lib
npm run build
# 测试
npm run test
Donation(打赏)
Contact me(联系我)
Just Contact Me At:
- Email: [email protected]
- : 言墨儿
结语
至此,我们发布的包的工作就彻底完成了。
我参考学习了很多的其他的第三方库以及工具网站,这里放上一些链接供大家参考:
unpkg
b64-to-blob
The anatomy of a vanilla JavaScript plugin
如何定义一个高逼格的原生JS插件
How to write and build JS libraries in 2018
Building Your Own JavaScript Modal Plugin
How to write a frontend JavaScript plugin using ES6 + SASS + Webpack
在发布之前可以将这整个目录扔到另一个项目的
node_modules
文件夹中来测试我们写的功能是否正确。
提示:后面还有精彩敬请期待,请大家关注我的专题:web前端。如有意见可以进行评论,每一条评论我都会认真对待。觉得有用却不点赞的,隔壁老X送来问候。