搭建脚手架步骤流程:
- 在自己的目录新建一个文件夹,命名为
test-hp-cli - 进入文件夹,执行命令
npm init -y - 根目录新建bin文件夹,在目录下新建index.js文件
- 在index.js文件中文件最上方写入以下代码
javascript
#!/usr/bin/env node
console.log('hello world');
- 在package.json文件中,修改bin字段为
"bin": "bin/index.js" - 执行命令
npm link,在全局环境下创建一个软链接到当前目录的node_modules文件夹下。这样就可以在任何地方通过命令行使用该脚手架了。例如:test-hp-cli hello world - 如果要发布到npm上,需要先注册一个账号,然后登录npm,再执行以下命令即可上传包:
npm publish --access public
发布npm包的方法:
- 登录npm账号:
npm login, 输入用户名、密码和邮箱 - 发布包失败,可能是因为包名已经被占用或者不符合npm的命名规范。可以尝试修改包名为其他名称,例如将
test-hp-cli改为@test/hp-cli
-
npm全局安装脚手架:
npm install -g test-hp-cli -
执行脚手架命令:
test-hp-cli,执行失败提示没有这个命令,检查package.json中的bin字段是否正确,key值需要和包名一致。例如"test-hp-test": "bin/index.js" -
修改包名后重新发布,需要更新版本号,否则也会发布失败。例如
npm version patch,然后重新发布:npm publish代表执行成功的提示信息:

- 如何安装远程版本,不使用本地的软链接
调试本地脚手架:
- 进入到脚手架目录执行
npm i -g test-hp-cli,查看bin目录下文件链接的路径可以看出来是链接到本地的 - 执行
npm link后,会在Node_modules中创建一个test-hp-cli的命令,命令链向的是node_modules下的test-hp-cli目录,node_modules下的test-hp-cli又链向本地的hp-test。
未发布的包如何调试:
- 进入到脚手架目录执行
npm link,此时会在全局环境下创建一个软链接到当前目录的node_modules文件夹下。这样就可以在任何地方通过命令行使用该脚手架了
注册命令&参数解析
-
process.argv可以获取到命令行参数,执行结果 -

-
选项和参数解析

lerna
是一个基于git+npm的多package项目的管理工具 为了解决什么问题?
- 解决脚手架开发过程中的一些重复性操作
- 场景一:例如开发一个大型项目,依赖一个工具类的包,如果这个包更新后怎么更新其他的包(需要npm link)n遍进行验证
- 场景二:依赖版本全部更新,需要手动删除node_modules并且重新执行npm i,并且package.json是自动增减的不可能手动增加
- 场景三:多package单元测试
- 代码提交,大型项目都共用的同给一个仓库
- 代码发布,每个包都要发一个单独的npm包,发布难以管理
- 版本一致性问题
- 发布时版本一致性,版本一致性的好处:升级时一起升级,否则开发时需要不停的版本调试,版本一致性时只需要保证当前的版本即可,不会存在向上和向下兼容问题
- 发布后项目依赖版本升级 优势:
- 大幅度减少重复操作
- 提升操作标准化
架构优化目的:项目复杂度提升后,需要对项目进行架构优化,架构优化的主要目标往往以提升效能为核心。 使用lerna的项目参考:
- babel github.com/babel/babel...
- vue-cli
- create-react-app
创建脚手架
- 创建文件夹test-cli-dev
- 在test-cli-dev下再创建test-cli-dev目录
- 执行
cnpm i -D lerna - 执行
lerna init可能会报错 解决方法: - 在package.json中添加如下代码:

json
"workspaces": [
"packages/*"
],
重新执行lerna init会生成如下内容: 帮我们自动生成了gitignore,lerna.json等文件

-
创建
package->lerna create创建core包lerna create core修改package name为@test-cli-dev/core这样命名
"name": "@test-cli-dev/utils",的好处是在npm上可以防止目录重复,npm i安装后的目录结构如下:

lerna addv7之前的版本使用,对照表
使用lerna add命令会报如下错误:
v8版本需要结合pnpm使用,教程参考:lerna.js.org/docs/recipe... 本地依赖,教程参考:pnpm.io/workspaces
- 将包安装在某个特定的空间
命令pnpm add @test-cli-dev/utils --filter @test-cli-dev/core,关于filter命令参考:pnpm.io/zh/filterin...- 全局安装依赖
pnpm add -w @test-cli-dev/utils会在和lerna.json平级的packages.json中新增如下配置:
less
"dependencies": {
"@test-cli-dev/utils": "workspace:^"
}
发布流程: lerna publish,发布之前必须要进行一次代码提交,否则会报错 发布后默认没有公开发布时私有的,可以通过命令进行配置文档参考:pnpm.io/zh/cli/publ...
lerna 源码分析
调试代码:lerna仓库:github.com/lerna/lerna 项目结构:从项目介绍中可以知道主要的目录为一下6个
- e2e 端到端测试,用来模拟用户场景,验证程序能否正常运行
- integration 一些遗留代码,包含端到端和单元测试内容,新的e2e测试已经覆盖这些场景,应该优先用e2e
- libs 源码库,用于组合发布包
- packages 要发布到npm上的包
- tools 一些js工具类
- website 站点展示也就是lerna官网 入口文件:
packages\lerna\package.json,可以查看其中的bin配置,找到入口文件,发现是
json
"bin": {
"lerna": "dist/cli.js"
},
而不是src/cli.js,为什么要这么配呢? 原因:lerna的源码是ts项目(nodejs无法运行),而npm包需要发布的是编译后的、可执行的js代码,dist目录就是准备被发布的最终产品目录。 如果是这样我们怎么进行调试呢?
- 添加调试文件,可以让ai读整个项目自己生成一份
bash
{
"version": "0.2.0",
"configurations": [
{
"name": "Debug Lerna CLI",
"type": "node",
"request": "launch",
"runtimeExecutable": "node",
"program": "${workspaceFolder}/packages/lerna/src/index.ts",
"args": ["init"],
"sourceMaps": true,
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"restart": true,
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
},
{
"name": "Debug Lerna Build",
"type": "node",
"request": "launch",
"runtimeExecutable": "npm",
"runtimeArgs": ["run", "build"],
"console": "integratedTerminal",
"internalConsoleOptions": "neverOpen"
},
{
"name": "Debug Specific Command",
"type": "node",
"request": "launch",
"runtimeExecutable": "node",
"program": "${workspaceFolder}/packages/lerna/src/index.ts",
"args": ["version", "--no-git-tag-version", "--no-push"],
"sourceMaps": true,
"outFiles": ["${workspaceFolder}/dist/**/*.js"],
"restart": true,
"skipFiles": ["<node_internals>/**"],
"console": "integratedTerminal"
}
]
}
- 执行
npm run build命令,生成dist文件,否则运行时bin文件配置会找不到