环境初始化

  1. mkdir npm-log
  2. cd npm-log
  3. npm init -y

入口文件

  • 自定义依赖模块和命令行的入口文件不同:

    • 模块是在 package.json 里通过 main 字段定义这个包对外裸露的入口;

      • 模块起源于node,语法默认反对commonjs标准
      • 模块若应用ES Module语法书写,通过 module 字段定义入口
    • 如果是提供命令行工具,则须要通过 bin 字段来定义裸露的命令名称与理论执行的文件

模块

  1. 创立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
  2. 更新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

      # Unixecho "module.exports = {extends: ['@commitlint/config-conventional']}" > commitlint.config.js# Windowsecho 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"

调试

  1. 进入本地NPM

    • npm link创立软链接到全局node环境中
  2. 进入依赖包的我的项目A中

    • npm link <packageName>建设软链接依赖
  3. 在我的项目A须要调用的文件中

    # 调用import Logmi from "log";const LogmiInstance = Logmi.create({ url: 'http://localhost:3000'})LogmiInstance.log(`paste: ${JSON.stringify(paste)}`, 1)
  4. 启动我的项目A,即可调试

开发

NPM包是commonJS语法,应用require(),而非import...from...引入依赖。

  • 实例化参数

    • 工厂函数
    • 参数默认值

      • const Noop = () => {}:空语句
    • 传参校验

      • 参数数据实体类型
      • 校验正告

        • 参数合并
  • DTO

    • 校验DTO组成构造参数ParamChecker
    • 对立构造ContentWrapper
  • 配置信息对立分类解决

    module.exports = {EXCEED_TRY_TIMES: 'Exceed try times',}

打包公布

打包须要引入webpack,这里的package.json批改入口文件:

"main": "dist/logmi.js","module": "lib/index.js",

其中,main是裸露打包后的入口文件;
modulewebpack环境下裸露的入口文件;

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

非官方配置rollupwebpack等打包工具提供的配置项。

指向的应该是一个基于ES6模块标准书写的模块。

pkg#private

设置"private": truenpm回绝公布该包。

pkg#workspaces

联合monorepo的概念,创立工作区。

pkg#files

装置该包时,目录中蕴含在pkg.files中指定的文件构造。

默认蕴含:

package.jsonREADMECHANGES / CHANGELOG / HISTORYLICENSE / LICENCENOTICEThe file in the "main" field

pkg#bundledDependencies

通过fptscp等工具传输该包时,须要将该包的依赖打包在一起。

  • bundledDependencies中指定依赖包的列表

    • 只须要指定包名,版本会在dependencies查找
  • 通过npm pack打包
  • 通过传输工具传输打好的*.tgz
  • 通过npm i *.tgz装置该包及其依赖

pkg#peerDependencies

  • 表明该包对主包/主工具库的兼容性,而不是依赖性,这种关系称之为插件。

    • 主包个别会对插件暴漏的接口指定规范

peerDependencies指定的包@版本号表明,咱们的包须要在指定包的环境下执行,须要一起装置。

打包

装置插件

npm i -D webpack-cli webpack cross-env terser-webpack-plugin
npm install --save-dev @babel/core babel-loader @babel/preset-envnpm 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/"  ]...

补充常识

  • [ ] 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/...