自定义NPM包
Posted 米花儿团儿
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了自定义NPM包相关的知识,希望对你有一定的参考价值。
环境初始化
mkdir npm-log
cd npm-log
npm init -y
入口文件
自定义依赖模块和命令行的入口文件不同:
模块是在
package.json
里通过main
字段定义这个包对外暴露的入口;- 模块起源于
node
,语法默认支持commonjs
规范 - 模块若使用
ES Module
语法书写,通过module
字段定义入口
- 模块起源于
- 如果是提供命令行工具,则需要通过
bin
字段来定义暴露的命令名称与实际执行的文件
模块
创建
lib/index.js
const Noop = () => {} class Logmi { errorHandler = Noop successHandler = Noop static create (options) { return new Logmi(options) } constructor (options = {}) { console.log(\'---------create------\', options) } log (msg, level) { console.log(\'log: start\', msg, level) } } module.exports = Logmi
更新
package.json
"main": "lib/index.js"
命令行
- 最主要的是在
package.json
里通过main
字段定义这个包对外暴露的入口; - 如果是提供命令行工具,则需要通过
bin
字段来定义暴露的命令名称与实际执行的文件
开发环境
- [ ] 自动日志
- [ ] 版本更新
husky
npm install husky --save-dev npx husky install
配置
run-script
:安装依赖后自动启动Git hooks
"prepare": "husky install"
追加测试钩子
# Unix系统可用 npx husky add .husky/pre-commit "npm run test" # Windows通过以下命令创建文件(引号在windows下不是正确的语法) npx husky add .husky/pre-commit # Windows去新建的文件中指定命令 #!/bin/sh . "$(dirname "$0")/_/husky.sh" npm run test
commitlint
commitlint
提交信息校验工具- 需要和校验规范配合使用,官网默认规范
@commitlint/config-conventional
—— 可自定义。 commitlint
绑定@commitlint/config-conventional
# Unix echo "module.exports = {extends: [\'@commitlint/config-conventional\']}" > commitlint.config.js # Windows echo module.exports = {extends: [\'@commitlint/config-conventional\']} > commitlint.config.js
配置
Git hook
:在提交commit msg
进行参数校验 —— 写在run-script
中无效# Unix系统可用 npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1" # Windows通过以下命令创建文件(引号在windows下不是正确的语法) npx husky add .husky/commit-msg # Windows去新建的文件中指定命令 #!/bin/sh . "$(dirname "$0")/_/husky.sh" npx --no-install commitlint --edit $1
standard-version
npm i --save-dev standard-version
配置
run-script
:发布前自动升级版本号 + 生成日志"publish": "standard-version"
注意:这里不要使用
prepublish
钩子,该钩子在npm i
时运行,而不是npm publish
时运行。
调试
进入本地
NPM
包npm link
创建软链接到全局node
环境中
进入依赖包的项目A中
npm link <packageName>
建立软链接依赖
在项目A需要调用的文件中
# 调用 import Logmi from "log"; const LogmiInstance = Logmi.create({ url: \'http://localhost:3000\' }) LogmiInstance.log(`paste: ${JSON.stringify(paste)}`, 1)
- 启动项目A,即可调试
开发
NPM
包是commonJS
语法,使用require()
,而非import...from...
引入依赖。
实例化参数
- 工厂函数
参数默认值
const Noop = () => {}
:空语句
传参校验
- 参数数据实体类型
校验警告
- 参数合并
DTO
- 校验DTO组成结构参数
ParamChecker
- 统一结构
ContentWrapper
- 校验DTO组成结构参数
配置信息统一分类处理
module.exports = { EXCEED_TRY_TIMES: \'Exceed try times\', }
打包发布
打包需要引入webpack
,这里的package.json
修改入口文件:
"main": "dist/logmi.js",
"module": "lib/index.js",
其中,main
是暴露打包后的入口文件;module
是webpack
环境下暴露的入口文件;
package.json
{
"name": "log",
"version": "1.0.0",
"description": "",
"main": "dist/logmi.js",
"module": "lib/index.js",
"scripts": {
"prepare": "husky install",
"build": "cross-env NODE_ENV=production webpack --config webpack.config.js --mode=production",
"test": "echo \\"npm run test\\" && exit 1"
},
"author": "",
"license": "ISC",
"devDependencies": {
"@babel/core": "^7.14.3",
"@babel/preset-env": "^7.14.4",
"@commitlint/cli": "^12.1.4",
"@commitlint/config-conventional": "^12.1.4",
"babel-loader": "^8.2.2",
"cross-env": "^7.0.3",
"husky": "^6.0.0",
"standard-version": "^9.3.0",
"terser-webpack-plugin": "^5.1.3",
"webpack": "^5.38.1",
"webpack-cli": "^4.7.0"
},
"dependencies": {
"@babel/polyfill": "^7.12.1",
"idb-managed": "^1.0.9"
},
"bundledDependencies": [
"idb-managed"
]
}
pkg#main
作为第三方依赖包时,包的入口执行文件。
如果没有指定,默认为root
目录下的index.js
。
pkg#bin
作为命令行工具时,包的入口执行文件
安装该包时,node
会自动创建硬链接该包到全局执行环境。
String
:单执行文件Map
:多执行文件
pkg#module
非官方配置,rollup
、webpack
等打包工具提供的配置项。
指向的应该是一个基于ES6
模块规范书写的模块。
pkg#private
设置"private": true
,npm
拒绝发布该包。
pkg#workspaces
结合monorepo
的概念,创建工作区。
pkg#files
安装该包时,目录中包含在pkg.files
中指定的文件结构。
默认包含:
package.json
README
CHANGES / CHANGELOG / HISTORY
LICENSE / LICENCE
NOTICE
The file in the "main" field
pkg#bundledDependencies
通过fpt
、scp
等工具传输该包时,需要将该包的依赖打包在一起。
在
bundledDependencies
中指定依赖包的列表- 只需要指定包名,版本会在
dependencies
查找
- 只需要指定包名,版本会在
- 通过
npm pack
打包 - 通过传输工具传输打好的
*.tgz
包 - 通过
npm i *.tgz
安装该包及其依赖
Note: 定义在bundledDependencies
列表内的依赖,安装NPM包时,该依赖会嵌套在包文件下,而不会提升到node_modules
目录的根下
pkg#peerDependencies
表明该包对主包/主工具库的兼容性,而不是依赖性,这种关系称之为插件。
- 主包一般会对插件暴漏的接口指定标准
在peerDependencies
指定的包@版本号
表明,我们的包需要在指定包的环境下执行,需要一同安装。
打包
安装插件
npm i -D webpack-cli webpack cross-env terser-webpack-plugin
npm install --save-dev @babel/core babel-loader @babel/preset-env
npm install --save @babel/polyfill
配置babel.config.json
{
"presets": [
[
"@babel/env",
{
"targets": {
"edge": "17",
"firefox": "60",
"chrome": "67",
"safari": "11.1"
},
"useBuiltIns": "usage",
"corejs": "3.6.5"
}
]
]
}
配置run-script
...
"build": "cross-env NODE_ENV=production webpack --config webpack.config.js --mode=production",
...
webpack.config.js
const path = require(\'path\')
const webpack = require(\'webpack\')
const TerserPlugin = require("terser-webpack-plugin")
const resolve = dir => path.join(__dirname, \'.\', dir)
const isProd = process.env.NODE_ENV === \'production\'
module.exports = {
entry: {
logmi: \'./lib/index.js\'
},
output: {
path: resolve(\'dist\'), // 输出目录
filename: \'[name].js\', // 输出文件
libraryTarget: \'umd\', // 采用通用模块定义
library: \'logmi\', // 库名称
libraryExport: \'default\', // 兼容 ES6(ES2015) 的模块系统、CommonJS 和 AMD 模块规范
globalObject: \'this\' // 兼容node和浏览器运行,避免window is not undefined情况
},
devtool: \'source-map\',
module: {
rules: [
{
test: /\\.js$/,
exclude: /(node_modules)/,
use: {
loader: \'babel-loader\',
options: {
presets: [\'@babel/preset-env\']
}
}
}
]
},
optimization: {
minimize: true,
minimizer: [new TerserPlugin()],
}
}
配置可见目录结构
...
"files": [
"dist/"
]
...
发布
若使用nrm
维护多个npm
源,需要切换到发布的目标源。
以npm
为例:
切换到
npm
源nrm use npm
- 在NPM官网注册账号
命令行中登录用户
npm login
在项目目录下发布包
npm publish
补充知识
[ ]
Peer Dependencies
The peerDependencies configuration was originally designed to address the problem of NPM packages that were ‘plugins’ for other frameworks.
删除CHangeLog
- https://github.com/convention...
- https://lukasznojek.com/blog/...
以上是关于自定义NPM包的主要内容,如果未能解决你的问题,请参考以下文章