Created
September 5, 2020 08:05
-
-
Save Frezc/135542be7c79ccc05d941dc8a168297e to your computer and use it in GitHub Desktop.
yarn依赖分析
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
const fs = require('fs'); | |
const path = require('path'); | |
const pkg = require('./package.json'); | |
const { execSync } = require('child_process'); | |
const yarntree = JSON.parse(execSync('yarn list --json')); | |
// 排除的依赖 | |
const exceptList = [ | |
]; | |
// 不再显示依赖的库 | |
const noChildrenList = [ | |
]; | |
const baseDeps = [ | |
]; | |
let tree = filterChildren(yarntree.data.trees); | |
constructSubTree(tree, tree); | |
tree = tree.filter(({ name }) => [pkg.dependencies || [], pkg.peerDependencies || []].some((deps) => deps[name.slice(0, name.lastIndexOf('@'))])); | |
checkCompiled(tree); | |
// fs.writeFileSync('./yarntreere.json', JSON.stringify(simplifyTree(tree), null, 2)); | |
fs.writeFileSync('./yarntreere.text', logTree(findBaseDeps(tree, baseDeps))); | |
fs.writeFileSync('./uplist.text', logSet(findBaseDeps(tree, baseDeps))); | |
// 去掉所有非@qunhe开头的依赖 | |
function filterChildren(list) { | |
return list.filter(({ name }) => name.startsWith('@qunhe/') && !exceptList.find((except) => getName(name) === except)) | |
.map((dep) => { | |
if (dep.children) { | |
dep.children = filterChildren(dep.children); | |
} | |
return dep; | |
}); | |
} | |
// 将子树拼到相应位置 | |
function constructSubTree(tree, list) { | |
tree.forEach((dep) => { | |
const name = getName(dep.name); | |
if (noChildrenList.includes(name)) { | |
dep.children = []; | |
} else if (dep.children && dep.children.length > 0) { | |
constructSubTree(dep.children, list); | |
} else { | |
const d = list.find((dep1) => getName(dep1.name) === name); | |
dep.children = d.children; | |
dep.name = d.name; | |
} | |
}); | |
} | |
function getName(nv) { | |
return nv.slice(0, nv.lastIndexOf('@')); | |
} | |
function logTree(tree, isLastList = []) { | |
return tree.map((t, i) => { | |
let prefix = ''; | |
if (isLastList.length > 0) { | |
prefix += isLastList.map((isLast) => isLast ? ' ' : '│ ').join(''); | |
} | |
const isLast = i === tree.length - 1; | |
if (isLast) { | |
prefix += '└─ ' | |
} else { | |
prefix += '├─ ' | |
} | |
let re = `${prefix}${t.name}${t.compiled ? ' [compiled]' : ''}\n`; | |
if (t.children) { | |
re += logTree(t.children, isLastList.concat(isLast)); | |
} | |
return re; | |
}).join(''); | |
} | |
function getDistinctDeps(tree, filter = () => true) { | |
const result = new Set(); | |
tree.forEach((dep) => { | |
if (filter(dep)) { | |
result.add(getName(dep.name)); | |
} | |
if (dep.children) { | |
getDistinctDeps(dep.children, filter).forEach((d) => { | |
result.add(d); | |
}); | |
} | |
}); | |
return result; | |
} | |
function logSet(tree) { | |
const compiled = getDistinctDeps(tree, (dep) => dep.compiled); | |
const others = getDistinctDeps(tree, (dep) => !dep.compiled); | |
let result = '[compiled]\n'; | |
compiled.forEach((name) => { | |
result += `${name}\n`; | |
}); | |
result += '\n[raw]\n'; | |
others.forEach((name) => { | |
result += `${name}\n`; | |
}); | |
return result; | |
} | |
// lib是否被编译成js | |
function checkCompiled(tree) { | |
tree.forEach((dep) => { | |
const pkg = require(`./node_modules/${getName(dep.name)}/package.json`); | |
let checkPath = `./node_modules/${getName(dep.name)}`; | |
if (pkg.main) { | |
const ext = path.extname(pkg.main); | |
if (ext === '.ts' || ext === '.tsx') { | |
dep.compiled = false; | |
} else { | |
checkPath = path.join(checkPath, pkg.main); | |
if (!ext) { | |
checkPath += '.js'; | |
} | |
dep.compiled = fs.existsSync(checkPath); | |
} | |
} else { | |
checkPath = path.join(checkPath, 'index.js'); | |
dep.compiled = fs.existsSync(checkPath); | |
} | |
if (dep.children) { | |
checkCompiled(dep.children); | |
} | |
}); | |
} | |
// 找到所有以baseDeps为基础依赖的库 | |
function findBaseDeps(tree, baseDeps) { | |
let result = []; | |
tree.forEach((dep) => { | |
if (baseDeps.includes(getName(dep.name))) { | |
result.push({ | |
name: dep.name, | |
compiled: dep.compiled, | |
}); | |
} else if (dep.children) { | |
const deps = findBaseDeps(dep.children, baseDeps); | |
if (deps.length > 0) { | |
result.push({ | |
name: dep.name, | |
compiled: dep.compiled, | |
children: deps, | |
}); | |
} | |
} | |
}); | |
return result; | |
} | |
// function calc | |
function simplifyTree(tree) { | |
return tree.map((dep) => { | |
const node = { | |
name: dep.name, | |
}; | |
if (dep.children) { | |
node.children = simplifyTree(dep.children); | |
} | |
return node; | |
}); | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment