导航菜单

  • 0.api
  • 0.Async
  • 0.module
  • 1.ES2015
  • 2.Promise
  • 3.Node
  • 4.NodeInstall
  • 5.REPL
  • 6.NodeCore
  • 7.module&NPM
  • 8.Encoding
  • 9.Buffer
  • 10.fs
  • 11.Stream-1
  • 11.Stream-2
  • 11.Stream-3
  • 11.Stream-4
  • 12-Network-2
  • 12.NetWork-3
  • 12.Network-1
  • 13.tcp
  • 14.http-1
  • 14.http-2
  • 15.compress
  • 16.crypto
  • 17.process
  • 18.yargs
  • 19.cache
  • 20.action
  • 21.https
  • 22.cookie
  • 23.session
  • 24.express-1
  • 24.express-2
  • 24.express-3
  • 24.express-4
  • 25.koa-1
  • 26.webpack-1-basic
  • 26.webpack-2-optimize
  • 26.webpack-3-file
  • 26.webpack-4.tapable
  • 26.webpack-5-AST
  • 26.webpack-6-sources
  • 26.webpack-7-loader
  • 26.webpack-8-plugin
  • 26.webpack-9-hand
  • 26.webpack-10-prepare
  • 28.redux
  • 28.redux-jwt-back
  • 28.redux-jwt-front
  • 29.mongodb-1
  • 29.mongodb-2
  • 29.mongodb-3
  • 29.mongodb-4
  • 29.mongodb-5
  • 29.mongodb-6
  • 30.cms-1-mysql
  • 30.cms-2-mysql
  • 30.cms-3-mysql
  • 30.cms-4-nunjucks
  • 30.cms-5-mock
  • 30.cms-6-egg
  • 30.cms-7-api
  • 30.cms-8-roadhog
  • 30.cms-9-yaml
  • 30.cms-10-umi
  • 30.cms-12-dva
  • 30.cms-13-dva-ant
  • 30.cms-14-front
  • 30.cms-15-deploy
  • 31.dva
  • 31.cms-13-dva-antdesign
  • 33.redis
  • 34.unittest
  • 35.jwt
  • 36.websocket-1
  • 36.websocket-2
  • 38.chat-api-1
  • 38.chat-api-2
  • 38.chat-3
  • 38.chat-api-3
  • 38.chat
  • 38.chat2
  • 38.chat2
  • 39.crawl-0
  • 39.crawl-1
  • 39.crawl-2
  • 40.deploy
  • 41.safe
  • 42.test
  • 43.nginx
  • 44.enzyme
  • 45.docker
  • 46.elastic
  • 47.oauth
  • 48.wxpay
  • index
  • 52.UML
  • 53.design
  • index
  • 54.linux
  • 57.ts
  • 56.react-ssr
  • 58.ts_react
  • 59.ketang
  • 59.ketang2
  • 61.1.devops-linux
  • 61.2.devops-vi
  • 61.3.devops-user
  • 61.4.devops-auth
  • 61.5.devops-shell
  • 61.6.devops-install
  • 61.7.devops-system
  • 61.8.devops-service
  • 61.9.devops-network
  • 61.10.devops-nginx
  • 61.11.devops-docker
  • 61.12.devops-jekins
  • 61.13.devops-groovy
  • 61.14.devops-php
  • 61.15.devops-java
  • 61.16.devops-node
  • 61.17.devops-k8s
  • 62.1.react-basic
  • 62.2.react-state
  • 62.3.react-high
  • 62.4.react-optimize
  • 62.5.react-hooks
  • 62.6.react-immutable
  • 62.7.react-mobx
  • 62.8.react-source
  • 63.1.redux
  • 63.2.redux-middleware
  • 63.3.redux-hooks
  • 63.4.redux-saga
  • 63.5.redux-saga-hand
  • 64.1.router
  • 64.2.router-connected
  • 65.1.typescript
  • 65.2.typescript
  • 65.3.typescript
  • 65.4.antd
  • 65.4.definition
  • 66-1.vue-base
  • 66-2.vue-component
  • 66-3.vue-cli3.0
  • 66-4.$message组件
  • 66-5.Form组件
  • 66-6.tree
  • 66-7.vue-router-apply
  • 66-8.axios-apply
  • 66-9.vuex-apply
  • 66-10.jwt-vue
  • 66-11.vue-ssr
  • 66-12.nuxt-apply
  • 66-13.pwa
  • 66-14.vue单元测试
  • 66-15.权限校验
  • 67-1-network
  • 68-2-wireshark
  • 7.npm2
  • 69-hooks
  • 70-deploy
  • 71-hmr
  • 72.deploy
  • 73.import
  • 74.mobile
  • 75.webpack-1.文件分析
  • 75.webpack-2.loader
  • 75.webpack-3.源码流程
  • 75.webpack-4.tapable
  • 75.webpack-5.prepare
  • 75.webpack-6.resolve
  • 75.webpack-7.loader
  • 75.webpack-8.module
  • 75.webpack-9.chunk
  • 75.webpack-10.asset
  • 75.webpack-11.实现
  • 76.react_optimize
  • 77.ts_ketang_back
  • 77.ts_ketang_front
  • 78.vue-domdiff
  • 79.grammar
  • 80.tree
  • 81.axios
  • 82.1.react
  • 82.2.react-high
  • 82.3.react-router
  • 82.4.redux
  • 82.5.redux_middleware
  • 82.6.connected
  • 82.7.saga
  • 82.8.dva
  • 82.8.dva-source
  • 82.9.roadhog
  • 82.10.umi
  • 82.11.antdesign
  • 82.12.ketang-front
  • 82.12.ketang-back
  • 83.upload
  • 84.graphql
  • 85.antpro
  • 86.1.uml
  • 86.2.design
  • 87.postcss
  • 88.react16-1
  • 89.nextjs
  • 90.react-test
  • 91.react-ts
  • 92.rbac
  • 93.tsnode
  • 94.1.JavaScript
  • 94.2.JavaScript
  • 94.3.MODULE
  • 94.4.EventLoop
  • 94.5.文件上传
  • 94.6.https
  • 94.7. nginx
  • 95.1. react
  • 95.2.react
  • 96.1.react16
  • 96.2.fiber
  • 96.3.fiber
  • 97.serverless
  • 98.websocket
  • 100.1.react-basic
  • 101.1.monitor
  • 101.2.monitor
  • 102.java
  • 103.1.webpack-usage
  • 103.2.webpack-bundle
  • 103.3.webpack-ast
  • 103.4.webpack-flow
  • 103.5.webpack-loader
  • 103.6.webpack-tapable
  • 103.7.webpack-plugin
  • 103.8.webpack-optimize1
  • 103.9.webpack-optimize2
  • 103.10.webpack-hand
  • 103.11.webpack-hmr
  • 103.11.webpack5
  • 103.13.splitChunks
  • 103.14.webpack-sourcemap
  • 103.15.webpack-compiler1
  • 103.15.webpack-compiler2
  • 103.16.rollup.1
  • 103.16.rollup.2
  • 103.16.rollup.3
  • 103.16.vite.basic
  • 103.16.vite.source
  • 103.16.vite.plugin
  • 103.16.vite.1
  • 103.16.vite.2
  • 103.17.polyfill
  • 104.1.binary
  • 104.2.binary
  • 105.skeleton
  • 106.1.react
  • 106.2.react_hooks
  • 106.3.react_router
  • 106.4.redux
  • 106.5.redux_middleware
  • 106.6.connected-react-router
  • 106.6.redux-first-history
  • 106.7.redux-saga
  • 106.8.dva
  • 106.9.umi
  • 106.10.ketang
  • 106.11.antdesign
  • 106.12.antpro
  • 106.13.router-6
  • 106.14.ssr
  • 106.15.nextjs
  • 106.16.1.cms
  • 106.16.2.cms
  • 106.16.3.cms
  • 106.16.4.cms
  • 106.16.mobx
  • 106.17.fomily
  • 107.fiber
  • 108.http
  • 109.1.webpack_usage
  • 109.2.webpack_source
  • 109.3.dll
  • 110.nest.js
  • 111.xstate
  • 112.Form
  • 113.redux-saga
  • 114.react+typescript
  • 115.immer
  • 116.pro5
  • 117.css-loader
  • 118.1.umi-core
  • 119.2.module-federation
  • 119.1.module-federation
  • 120.create-react-app
  • 121.react-scripts
  • 122.react-optimize
  • 123.jsx-runtime
  • 124.next.js
  • 125.1.linux
  • 125.2.linux-vi
  • 125.3.linux-user
  • 125.4.linux-auth
  • 125.5.linux-shell
  • 125.6.linux-install
  • 125.7.linux-system
  • 125.8.linux-service
  • 125.9.linux-network
  • 125.10.nginx
  • 125.11.docker
  • 125.12.ci
  • 125.13.k8s
  • 125.14.k8s
  • 125.15.k8s
  • 125.16.k8s
  • 126.11.react-1
  • 126.12.react-2
  • 126.12.react-3
  • 126.12.react-4
  • 126.12.react-5
  • 126.12.react-6
  • 126.12.react-7
  • 126.12.react-8
  • 127.frontend
  • 128.rollup
  • 129.px2rem-loader
  • 130.health
  • 131.hooks
  • 132.keepalive
  • 133.vue-cli
  • 134.react18
  • 134.2.react18
  • 134.3.react18
  • 135.function
  • 136.toolkit
  • 137.lerna
  • 138.create-vite
  • 139.cli
  • 140.antd
  • 141.react-dnd
  • 142.1.link
  • 143.1.gulp
  • 143.2.stream
  • 143.3.gulp
  • 144.1.closure
  • 144.2.v8
  • 144.3.gc
  • 145.react-router-v6
  • 146.browser
  • 147.lighthouse
  • 148.1.basic
  • 148.2.basic
  • 148.3.basic
  • 148.4.basic
  • 148.5.basic
  • 149.1.vite
  • 149.2.vite
  • 149.3.vite
  • 149.4.vite
  • 150.react-window
  • 151.react-query
  • 152.useRequest
  • 153.transition
  • 154.emotion
  • 155.1.formily
  • 155.2.formily
  • 155.3.formily
  • 155.3.1.mobx.usage
  • 155.3.2.mobx.source
  • 156.vue-loader
  • 103.11.mf
  • 157.1.react18
  • 158.umi4
  • 159.rxjs
  • 159.rxjs2
  • 160.bff
  • 161.zustand
  • 162.vscode
  • 163.emp
  • 164.cors
  • 1.lerna
    • 1.1 简介
    • 1.2.lerna 入门
  • 2.lerna 源码
    • 2.1 配置安装源
    • 2.2 克隆源码
    • 2.3 调试源码
    • 2.4 核心包
  • 3.创建 npm 私服
  • 4.创建包
  • 4.单元测试
    • 5.1 package.json
    • 5.2 jest.config.js
    • 5.3 lerna4\package.json
    • 5.4 lerna4.js
    • 5.5 create.test.js
  • 6.eslint
    • 6.1 .eslintrc.js
    • 6.2 .eslintignore
    • 6.3 package.json
  • 7.Prettier
    • 7.1 .eslintrc.js
    • 7.2 .prettierrc.js
  • 8. editorconfig
    • 8.1 .editorconfig
    • 8.2 总结
  • 9. git hook
    • 9.1 pre-commit
      • 9.1.1 安装 Git hooks
      • 9.1.2 安装 pre-commit
    • 9.2 commit-msg
      • 9.2.1 安装配置
      • 9.2.2 安装 commit-msg
      • 9.2.3 添加命令
      • 9.2.4 .cz-config.js
      • 9.2.5 commitlint.config.js
      • 9.2.6 package.json
  • 10.发布上线
  • 11.安装命令
    • 11.1 cli.js
    • 11.2 lerna4\index.js
    • 11.3 lerna4\package.json
    • 11.4 链接
  • 12. yargs
  • 13.跑通 init 命令
    • 13.1 cli\package.json
    • 13.2 cli\index.js
    • 13.3 init\command.js
    • 13.4 lerna4\package.json
    • 13.5 lerna4\index.js
  • 14.实现 init 命令
    • 14.1 安装依赖
    • 14.2 init\command.js
    • 14.3 packages\init\index.js
  • 15.实现 create 命令
    • 15.1 安装依赖
    • 15.2 lerna4\index.js
    • 15.3 lerna4\package.json
    • 15.4 create\command.js
    • 15.5 create\index.js
  • 16.参考
    • 16.1 lerna 命令
      • 项目初始化
      • 16.2 创建包
      • 16.3 开发和测试
      • 16.4 发布上线
    • 17.格式化提交
      • 17.1 Conventional Commits
      • 17.2 类型(type)
      • 17.3 范围(scope)

1.lerna #

1.1 简介 #

  • Lerna 官网 是一个管理工具,用于管理包含多个软件包(package)的 JavaScript 项目
  • Lerna Git 仓库 是一种工具,针对 使用 git 和 npm 管理多软件包代码仓库的工作流程进行优化

1.2.lerna 入门 #

首先使用 npm 将 Lerna 安装到全局环境中

npm install -g lerna

接下来,我们将创建一个新的 git 代码仓库

mkdir lerna4 && cd lerna4

现在,我们将上述仓库转变为一个 Lerna 仓库:

lerna init
lerna notice cli v4.0.0
lerna info Initializing Git repository
lerna info Creating package.json
lerna info Creating lerna.json
lerna info Creating packages directory
lerna success Initialized Lerna files
lerna4 / packages / 放置多个软件包(package);
package.json;
lerna.json;

.gitignore

node_modules.idea.vscode;

2.lerna 源码 #

2.1 配置安装源 #

npm install -g yrm
npm install -g nrm

2.2 克隆源码 #

git clone https://gitee.com/zhufengpeixun/lerna.git --depth=1

2.3 调试源码 #

.vscode\launch.json

{
  "version": "0.2.0",
  "configurations": [
    {
      "type": "node",
      "request": "launch",
      "name": "Launch Program",
      "skipFiles": ["<node_internals>/**"],
      "program": "${workspaceFolder}\\core\\lerna\\cli.js",
      "args": ["ls"]
    }
  ]
}

