環境初始化
mkdir npm-logcd npm-lognpm init -y
入口文件
-
自定義依賴模塊:
-
模塊是在
package.json裏通過main字段定義這個包對外暴露的入口;- 模塊起源於
node,語法默認支持commonjs規範 - 模塊若使用
ES Module語法書寫,通過module字段定義入口(需要打包工具配合使用)
- 模塊起源於
-
-
自定義命令行:
- 如果是提供命令行工具,則需要通過
pkg#bin字段來定義暴露的命令名稱與實際執行的文件
- 如果是提供命令行工具,則需要通過
這篇文章講述自定義依賴模塊的聲明,後續會有專門篇幅進行自定義命令行的講述。
聲明示例
-
創建
lib/index.jsconst 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"
開發環境
- [ ] 自動日誌
- [ ] 版本更新
-
huskynpm 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
-
-
-
commitlintcommitlint提交信息校驗工具- 需要和校驗規範配合使用,官網默認規範
@commitlint/config-conventional—— 可自定義。 -
commitlint綁定@commitlint/config-conventionalnpm i -D 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-versionnpm i --save-dev standard-version-
配置
run-script:發佈前自動升級版本號 + 生成日誌"prepublishOnly": "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源,需要切換到發佈的目標源。或者通過pkg#publishConfig、.npmrc指定目標源。
以npm為例:
-
切換到
npm源nrm use npm - 在NPM官網註冊賬號
-
命令行中登錄用户
npm login -
在項目目錄下發布包
npm publish
補充知識
-
[ ]
Peer DependenciesThe 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/...