Skip to content

Instantly share code, notes, and snippets.

@Frezc
Created September 5, 2020 08:05
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Frezc/135542be7c79ccc05d941dc8a168297e to your computer and use it in GitHub Desktop.
Save Frezc/135542be7c79ccc05d941dc8a168297e to your computer and use it in GitHub Desktop.
yarn依赖分析
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