脚手架开发流程

  1. 创建 npm 项目

  2. 创建脚手架入口文件, 最上方添加:

    1
    #!/usr/bin/env node
  3. 配置 package.json, 添加 bin 属性

  4. 编写脚手架代码

  5. 将脚手架发布到 npm

脚手架使用流程

  1. 安装脚手架

    1
    npm install -g your-cli
  2. 使用脚手架

    1
    your-cli

脚手架开发难点

  1. 分包: 将复杂的系统拆分成若干个模块

  2. 命令注册:

    1
    2
    3
    vue create
    vue add
    vue invoke
  3. 参数解析:

    1
    vue command [options] <params>
    • options 全称: –version、–help
    • options 简写: -v、 -h
    • paramsoptions: --path /Users/ogliu/Desktop/vue-test
  4. 帮助文档:

    • global help

      • Usage
      • Options
      • Commands
    • command help

      • Usage
      • Options
  5. 命令行交互

  6. 日志打印

  7. 命令行文字变色

  8. 网络通信: HTTP / WebSocket

  9. 文件处理

等等……

原生脚手架开发痛点

  1. 重复操作
    • 多 Pacage 本地 link
    • 多 Package 依赖安装
    • 多 Package 单元测试
    • 多 Package 代码提交
    • 多 Package 代码发布
  2. 版本一致性
    • 发布时版本一致性
    • 发布后相互依赖版本升级

package 越多,管理复杂度越高

Lerna 简介

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

Lerna 是架构优化的产物, 它揭示了一个架构真理: 项目复杂度提升后, 就需要对项目进行架构优化,架构优化的主要目标往往都是以效能为核心。

官网: https://lerna.js.org

Lerna 开发脚手架流程

  1. 脚手架项目初始化
    • 初始化 npm 项目
    • 安装 lerna
    • lerna init 初始化项目
  2. 创建 package
    • lerna create 创建 Package
    • lerna add 安装依赖
    • lerna link 链接依赖
  3. 脚手架开发和测试
    • lerna exec 执行 shell 脚本
    • lerna run 执行 npm 命令
    • lerna clean 清空依赖
    • lerna bootstrap 重装依赖
  4. 脚手架发布上线
    • lerna version bump version
    • lerna changed 查看上版本以来的所有变更
    • lerna diff 查看 diff
    • lerna publish 项目发布

Lerna 脚手架框架搭建闭环示例

根据上面的 Lerna 开发脚手架流程实现完整示例

基础框架搭建

  1. 确认脚手架名称, 这里以 ogliu-cli-demo 为例, 为了方便管理分包, 打开 npm 官网, 创建组织 Add Organization , 直接输入组织名称 ogliu-cli-demo , 然后点击 Create , 然后点击 Skip 跳过

  2. 打开终端命令行, 创建项目文件夹并初始化 npm 项目

    1
    2
    mkdir ogliu-cli-demo && cd ogliu-cli-demo
    npm init -y
  3. 安装 Lerna

    1
    2
    npm install -D lerna
    npm install lerna -g
  4. 初始化 lerna

    1
    lerna init
  5. 修改默认配置文件 lerna.json, 将当前版本号修改成 1.0.0

  6. 创建 git 忽略文件 .gitignore , 将常见的文件排除掉

    1
    2
    3
    4
    5
    6
    7
    8
    .vscode
    .idea
    .DS_Store

    node_modules

    lerna-debug.log
    packages/**/node_modules
  7. 使用 lerna create 创建 Package: core, package name 使用 @ogliu-cli-demo/core

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    lerna create core

    package name: (core) @ogliu-cli-demo/core
    version: (1.0.0)
    description: ogliu-cli-demo core
    keywords:
    homepage:
    license: (ISC)
    entry point: (lib/core.js)
    git repository:
    About to write to /Users/liukun/Learn/ogliu-cli-demo/packages/core/package.json:

    {
    "name": "@ogliu-cli-demo/core",
    "version": "1.0.0",
    "description": "ogliu-cli-demo core",
    "author": "LiuKun <308880147@qq.com>",
    "homepage": "",
    "license": "ISC",
    "main": "lib/core.js",
    "directories": {
    "lib": "lib",
    "test": "__tests__"
    },
    "files": [
    "lib"
    ],
    "scripts": {
    "test": "echo \"Error: run tests from root\" && exit 1"
    }
    }


    Is this OK? (yes)
    lerna success create New package @ogliu-cli-demo/core created at ./packages/core
  8. 使用 lerna create 创建 Package: utils, package name 使用 @ogliu-cli-demo/utils

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    lerna create utils

    package name: (utils) @ogliu-cli-demo/utils
    version: (1.0.0)
    description: ogliu-cli-demo utils
    keywords:
    homepage:
    license: (ISC)
    entry point: (lib/utils.js)
    git repository:
    About to write to /Users/liukun/Learn/ogliu-cli-demo/packages/utils/package.json:

    {
    "name": "@ogliu-cli-demo/utils",
    "version": "1.0.0",
    "description": "> TODO: description",
    "author": "LiuKun <308880147@qq.com>",
    "homepage": "",
    "license": "ISC",
    "main": "lib/utils.js",
    "directories": {
    "lib": "lib",
    "test": "__tests__"
    },
    "files": [
    "lib"
    ],
    "scripts": {
    "test": "echo \"Error: run tests from root\" && exit 1"
    }
    }


    Is this OK? (yes)
    lerna success create New package @ogliu-cli-demo/utils created at ./packages/utils

