本地环境搞起来

  • 下载源码,安装依赖
  • vscode 创建默认 launch.json,添加参数"args": ["ls"]
  • F5 运行看下是否打印出东西来
  • 在入口文件里面打断点尝试调试,如果断点成功,说明环境OK

技术点整理

  • file:../abc方式引入依赖包(优于 link),发布的时候自动替换为正常的版本号
    1
    2
    3
    4
    5
    6
    7
    8
    {
    "dependencies": {
    "@lerna/global-options": "file:../global-options",
    "dedent": "^0.7.0",
    "npmlog": "^4.1.2",
    "yargs": "^14.2.2"
    }
    }
  • JS事件循环,宏任务,微任务
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    console.log(1)
    setTimeout(()=>{
    console.log('7:最后执行')
    },0)
    new Promise(()=>{
    let chain=Promise.resolve();
    chain.then(()=>console.log('3'))
    chain.then(()=>console.log('4'))
    chain.then(()=>console.log('5'))
    })
    let chain=Promise.resolve();
    chain.then(()=>console.log('6'));
    console.log(2)
  • yargs的使用参考—>cxvh-cli-test
  • clone-deep深拷贝(lodash也有深拷贝方法)
  • dedent去掉反斜杠里面字符串的缩进
  • import-local本地存在一个脚手架命令,全局也有,优先选用node_modules里面的!!!
    • pkg-dir会循环找到项目中package.json文件
      • path.join('/user','/test','..')返回/test
      • path.resolve('/user','/test','..')返回/
      • path.resolve('.')返回当前的完整路径
      • path.parse(path.resolve('.'))解析路径
      • find-upwhite(true){return 1||null}方法用return,否则会死循环
      • locate-path判断是否存在路径,存在返回第一个路径
      • path-exists判断路径是否存在(fs.accessSync(fp))
    • resolve-cwd从当前工作目录解析模块的路径
    • var a="123\x00321"a123 321
    • /(?:^|\/)\.?\.$)/.test(request)匹配/..或者/.结尾的字符串
    • fs.realpathSync(requestPath,{[internalFS.realpathCacheKey]:realpathCache})返回已解析的路径名
    • Object.create(null)创建的对象没有原型链
    • '/xxx/yyy'.indexOf('/',1)跳过第一个开始查找,返回4
    • Module._nodeModulePaths生成node_modules可能的路径,如:['/a/b/c/node_modules','/a/b/node_modules','/a/node_modules'],'/node_modules']
      • 判断路径是否为/,是返回['node_modules'],否遍历各级目录,在目录后添加node_modules,并存储到paths
    • Module._resolveFilename_解析模块的真实路径
      • 是否为内置模块,是返回,否:Module.resolveLookupPathspaths和环境变量node_modules合并,Module.findPathpaths中解析模块的真实路径
    • require()源码解读
    • fs.lstat(path[, options], callback)lstat()stat()相同,只是如果path是符号链接,则查看的是链接自身,而不是它指向的文件。
    • fs.realpathSync()查询缓存=>是:直接返回结果,否:
  • lerna命令相当于执行node /users/sam/.nvm/versions/node/v12.11.1/lib/node_modules/lerna/cli.js

yargs是如何实现脚手架的?

  • 脚手架构成
    • bin(主命令):在package.json配置,本地安装用npm link
    • command:命令
    • options:参数(boolean、string、number)
    • 文件顶部增加#!/usr/bin/env node(告诉操作系统,要在环境变量中查询到node命令,通过node命令来执行文件)
  • 脚手架初始化流程
    • 构建函数:Yargs()
    • 常用方法(增强脚手架功能):
      • Yargs.usage用法说明
      • Yargs.recommendCommands输入错误会提示相似命令
      • Yargs.demandCommand限制命令数量
      • Yargs.fail错误处理
      • Yargs.strict严格模式
      • Yargs.alias别名
      • Yargs.wrap宽度
      • Yargs.epilogue页脚提示
      • Yargs.options选项(多个选项传数组)
      • Yargs.options选项(单个选项,传JSON)
      • Yargs.group分组
  • 脚手架参数解析方法(识别命令)
    • hideBin(process.argv)/Yargs.argv
    • Yargs.parse(argv,options)
  • 命令注册方法
    • Yargs.commannd(command,describe,builder,handler)
    • Yargs.commannd({command,describe,builder,handler})

      Lerna有什么用,如何实现命令调用?

  • Lerna是基于git+npm的多package项目管理工具
  • 实现原理
    • 通过import-local优先调用本地lerna命令
    • 通过Yargs生成脚手架,先注册全局属性,再注册命令,最后通过parse方法解析参数
    • lerna命令注册时需要传入builderhandler两个方法,builder方法用于注册命令专属的optionshandler用来处理命令的业务逻辑
    • lerna通过配置npm本地依赖的方式来进行本地开发,具体写法是在package.json的依赖中写入:file:../your/local/module/path,在lerna publish时会自动将该路径替换