2.4 核心包 #

lerna 入口核心包
@lerna/cli
@lerna/create 创建包命令
@lerna/init 初始化lerna项目

3.创建 npm 私服 #

  • verdaccio是一个简单 、零配置的本地私有化 npm 仓库
cnpm install verdaccio -g
verdaccio
http://localhost:4873
npm adduser --registry http://localhost:4873/
npm publish --registry http://localhost:4873/

4.创建包 #

lerna create lerna4 --registry http://localhost:4873
lerna success create New package lerna4 created at ./packages\lerna4
lerna create @lerna4/cli --registry http://localhost:4873
lerna success create New package @lerna4/cli created at ./packages\cli
lerna create @lerna4/create --registry http://localhost:4873
lerna success create New package @lerna4/create created at ./packages\create
lerna create @lerna4/init --registry http://localhost:4873
lerna success create New package @lerna4/init created at ./packages\init

4.单元测试 #

  • Jest是一个 JavaScript 测试框架
  • expect
npm install --save-dev jest
//在所有的包下执行test命令
lerna run test
//在lerna4下执行test命令
lerna run test --scope lerna4

//在所有的包下执行shell脚本
lerna exec -- jest
//在lerna4下执行shell脚本
lerna exec --scope lerna4 -- jest

5.1 package.json #

