Build scaffolding based on Lerna

  • Create a folder;

    mkdir xxx-cli
    cd xxx-cli
    Copy the code
  • Initialize the NPM project

    npm init -y
    Copy the code
  • Install lerna

    npm i lerna -D
    npm i lerna -g
    Copy the code
  • Lerna initialization (initialization creates lerna.json, which initializes git)

    lerna init
    Copy the code
  • Manually create.gitignore

    Idea node_modules packages/**/node_modulesCopy the code
  • Create a new lerna managed package

    Lerna create XXX [loc]Copy the code
  • Add the dependent

    Lerna add <package>[@version] [--dev] [--exact] [--peer] Install XXX -cli/utils lerna add @xxx-cli/utils Clear all lerna installation directories Lerna add@xxx - CLI /utils Packages /coreCopy the code
  • Develop test

    Install dependencies and add soft link lerna Bootstrap dependencies, Lerna exec -- <command> [..args] delete all dependencies lerna exec -- rm -rf./node_modules run lerna exec -- <command> [..args] in all packages Lerna exec --scope @xxx-cli/core -- rm -rf./node_modules testCopy the code
  • Published online

    Bump version number Lerna version Which packages have changed Lerna changed View diff Lerna Diff project initialization git add. Git commit -m 'init' create repository association remote link git remote add origin [email protected]:.... Git push origin master --set-upstream publish git push origin master --set-upstream publishCopy the code
  • The problem

    "PublishConfig ": {"access": "public"} 2. Add license.mdCopy the code

Lerna source code analysis

Local debugging methods
NPM link unlink lerna is better than NPM link "@lerna/add": "file:.. /.. /commands/add" Lerna project publish calls updateLocalDependency on "file:.. /.. /commands/add" becomes an online linkCopy the code
Event Loop

In JavaScript, tasks are divided into two types: MacroTask and MicroTask.

  • Macro task

    Script All code, setTimeout, setInterval, setImmediate, I/O, UI Rendering

  • Micro tasks

    Process.nextTick(unique to Node), Promise, Object.observe(deprecated), MutationObserver

JavaScript

  • Executing macro tasks
  • The macro tasks are put into the execution stack (last in, first out) and executed in sequence. The micro tasks are put into the micro task queue and the macro tasks are put into the macro task queue
  • Check the microtask queue. If there are any tasks, put the microtasks on the execution stack and execute them successively until the microtask queue is empty
  • View the macro task queue, loop to 1

Node

  • When each phase is complete, if a nextTick queue exists, all callbacks in the queue are emptied and take precedence over other micro-tasks (Micro)
Module._nodeModulePaths (Generate all possible paths for node_modules)
const paths = []; For (let I = from. Length - 1, p = 0, last = from. Length; i >= 0; -- I) {// get current code const code = from. CharCodeAt (I); if (code === '/' || code === '\' || code === ':') { if (p ! == nmLen) // Node_modules paths.push(from. Slice (0, last) + '\\node_modules'); last = i; p = 0; } else if (p ! == -1) {// Node_modules if (nmChars[p] === code) {// The number of matched characters ++p; } else { p = -1; }}}Copy the code
Module._resolvefilename (the real path to resolve the Module)
NativeModule. CanBeRequiredByUsers (request) / / / / whether the built-in Module node_modules environment variables in the path with the Module. The _nodeModulePaths merge the path of the generated paths Module._resolveLookupPaths module. _findPath // Parse the true path of the Module in the Paths sectionCopy the code
Module._findPath
Split ('\x00') const cacheKey = request + '\x00' + (paths.length === 1? paths[0] : paths.join('\x00')); // Find cache const entry = module. _pathCache[cacheKey]; if (entry) return entry; // The file exists // Call toRealPath to generate the real file pathCopy the code
toRealPath
Fs. realpathSync The process is as follows: Query whether the cache path exists or whether to query the realpath for the soft connection. Cache Soft connection file cache The mapping between the current path and the realpath is searched periodically until the realpath is not the soft connectionCopy the code
/ (? : ^ | \ \. /)? \.$/. Matches any string \. Match point? Matches zero or one character /\.? \./ Match two dots /\.? \.$/ The matching point () at the end indicates the need to return the matching result. : don't not match group, the group points displayed content [. ^ \] don't match point / ^ \. / a point / ^ / match a space / ^ | \ matching Spaces or / / /Copy the code
Pay attention to
// require('.') // require('./index.js') path.resolve Path to merge two paths path.dirname files Fs.exists The fs.accesssync path-exists library '/ XXX /yy'.indexof ('/', I) // the I/is deprecatedCopy the code