自定義NPM包

環境初始化

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

入口文件

  • 自定義依賴模塊和命令行的入口文件不一樣:node

    • 模塊是在 package.json 裏經過 main 字段定義這個包對外暴露的入口;webpack

      • 模塊起源於node,語法默認支持commonjs規範
      • 模塊若使用ES Module語法書寫,經過 module 字段定義入口
    • 若是是提供命令行工具,則須要經過 bin 字段來定義暴露的命令名稱與實際執行的文件

模塊

  1. 建立lib/index.jsgit

    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.jsongithub

    "main": "lib/index.js"

命令行

  • 最主要的是在 package.json 裏經過 main 字段定義這個包對外暴露的入口;
  • 若是是提供命令行工具,則須要經過 bin 字段來定義暴露的命令名稱與實際執行的文件

開發環境

  • [ ] 自動日誌
  • [ ] 版本更新
  • huskyweb

    npm install husky --save-dev
     npx husky install
    • 配置run-script:安裝依賴後自動啓動Git hookschrome

      "prepare": "husky install"
      • 追加測試鉤子npm

        # 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
  • commitlintjson

    • commitlint提交信息校驗工具
    • 須要和校驗規範配合使用,官網默認規範@commitlint/config-conventional —— 可自定義。
    • commitlint綁定@commitlint/config-conventionalwindows

      # 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"

調試

  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.json
README
CHANGES / CHANGELOG / HISTORY
LICENSE / LICENCE
NOTICE
The 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-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/"
  ]
...

補充知識

  • [ ] Peer Dependencies

    The peerDependencies configuration was originally designed to address the problem of NPM packages that were ‘plugins’ for other frameworks.

刪除CHangeLog

相關文章
相關標籤/搜索