After a long time did not update the NPM source analysis series, also do not know is more busy or more busy, in short, continued today.

In daily development and debugging, it is often necessary to read the source code directly to find the problem clues faster.

My personal habit is to bring the git-clone source library locally and quickly switch files in VsCode to view the source code. Working with Octotree on Github is fine, but it’s never as fast as switching files locally. There may be many other ways, you can post them in the comments section, maybe you can get some of your tricks and tricks. Without further ado, let’s get straight to the point of this article.

NPM provides a command to quickly access github’s source code page, called NPM repo XXX.

Implementation logic

If you are not familiar with how NPM is started, you can take a look at the principle of NPM startup and the export logic of each command.

For those of you familiar with it, let’s go straight to rebo.js in the lib directory

function repo (args, cb) {  const n = args.length ? args[0] : '.'  fetchPackageMetadata(n, '.', {fullMetadata: true}, function (er, d) {    if (er) return cb(er)    getUrlAndOpen(d, cb)  })}
Copy the code

* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * Then automatically open the browser to access the corresponding Github source page.

When developing a custom NPM package, try to maintain Git repository address information in it

The logic to get Git repository location information is all in getUrlAndOpen, and the function name is a good way to see what it does.

function getUrlAndOpen (d, cb) { const r = d.repository if (! R) return cb(new Error('no repository')) // XXX remove this when [email protected] from node 0.10 is deprecated // from const info = hostedGitInfo.fromUrl(r.url) const url = info ? info.browse() : unknownHostedUrl(r.url) if (! url) return cb(new Error('no repository: could not get url')) openUrl(url, 'repository available at the following URL', cb)}Copy the code

Want to mention here [hosted – git – info] ( this bag. Support for the mainstream source hosting platform host resolution and all kinds of page address generation, through it can be very convenient to get a variety of forms of Git repository address links.

So far, all the logic is very simple and coherent, but the most important step is missing, which is fetchPackageMetadata.

That is, how to get the source information of the corresponding NPM package?

function fetchPackageMetadata (spec, where, opts, done) { ... pacote.manifest(dep, npmConfig({ annotate: true, fullMetadata: opts.fullMetadata, log: tracker || npmlog, memoize: CACHE, where: where })).then( (pkg) => logAndFinish(null, deprCheck(pkg)), (err) => { ... })}Copy the code

Here I intercept the core logic and use the NPM architecture to build pacote, one of the core dependencies.

Core capabilities include reading manifest, extracting source code, pulling tarballs, and so on. When developing custom NPM packages, it makes it very easy to handle dependency packages.

It not only has API form, but also can be used directly as cli, which is more convenient.

const pacote = require('pacote') // get a package manifest pacote.manifest('[email protected]').then(manifest => console.log('got it', manifest)) // extract a package into a folder pacote.extract('github:npm/cli', 'some/path', options) .then(({from, resolved, integrity}) => { console.log('extracted! ', from, resolved, integrity) }) pacote.tarball('').then(data => { console.log('got ' + data.length + ' bytes  of tarball data') })Copy the code

NPM repo uses pacote.manifest to extract package source information, similar to package.json, and then passes package.repository to getUrlAndOpen.

Different way of thinking

Git repository: Git repository: Git repository: Git repository: Git repository: Git repository: Git repository: Git repository: Git repository: Git repository Go straight to Pacote.

The following code logic is extracted from a tool I wrote myself, the main function is to rely on Pacote to implement git-Clone source code library to the local.

async function resolveSourceCodeGitClone(argv) { const [, , package] = argv._; if (! package) { log('Npm package is undefined\n'); process.exit(0); } else { const { name, repository = {} } = await pacote.manifest(package, { fullMetadata: true, where: '.', }); console.log('package repository: ', repository); const { url } = repository; if (! url) { log('Npm package repository not found'); process.exit(0); } const info = hostedGitInfo.fromUrl(url); if (! info) { log('Npm package repository not found'); process.exit(0); } const repo = info.https({ noGitPlus: true }); console.log('repo: ', repo); console.log('source: ', source); await runScript('git', ['clone', repo, name], { cwd: source }); }}Copy the code


Through the source code reading to solve the problems in daily development, often the efficiency is relatively high, but also better familiar with these dependent packages, to further broaden their coding breadth. Must master such commands as NPM repo, in the source code read a step faster, from now on to develop the habit of reading source code often!

Previous NPM source code analysis series

  1. NPM start
  2. NPM configuration setup and read
  3. NPM install analysis
  4. NPM help analysis