{
  "name": "root",
  "private": true,
  "devDependencies": {
    "lerna": "^4.0.0"
  },
+ "scripts": {
+    "test":"jest"
+  }
}

5.2 jest.config.js #

  • configuration
  • expect
module.exports = {
  testMatch: ["**/__tests__/**/*.test.js"],
};

5.3 lerna4\package.json #

packages\lerna4\package.json

{
+  "scripts": {
+    "test": "jest"
+  }
}

5.4 lerna4.js #

packages\lerna4\lib\lerna4.js

module.exports = lerna4;
function lerna4() {
  return "lerna4";
}

5.5 create.test.js #

packages\create__tests__\create.test.js

"use strict";

const create = require("..");
describe("@lerna4/create", () => {
  it("create", () => {
    expect(create()).toEqual("create");
  });
});

6.eslint #

  • eslint是一个插件化并且可配置的 JavaScript 语法规则和代码风格的检查工具
  • 代码质量问题:使用方式有可能有问题
  • 代码风格问题:风格不符合一定规则
  • vscode-eslint
cnpm i eslint  --save-dev

6.1 .eslintrc.js #

module.exports = {
  parserOptions: { ecmaVersion: 2017, sourceType: "module" },
  extends: ["eslint:recommended"],
  rules: {
    "no-unused-vars": ["off"],
  },
  env: { node: true, jest: false },
};

6.2 .eslintignore #

__tests__;

6.3 package.json #

  "scripts": {
    "test": "jest",
+   "lint":"eslint --ext .js packages/**/*.js --no-error-on-unmatched-pattern --fix"
  }

7.Prettier #

  • ESLint 主要解决的是代码质量问题
  • Prettier 主要解决的是代码风格问题
  • Prettier 会去掉你代码里的所有样式风格,然后用统一固定的格式重新输出
  • prettier声称自己是一个有主见的代码格式化工具
  • Prettier vs. Linters
  • integrating-with-linters
  • Prettier 对应的是各种 Linters 的 Formatting rules 这一类规则
  • 禁用 Linters 自己的 Formatting rules,让 Prettier 接管这些职责
  • eslint-config-prettier用来关闭和 Prettier 冲突非必要的规则
  • recommended-configuration
  • prettier-vscode
cnpm i   prettier eslint-plugin-prettier  --save-dev

7.1 .eslintrc.js #

module.exports = {
  extends: ['eslint:recommended'],
  //让所有可能会与 prettier 规则存在冲突的 eslint rule失效,并使用 prettier 的规则进行代码检查
  //相当于用 prettier 的规则,覆盖掉 eslint:recommended 的部分规则
+ plugins: ['prettier'],
  rules: {
    'no-unused-vars': ['off'],
    //不符合prettier规则的代码要进行错误提示
+   'prettier/prettier': ['error', { endOfLine: 'auto' }],
  },
  env: { node: true, jest: false },
};

7.2 .prettierrc.js #

module.exports = {
  singleQuote: true,
};

8. editorconfig #

  • editorconfig帮助开发人员在不同的编辑器和 IDE 之间定义和维护一致的编码样式
  • 不同的开发人员,不同的编辑器,有不同的编码风格,而 EditorConfig 就是用来协同团队开发人员之间的代码的风格及样式规范化的一个工具,而.editorconfig 正是它的默认配置文件
  • EditorConfig
  • vscode 这类编辑器,需要自行安装 editorconfig 插件

8.1 .editorconfig #

  • Unix 系统里,每行结尾只有换行,即\n LF(Line Feed)
  • Windows 系统里面,每行结尾是换行 回车,即\r\n CR/LF
  • Mac 系统里,每行结尾是回车,即\r CR(Carriage Return)
root = true

[*]
indent_style = space
indent_size = 2
end_of_line = lf
charset = utf-8
trim_trailing_whitespace = true

[*.md]
trim_trailing_whitespace = false

8.2 总结 #

  • 开发过程中,如果写出代码质量有问题的代码,eslint 能够及时提醒开发者,便于及时修复
  • 如果写出代码格式有问题的代码,prettier 能够自动按照我们制定的规范、格式化代码
  • 不同开发者如果使用不同的编辑器(webstorm/vscode)或系统(windows/mac),能够执行统一的代码风格标准

9. git hook #

9.1 pre-commit #

  • 可以在 git commit 之前检查代码,保证所有提交到版本库中的代码都是符合规范的
  • 可以在 git push 之前执行单元测试,保证所有的提交的代码经过的单元测试
  • husky可以让我们向项目中方便添加 git hooks
  • lint-staged 用于实现每次提交只检查本次提交所修改的文件

9.1.1 安装 Git hooks #

cnpm i husky --save-dev
npm set-script prepare "husky install"

9.1.2 安装 pre-commit #

npx husky add .husky/pre-commit "npx lint-staged"

9.2 commit-msg #

  • commitizen插件可帮助实现一致的提交消息
  • cz-customizable可以实现自定义的提交
  • @commitlint/cli可以检查提交信息
  • @commitlint/config-conventional检查您的常规提交

9.2.1 安装配置 #

