这是我参与11月更文挑战的第28 天,活动详情查看:2021最后一次更文挑战
前端架构师必备脚手架小知识(四)
- lerna 源码结构分析和调试技巧
- Node 源码调试过程中必会的小技巧
- learna 初始化过程源码详细分析
- [高级] npm 项目本地依赖引用方法
为什么要做源码分析?
- 自我成长、提升编码能力和技术深度的需要
- 为我所用、应用到实际开发,实际产生效益
- 学习借鉴、站在巨人肩膀上,登高望远
为什么要分析Lerna源码?
- 3W+ Star 的明星项目
- Lerna是脚手架,对开发脚手架有借鉴价值
- Lerna 项目蕴含大量最佳实践, 值得深入研究和学习
目标 / 产出
-
Lerna源码结构和执行流程分析
-
import-local
源码深度精度 -
脚手架执行流程的一种实现思路
-
脚手架调试本地源码的一种方法
-
Node.js加载node_modules模块的流程
-
各种文件操作算法和最佳实践
Lerna 4.0.0 源码结构分析
目录结构
$ tree -I "node_modules" -L 2
.
├── CHANGELOG.md
├── CODE_OF_CONDUCT.md
├── CONTRIBUTING.md
├── FAQ.md
├── LICENSE
├── README.md
├── __fixtures__
│ ├── __independent
│ ├── __normal
│ ├── cycle-intersection
│ ├── cycle-parent
│ ├── cycle-separate
│ ├── independent
│ ├── licenses
│ ├── licenses-missing
│ ├── licenses-names
│ ├── lifecycle
│ ├── lifecycle-rooted-leaf
│ ├── lockfile-leaf
│ ├── normal
│ ├── normal-exact
│ ├── pack-directory
│ ├── prerelease
│ ├── prerelease-independent
│ ├── root-manifest-only
│ ├── toposort
│ └── yarn-link-spec
├── commands
│ ├── __mocks__
│ ├── add
│ ├── bootstrap
│ ├── changed
│ ├── clean
│ ├── create
│ ├── diff
│ ├── exec
│ ├── import
│ ├── info
│ ├── init
│ ├── link
│ ├── list
│ ├── publish
│ ├── run
│ └── version
├── core
│ ├── child-process
│ ├── cli
│ ├── command
│ ├── conventional-commits
│ ├── filter-options
│ ├── global-options
│ ├── lerna
│ ├── otplease
│ ├── package
│ ├── package-graph
│ ├── project
│ ├── prompt
│ └── validation-error
├── doc
│ ├── guides.md
│ ├── hoist.md
│ └── troubleshooting.md
├── helpers
│ ├── calls-back
│ ├── cli-runner
│ ├── clone-fixture
│ ├── command-runner
│ ├── commit-change-to-package
│ ├── copy-fixture
│ ├── find-fixture
│ ├── get-commit-message
│ ├── git-add
│ ├── git-checkout
│ ├── git-commit
│ ├── git-init
│ ├── git-merge
│ ├── git-status
│ ├── git-tag
│ ├── init-fixture
│ ├── init-named-fixture
│ ├── load-manifests
│ ├── logging-output
│ ├── multi-line-trim-right
│ ├── normalize-relative-dir
│ ├── pkg-matchers
│ ├── serialize-changelog
│ ├── serialize-git-sha
│ ├── serialize-placeholders
│ ├── serialize-tempdir
│ ├── serialize-windows-paths
│ ├── set-npm-userconfig
│ ├── show-commit
│ ├── silence-logging
│ └── update-lerna-config
├── integration
│ ├── __fixtures__
│ ├── lerna-add.test.js
│ ├── lerna-bootstrap-ci.test.js
│ ├── lerna-bootstrap-hoist.test.js
│ ├── lerna-bootstrap-legacy.test.js
│ ├── lerna-bootstrap-yarn.test.js
│ ├── lerna-changed.test.js
│ ├── lerna-clean.test.js
│ ├── lerna-exec-since.test.js
│ ├── lerna-exec.test.js
│ ├── lerna-import.test.js
│ ├── lerna-init.test.js
│ ├── lerna-link-sibling-bins.test.js
│ ├── lerna-ls.test.js
│ ├── lerna-publish-auth.test.js
│ ├── lerna-publish-canary.test.js
│ ├── lerna-publish-conventional-fixed-prerelease.test.js
│ ├── lerna-publish-conventional-fixed.test.js
│ ├── lerna-publish-conventional-independent-prerelease.test.js
│ ├── lerna-publish-conventional-independent.test.js
│ ├── lerna-publish-custom-tag.test.js
│ ├── lerna-publish-error.test.js
│ ├── lerna-publish-fixed.test.js
│ ├── lerna-publish-independent.test.js
│ ├── lerna-publish-lifecycle-errors.test.js
│ ├── lerna-publish-lifecycle-silent.test.js
│ ├── lerna-publish-lifecycle.test.js
│ ├── lerna-publish-relative-file-spec.test.js
│ ├── lerna-publish-skip-npm.test.js
│ ├── lerna-publish-transitive.test.js
│ ├── lerna-publish-validation.test.js
│ ├── lerna-run-since.test.js
│ └── lerna-run.test.js
├── jest.config.js
├── jest.integration.js
├── lerna.json
├── package-lock.json
├── package.json
├── scripts
│ └── update_dependency.sh
├── setup-integration-timeout.js
├── setup-unit-test-timeout.js
└── utils
├── check-working-tree
├── collect-uncommitted
├── collect-updates
├── create-symlink
├── describe-ref
├── filter-packages
├── get-npm-exec-opts
├── get-packed
├── github-client
├── gitlab-client
├── has-npm-version
├── listable
├── log-packed
├── map-to-registry
├── npm-conf
├── npm-dist-tag
├── npm-install
├── npm-publish
├── npm-run-script
├── output
├── pack-directory
├── prerelease-id-from-version
├── profiler
├── pulse-till-done
├── query-graph
├── resolve-symlink
├── rimraf-dir
├── run-lifecycle
├── run-topologically
├── symlink-binary
├── symlink-dependencies
├── timer
└── write-log-file
通过根目录下的 package.json 找到工作区 workspaces, [ "commands/", "core/", "utils/*" ]
找到 core/lerna 目录下 package.json 找到入口文件 cli.js
// cli.js
#!/usr/bin/env node
"use strict";
/* eslint-disable import/no-dynamic-require, global-require */
const importLocal = require("import-local");
if (importLocal(__filename)) {
require("npmlog").info("cli", "using local version of lerna");
} else {
require(".")(process.argv.slice(2));
}
WebStorm 使用 Debug 调试 Lerna 代码
0. 执行命令lerna boostrap
安装所有包的依赖
1. 第一步要在需要执行的地方打上断点
2.第二部配置 debug
开始 Debug 模式