前端架构师必备脚手架小知识(四)

543 阅读2分钟

这是我参与11月更文挑战的第28 天,活动详情查看:2021最后一次更文挑战

前端架构师必备脚手架小知识(四)

  • lerna 源码结构分析和调试技巧
  • Node 源码调试过程中必会的小技巧
  • learna 初始化过程源码详细分析
  • [高级] npm 项目本地依赖引用方法

为什么要做源码分析?

  • 自我成长、提升编码能力和技术深度的需要
  • 为我所用、应用到实际开发,实际产生效益
  • 学习借鉴、站在巨人肩膀上,登高望远

为什么要分析Lerna源码?

  • 3W+ Star 的明星项目
  • Lerna是脚手架,对开发脚手架有借鉴价值
  • Lerna 项目蕴含大量最佳实践, 值得深入研究和学习

目标 / 产出

  • Lerna源码结构和执行流程分析

  • import-local 源码深度精度

  • 脚手架执行流程的一种实现思路

  • 脚手架调试本地源码的一种方法

  • Node.js加载node_modules模块的流程

  • 各种文件操作算法和最佳实践

Lerna 4.0.0 源码结构分析

源码仓库 github.com/lerna/lerna

目录结构

$ 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. 第一步要在需要执行的地方打上断点

image-20211123021525341.png

2.第二部配置 debug

image-20211123021723021.png

image-20211123021836893.png

image-20211123022116539.png

开始 Debug 模式 image-20211123022252650.png