cnpm install commitizen cz-customizable @commitlint/cli @commitlint/config-conventional --save-dev

9.2.2 安装 commit-msg #

npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"

9.2.3 添加命令 #

npx husky add .husky/commit-msg "npx --no-install commitlint --edit $1"

9.2.4 .cz-config.js #

module.exports = {
  types: [
    { value: "feat", name: "feat:一个新特性" },
    { value: "fix", name: "fix:修复BUG" },
  ],
  scopes: [{ name: "sale" }, { name: "user" }, { name: "admin" }],
};

9.2.5 commitlint.config.js #

module.exports = {
  extends: ["@commitlint/config-conventional"],
};

9.2.6 package.json #

  "scripts": {
    "test": "jest",
    "lint": "eslint --ext .js packages/**/*.js --no-error-on-unmatched-pattern --fix",
    "prepare": "husky install",
+   "commit": "cz"
  },

10.发布上线 #

npx husky add .husky/pre-push "npm run test"
lerna version
lerna publish

11.安装命令 #

11.1 cli.js #

packages\lerna4\cli.js

#!/usr/bin/env node
require(".")(process.argv.slice(2));

11.2 lerna4\index.js #

packages\lerna4\index.js

module.exports = main;
function main(argv) {
  console.log(argv);
}

11.3 lerna4\package.json #

packages\lerna4\package.json

{
+  "main": "index.js",
+  "bin":{
+    "lerna4":"cli.js"
+  }
}

11.4 链接 #

cd packages\lerna4
npm link
lerna4

12. yargs #

  • yargs用来解析命令行参数和选项
const yargs = require("yargs/yargs");
const argv = process.argv.slice(2);
const cli = yargs(argv);
//应用到每一个命令的全局参数
const opts = {
  loglevel: {
    defaultDescription: "info",
    describe: "报告日志的级别",
    type: "string",
    alias: "L",
  },
};
//全局的key
const globalKeys = Object.keys(opts).concat(["help", "version"]);
cli
  .options(opts) //配置全局参数
  .group(globalKeys, "Global Options:") // 把全局参数分到全局组里
  .usage("Usage: $0 <command> [options]") //提示使用说明
  .demandCommand(1, "至少需要一个命令,传递--help查看所有的命令和选项") //指定最小命令数量
  .recommendCommands() //推荐命令
  .strict() //严格命令,不正确 会报错
  .fail((msg, err) => {
    //自定义错误打印
    console.error("lerna", msg, err);
  })
  .alias("h", "help") //别名
  .alias("v", "version") //别名
  .wrap(cli.terminalWidth()) //命令行宽度
  .epilogue(
    //结语
    `当1个命令失败了,所有的日志将会写入当前工作目录中的lerna-debug.log`
  )
  .command({
    command: "create <name>",
    describe: "创建一个新的lerna管理的包",
    builder: (yargs) => {
      yargs
        .positional("name", {
          describe: "包名(包含scope)",
          type: "string",
        })
        .options({
          registry: {
            group: "Command Options:",
            describe: "配置包的发布仓库",
            type: "string",
          },
        });
    },
    handler: (argv) => {
      console.log("执行init命令", argv);
    },
  })
  .parse(argv);

/**
node lerna4.js create project --registry  http://localhost:4873
执行init命令 {
  '$0': 'lerna4.js',
  _: [ 'create' ],
  name: 'project'
  registry: 'http://localhost:4873',
}
*/

13.跑通 init 命令 #

lerna link
lerna bootstrap

13.1 cli\package.json #

packages\cli\package.json

"dependencies": {
    "@lerna4/cli":"^0.0.4",
    "@lerna4/init":"^0.0.4"
},
+  "main": "index.js",

13.2 cli\index.js #

packages\cli\index.js