Lerna 核心操作(练习)

  1. lerna add, 给所有 package 安装依赖

    1
    lerna add package-name
  2. lerna clean, 清空所有 package 的依赖, 需要手动删除 package.jsondependencies

    1
    lerna clean
  3. lerna add, 给指定 package 安装依赖

    1
    lerna add package-name packages/core/
  4. lerna bootstrap, 重新安装所有依赖

    1
    lerna bootstrap
  5. lerna link, 将 lerna 管理的所有 package 下面的相互依赖进行 link

    • package 内的 package.json 文件中指定依赖

      1
      2
      3
      4
      5
      package/core/package.json

      "dependencies": {
      "@ogliu-cli-demo/utils": "^1.0.0"
      }
    • 使用命令 lerna link , 它将在 core 中的 node_modules 内创建软链接,指向本地的 @ogliu-cli-demo/utils

      1
      2
      3
      4
      5
      6
      7
      8
      lerna link

      cd packages/core/node_modules/@ogliu-cli-demo && ll

      total 0
      drwxr-xr-x 3 liukun staff 96 2 8 15:12 ./
      drwxr-xr-x 3 liukun staff 96 2 8 15:12 ../
      lrwxr-xr-x 1 liukun staff 14 2 8 15:12 utils@ -> ../../../utils
  6. lerna exec, 在所有 package 下执行命令

    1
    lerna exec -- rm -rf node_modules/
  7. lerna exec, 在指定的 package 下执行命令

    1
    lerna exec --scope @ogliu-cli-demo/core -- rm -rf node_modules/
  8. lerna run, 执行每一个 packagenpm 脚本, 也就是 package.json 中的 scripts , 如果需要执行指定 package 下的 npm 脚本,则同 lerna exec 一样添加 --scope 选项

    1
    2
    lerna run test
    lerna run --scope @ogliu-cli-demo/core test

Lerna 发布上线相关命令

  1. 通过 lerna version 命令升级版本号
  2. 通过 lerna changed 查看自上一个版本以来,哪些 package 做了变更
  3. 通过 lerna diff 查看自上一个 commit 以来,哪些文件做了变更
  4. 通过 lerna publish 发布上线

Lerna 第一次发布上线

  1. 使用 Organizations 的形式发布 npm 包时, 默认情况下都为 Private 的,需要添加配置修改 为 Public , 在每个 packagepackage.json 文件中添加下面配置

    1
    2
    3
    "publishConfig": {
    "access": "public"
    }
  2. 需要在根目录下添加 LICENSE.md 文件

  3. 需要执行 npm login 进行登录

  4. 通过 lerna publish 发布上线

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    lerna publish
    info cli using local version of lerna
    lerna notice cli v4.0.0
    lerna info current version 1.0.0
    lerna info Assuming all packages changed
    ? Select a new version (currently 1.0.0) Patch (1.0.1)

    Changes:
    - @ogliu-cli-demo/core: 1.0.0 => 1.0.1
    - @ogliu-cli-demo/utils: 1.0.0 => 1.0.1

    ? Are you sure you want to publish these packages? Yes
    lerna info execute Skipping releases
    lerna info git Pushing tags...
    lerna info publish Publishing packages to npm...
    lerna info Verifying npm credentials
    lerna http fetch GET 200 https://registry.npmjs.org/-/npm/v1/user 856ms
    lerna http fetch GET 200 https://registry.npmjs.org/-/org/og-liu/package?format=cli 1972ms (cache miss)
    lerna info Checking two-factor auth mode
    lerna http fetch GET 200 https://registry.npmjs.org/-/npm/v1/user 274ms
    lerna http fetch PUT 200 https://registry.npmjs.org/@ogliu-cli-demo%2futils 2747ms
    lerna success published @ogliu-cli-demo/utils 1.0.1
    lerna notice
    lerna notice 📦 @ogliu-cli-demo/utils@1.0.1
    lerna notice === Tarball Contents ===
    lerna notice 73B lib/utils.js
    lerna notice 486B package.json
    lerna notice 0B LICENSE.md
    lerna notice 108B README.md
    lerna notice === Tarball Details ===
    lerna notice name: @ogliu-cli-demo/utils
    lerna notice version: 1.0.1
    lerna notice filename: ogliu-cli-demo-utils-1.0.1.tgz
    lerna notice package size: 596 B
    lerna notice unpacked size: 667 B
    lerna notice shasum: 01393c72bce7b879c3929ba631bc9b11dbe63cd3
    lerna notice integrity: sha512-mWU8zYJEsM2Qu[...]+ezmbg0/BpgiQ==
    lerna notice total files: 4
    lerna notice
    lerna success published @ogliu-cli-demo/core 1.0.1
    lerna notice
    lerna notice 📦 @ogliu-cli-demo/core@1.0.1
    lerna notice === Tarball Contents ===
    lerna notice 71B lib/core.js
    lerna notice 546B package.json
    lerna notice 0B LICENSE.md
    lerna notice 105B README.md
    lerna notice === Tarball Details ===
    lerna notice name: @ogliu-cli-demo/core
    lerna notice version: 1.0.1
    lerna notice filename: ogliu-cli-demo-core-1.0.1.tgz
    lerna notice package size: 623 B
    lerna notice unpacked size: 722 B
    lerna notice shasum: 67d557e3de1c10d8b40b3eb30c67c9e65a45c93c
    lerna notice integrity: sha512-x/XU8GiilKGG3[...]kBR/UbJJDiW6A==
    lerna notice total files: 4
    lerna notice
    Successfully published:
    - @ogliu-cli-demo/core@1.0.1
    - @ogliu-cli-demo/utils@1.0.1
    lerna success published 2 packages
    lerna http fetch PUT 200 https://registry.npmjs.org/@ogliu-cli-demo%2fcore 3709ms