1. 脚手架实现原理,基于 Lerna 搭建自己的脚手架并发布到npm

1.1 为什么全局安装 @vue/cli 后会添加的命令为 vue ?

全局安装脚手架后,会根据脚手架的 package.json 中的 bin 来决定脚手架的命令

  "bin": {
    "vue": "bin/vue.js"
  },

当执行vue命令的时候,相当于执行node bin/vue.js

1.2 全局安装 @vue/cli 时发生了什么

首先 npm 下载包文件到 node 安装目录下的 node_modules,然后根据 package.json 文件 bin 属性中配置的命令在 C:\Program Files\nodejs 生成一个 vue 文件并注册到环境变量

1.3 执行 vue 命令时发生了什么?为什么 vue 指向一个 js 文件,我们却可以直接通过 vue 命令去执行它呢?

因为会在 bin/vue.js 文件头部声明了以下代码

#!/usr/bin/env node

它会告诉系统要用 node 去执行

1.4 已发布到npm脚手架 diao-cli

2. Yargs 常用 API 和开发流程

const yargs  = require('yargs/yargs')
// 一个ES6字符串标签,从多行字符串中去除缩进。
const dedent = require("dedent");

const cli = yargs()
const argv = process.argv.slice(2)

// 注入额外参数
const context = {
  diaoVersion: '1.0.0',
};
cli
  // 开启严格模式,输入无效命令会报错无法识别命令
  .strict()
  // 在头部输出一段信息
  .usage('Usage: diao-cli [command] <options>')
  // 设置需要输入命令的最小值,这里设置最少输入一个命令,否则则抛出错误信息
  .demandCommand(1, "A command is required. Pass --help to see all available commands and options.")
  // 如果没有找到匹配的命令,yargs提供关于类似命令的建议
  .recommendCommands()
  // 在有错误的时候执行,可以在这里自定义错误信息
  .fail((err, msg) => {
    console.error('err:', err)
  })
  // 设置 command 的别名
  .alias('h', 'help')
  .alias('v', 'version')
  // 设置命令行输出时候的宽度
  .wrap(cli.terminalWidth())
  // 在命令行末尾打印的消息
  .epilogue(dedent`
    When a command fails, all logs are written to lerna-debug.log in the current working directory.

    For more information, find our manual at https://github.com/lerna/lerna
  `)
  // 配置额外选项
  .options({
    debug: {
      type: 'boolean',
      describe: 'Bootstrap debug mode',
      alias: 'd'
    }
  })
  // 配置额外选项
  .option("registry", {
    type: "string",
    describe: 'Define global registry',
    alias: 'r'
  })
  // 对选项进行分组
  .group(['debug'], 'Dev Options')
  .group(['registry'], 'Extra Options')
  // 注册命令
  .command('init [name]', 'Do init a project', (yargs) => {
    yargs
      .option('name', {
        type: 'string',
        describe: 'Name of a project',
        alias: 'n'
      })
  }, (argv) => {
    console.log(argv)
  })
  // 注册命令
  .command({
    command: 'list',
    aliases: ['ls', 'la', 'll'],
    describe: 'List local packages',
    builder: (yargs) => {},
    handler: (argv) => {
      console.log(argv)
    }
  })
  // 解析命令输入参数
  .parse(argv, context)

3. Lerna 常用命令和实现原理

Lerna 是基于 git+npm 的多package项目管理工具

3.1 常用命令

初始化 Lerna 项目

lerna init

创建 Package

lerna create @diao-cli/core packages

安装依赖

lerna add mocha packages/core --dev

删除依赖

lerna clean

安装依赖

lerna boorstaap

执行单元测试

lerna run test

执行特定包单元测试

lerna run test @diao-cli/core

link 项目

lerna link

发布项目

lerna publish

3.2 Lerna 实现原理 (需要二刷三刷)

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

4. 理解 import-local 实现原理, 理解 require.resolve 实现原理

懵逼中,后面回过头再看~

Copyright © imooc-lego (2020 - present) all right reserved,powered by GitbookFile Modify: 2021-06-27 08:04:57

results matching ""

    No results matching ""