const yargs = require("yargs/yargs");
function lernaCLI() {
  const cli = yargs();
  //应用到每一个命令的全局参数
  const opts = {
    loglevel: {
      defaultDescription: "info",
      describe: "报告日志的级别",
      type: "string",
      alias: "L",
    },
  };
  //全局的key
  const globalKeys = Object.keys(opts).concat(["help", "version"]);
  return cli
    .options(opts) //配置全局参数
    .group(globalKeys, "Global Options:") // 把全局参数分到全局组里
    .usage("Usage: $0 <command> [options]") //提示使用说明
    .demandCommand(1, "至少需要一个命令,传递--help查看所有的命令和选项") //指定最小命令数量
    .recommendCommands() //推荐命令
    .strict() //严格命令,不正确 会报错
    .fail((msg, err) => {
      //自定义错误打印
      console.error("lerna", msg, err);
    })
    .alias("h", "help") //别名
    .alias("v", "version") //别名
    .wrap(cli.terminalWidth()) //命令行宽度
    .epilogue(
      //结语
      `当1个命令失败了,所有的日志将会写入当前工作目录中的lerna-debug.log`
    );
}
module.exports = lernaCLI;

13.3 init\command.js #

packages\init\command.js

exports.command = "init";
exports.describe = "创建一个新的Lerna仓库";
exports.builder = (yargs) => {
  console.log("执行init builder");
};
exports.handler = (argv) => {
  console.log("执行init命令", argv);
};

13.4 lerna4\package.json #

packages\lerna4\package.json

+  "main": "index.js"

13.5 lerna4\index.js #

packages\lerna4\index.js

const cli = require('@lerna4/cli');
const initCmd = require('@lerna4/init/command');
function main(argv) {
  return cli().command(initCmd).parse(argv);
}

module.exports = main;

14.实现 init 命令 #

14.1 安装依赖 #

lerna add fs-extra  packages/init
lerna add  execa  packages/init

14.2 init\command.js #

packages\init\command.js

exports.command = "init";
exports.describe = "创建一个新的Lerna仓库";
exports.builder = () => {
  console.log("执行init builder");
};
exports.handler = (argv) => {
  console.log("执行init命令", argv);
  return require(".")(argv);
};

14.3 packages\init\index.js #

packages\init\index.js

const path = require("path");
const fs = require("fs-extra");
const execa = require("execa");

class InitCommand {
  constructor(argv) {
    this.argv = argv;
    this.rootPath = path.resolve();
  }
  async execute() {
    await execa("git", ["init"], { stdio: "pipe" });
    await this.ensurePackageJSON();
    await this.ensureLernaConfig();
    await this.ensurePackagesDir();
    console.log("Initialized Lerna files");
  }
  async ensurePackageJSON() {
    console.log("创建 package.json");
    await fs.writeJson(
      path.join(this.rootPath, "package.json"),
      {
        name: "root",
        private: true,
        devDependencies: {
          lerna: "^4.0.0",
        },
      },
      { spaces: 2 }
    );
  }
  async ensureLernaConfig() {
    console.log("创建 lerna.json");
    await fs.writeJson(
      path.join(this.rootPath, "lerna.json"),
      {
        packages: ["packages/*"],
        version: "0.0.0",
      },
      { spaces: 2 }
    );
  }
  async ensurePackagesDir() {
    console.log("创建 packages 目录");
    await fs.mkdirp(path.join(this.rootPath, "packages"));
  }
}
function factory(argv) {
  new InitCommand(argv).execute();
}
module.exports = factory;

15.实现 create 命令 #

  • pify
  • dedent
  • init-package-json

15.1 安装依赖 #

lerna add pify  packages/crate
lerna add  init-package-json  packages/crate
lerna add  dedent  packages/crate

15.2 lerna4\index.js #

packages\lerna4\index.js

const cli = require('@lerna4/cli');
const initCmd = require('@lerna4/init/command');
const createCmd = require('@lerna4/create/command');
function main(argv) {
  return cli()
   .command(initCmd)
+  .command(createCmd)
   .parse(argv);
}

module.exports = main;

15.3 lerna4\package.json #

packages\lerna4\package.json

{
  "dependencies": {
    "@lerna4/cli":"^0.0.4",
    "@lerna4/init":"^0.0.4",
+   "@lerna4/create":"^0.0.4"
  },
}

15.4 create\command.js #

packages\create\command.js

exports.command = "create <name>";
exports.describe = "创建一个新的lerna管理的包";
exports.builder = (yargs) => {
  console.log("执行init builder");
  yargs
    .positional("name", {
      describe: "包名(包含scope)",
      type: "string",
    })
    .options({
      registry: {
        group: "Command Options:",
        describe: "配置包的发布仓库",
        type: "string",
      },
    });
};
exports.handler = (argv) => {
  console.log("执行create命令", argv);
  return require(".")(argv);
};

