Thinking--javascript 多类目创建(npm源码解读)

2021-12-10 08:46:41 浏览数 (1)

Npm 获取配置的顺序(由高到低):Command Line Flags > Environment Variables > npmrc Files > Default Configs

  1. Command Line Flags:--flag1 --flag2 bar -- flag3 结果:flag1=true,flag2=bar,flag3为命令参数。
  2. Environment Variables:以 npm_config_ 开头的环境变量将被解释为配置参数。npm_config_flag=bar 可通过 process.env.npm_config_flag获取
  3. npmrc Files:根据存放位置不同,优先级不同 – https://docs.npmjs.com/cli/v8/configuring-npm/npmrc
  4. Default Configs:内置配置参数,可通过 npm config ls -l 查看

相关配置命令:

代码语言:javascript复制
npm config set <key> <value>
npm config get [<key>]
npm config delete <key>
npm config list [--json]
npm config edit
npm set <key> <value>
npm get [<key>]

这里重点讲述的是:npm 是如何对这些配置做“统一管理”。

核心思路:统一入口

  1. 枚举了每个“配置”【必选】【可选】属性,对此做统一强校验,后续无需再做是否存在判断。
  2. Object.assign(this, def) 【扩充实例属性】这里包括 key、def
  3. 统一定义【校验方法】,关联到当前实例中(挂载到了类的 prototype 属性上面)

Class 类方法都定义在类的 prototype 属性上面。 class Person { constructor (name) {} say(){} } console.log(Person.prototype) // {constructor: f, say: f} p.hasOwnProperty('say') // false p.__proto__.hasOwnProperty('say') // true 在类的实例上面调用方法,其实就是调用原型上的方法。 const p = new Person('ligang') p.constructor === Person.prototype.constructor // true 类的所有实例共享一个原型对象。 const p1 = new Person('li') const p2 = new Person('gang') p1.__proto__ === p2.__proto__ // true

definition.js 描述配置属性

代码语言:javascript复制
// 配置项必须具备的属性
const required = ['key', 'type', 'default']	
// 配置项可选属性
const allowed = [...required, 'description', 'name', 'flatten']

/* 统一结构定义 */
class Definition {
  constructor (key, def) {
    this.key = key
    // 扩充实例属性
    Object.assign(this, def)
    // 校验
    this.validate()
    // 统一处理
    if (!this.defaultDescription) {}
    if (!this.typeDescription) {}
    if (!this.hint) {}
  }

  validate () {
    for (let req of required) {
      // 校验必须存在的属性
      if (!Object.prototype.hasOwnProperty.call(this, req)) {
        throw new Error(`缺失必须属性 ${req}: ${this.key}`)
      }
      // 校验是否存在未知属性
      for (let field of Object.keys(this)) {
        if (!allowed.includes(field)) {
          throw new Error(`存在未知属性 ${field}: ${this.key}`)
        }
      }
    }
  }
}

definitions.js 定义相关配置

代码语言:javascript复制
// basic flattening function, just copy it over camelCase
const flatten = (key, obj, flatOptions) => {
  const camel = key.replace(/-([a-z])/g, (_0, _1) => _1.toUpperCase())
  flatOptions[camel] = obj[key]
}

const definitions = {}
const define = (key, def) => {
  definitions[key] = new Definition(key, def)
}
define('registry', {
  type: url,
  default: 'https://registry.npmjs.org/',
  description: 'The base URL of the npm registry.',
  flatten
})
define('user-agent', {
  type: String,
  default: 'npm/{npm-version} node/{node-version} {platform} {arch} workspaces/{workspaces} {ci}',
  description: 'Sets the User-Agent request header.',
  flatten (key, obj, flatOptions) {
    // 特殊处理
  }
})

参考地址:

  • https://developer.mozilla.org/zh-CN/docs/Web/JavaScript/Reference/Classes
  • https://github.com/npm/cli/blob/HEAD/lib/utils/config/definition.js
  • https://github.com/npm/cli/blob/HEAD/lib/utils/config/definitions.js
  • https://blog.csdn.net/jiaojsun/article/details/99831112

0 人点赞