15.5 create\index.js #

packages\create\index.js

const path = require("path");
const fs = require("fs-extra");
const dedent = require("dedent");
const initPackageJson = require("pify")(require("init-package-json"));
class CreateCommand {
  constructor(options) {
    this.options = options;
    this.rootPath = path.resolve();
    console.log("options", options);
  }
  async execute() {
    const { name, registry } = this.options;
    this.targetDir = path.join(this.rootPath, "packages/cli");
    this.libDir = path.join(this.targetDir, "lib");
    this.testDir = path.join(this.targetDir, "__tests__");
    this.libFileName = `${name}.js`;
    this.testFileName = `${name}.test.js`;
    await fs.mkdirp(this.libDir);
    await fs.mkdirp(this.testDir);
    await this.writeLibFile();
    await this.writeTestFile();
    await this.writeReadme();
    var initFile = path.resolve(process.env.HOME, ".npm-init");
    await initPackageJson(this.targetDir, initFile);
  }
  async writeLibFile() {
    const libContent = dedent`
        module.exports = ${this.camelName};
        function ${this.camelName}() {
            // TODO
        }
    `;
    await catFile(this.libDir, this.libFileName, libContent);
  }
  async writeTestFile() {
    const testContent = dedent`
    const ${this.camelName} = require('..');
    describe('${this.pkgName}', () => {
        it('needs tests');
    });
  `;
    await catFile(this.testDir, this.testFileName, testContent);
  }
  async writeReadme() {
    const readmeContent = dedent`## Usage`;
    await catFile(this.targetDir, "README.md", readmeContent);
  }
}
function catFile(baseDir, fileName, content) {
  return fs.writeFile(path.join(baseDir, fileName), `${content}\n`);
}
function factory(argv) {
  new CreateCommand(argv).execute();
}

module.exports = factory;

16.参考 #

16.1 lerna 命令 #

项目初始化 #

命令 说明
lerna init 初始化项目

16.2 创建包 #

命令 说明
lerna create 创建 package
lerna add 安装依赖
lerna link 链接依赖

16.3 开发和测试 #

命令 说明
lerna exec 执行 shell 脚本
lerna run 执行 npm 命令
lerna clean 清空依赖
lerna bootstrap 重新安装依赖

16.4 发布上线 #

命令 说明
lerna version 修改版本号
lerna changed 查看上个版本以来的所有变更
lerna diff 查看 diff
lerna publish 发布项目

17.格式化提交 #

17.1 Conventional Commits #

  • 规范化的git commit可以提高git log可读性,生成格式良好的changelog
  • Conventional Commits 是一种用于给提交信息增加人机可读含义的规范
  • 它提供了一组简单规则来创建清晰的提交历史
  • 通过在提交信息中描述功能、修复和破坏性变更,使这种惯例与 semver 相互对应
<类型>[可选 范围]: <描述>

[可选 正文]

[可选 脚注]

17.2 类型(type) #

  • feat: 类型 为 feat 的提交表示在代码库中新增了一个功能(这和语义化版本中的 MINOR 相对应)
  • fix: 类型 为 fix 的提交表示在代码库中修复了一个 bug(这和语义化版本中的 PATCH 相对应)
  • docs: 只是更改文档
  • style: 不影响代码含义的变化(空白、格式化、缺少分号等)
  • refactor: 代码重构,既不修复错误也不添加功能
  • perf: 改进性能的代码更改
  • test: 添加确实测试或更正现有的测试
  • build: 影响构建系统或外部依赖关系的更改(示例范围:gulp、broccoli、NPM)
  • ci: 更改持续集成文件和脚本(示例范围:Travis、Circle、BrowserStack、SauceLabs)
  • chore: 其他不修改 src 或 test 文件。
  • revert: commit 回退

17.3 范围(scope) #

  • 可以为提交类型添加一个围在圆括号内的作用域,以为其提供额外的上下文信息

访问验证

请输入访问令牌

Token不正确,请重新输入