@speedy-js/depcost
Version:
[](https://npm.im/@speedy-js/depcost)
198 lines (169 loc) • 5.36 kB
JavaScript
const fs = require('fs-extra')
const path = require('path')
const log = require('npmlog')
const execa = require('execa')
const requireFromString = require('require-from-string')
const { DepCost, DepCostEvents } = require('./dep-cost')
const requirePkg = require('./require-pkg')
const loadConfig = require('./load-config')
function getPkgByDependencies(dependencies) {
return Object.keys(dependencies).map(name => {
const range = dependencies[name]
let version
if (range === '*') {
version = ''
} else {
version = range.replace(/^(~|\^)/, '')
}
return version ? `${name}@${version}` : name
})
}
module.exports = async opts => {
opts.cwd = opts.cwd || process.cwd()
let masterPkgName = ''
let pkgs = opts.pkgs || []
if (opts.debug) {
opts.logLevel = 'debug'
}
const localConfig = await loadConfig()
opts = {
npmClient: 'npm',
...localConfig,
...opts,
}
let dependencies = {}
let devDependencies = {}
if (opts.dependencies || opts.devDependencies) {
if (opts.pkgs.length > 1) {
throw new Error(`length of pkgs under 'dependencies' or 'devDependencies' mode should be 1 or 1, but got ${pkgs}`)
}
const currentPkg = pkgs[0]
if (currentPkg) {
masterPkgName = currentPkg
// TODO Error handling
if (opts.allDependencies || opts.dependencies) {
const { stdout } = await execa(opts.npmClient, ['view', currentPkg, 'dependencies'])
dependencies = requireFromString(`module.exports = ${stdout}`)
}
if (opts.allDependencies || opts.devDependencies) {
const { stdout } = await execa(opts.npmClient, ['view', currentPkg, 'devDependencies'])
devDependencies = requireFromString(`module.exports = ${stdout}`)
}
} else {
const packageJson = requirePkg(opts.cwd)
masterPkgName = packageJson.name
if (opts.allDependencies || opts.dependencies) {
dependencies = packageJson.dependencies
}
if (opts.allDependencies || opts.devDependencies) {
devDependencies = packageJson.devDependencies
}
}
const dependenciesPkgs = getPkgByDependencies(dependencies)
const devDependenciesPkgs = getPkgByDependencies(devDependencies)
if (opts.allDependencies) {
pkgs = [...dependenciesPkgs, ...devDependenciesPkgs]
} else if (opts.dependencies) {
pkgs = dependenciesPkgs
} else if (opts.devDependencies) {
pkgs = dependenciesPkgs
}
} else if (opts.monorepo) {
const loadMonorepoPackages = require('./load-monorepo-packages')
const monorepoPaackages = loadMonorepoPackages(opts.cwd)
.filter(pkg => !!(pkg.name && pkg.version && !pkg.private))
.map(pkg => `${pkg.name}@${pkg.version}`)
pkgs = [
...pkgs,
...monorepoPaackages,
]
}
log.level = opts.logLevel || 'warn'
log.info('pkgs', pkgs)
log.info('opts', opts)
const program = new DepCost({
...opts,
pkgs,
})
let isFirst = false
const results = []
program.on(DepCostEvents.message, result => {
results.push(result)
if (opts.table) {
if (!isFirst) {
isFirst = true
console.log(`| name | install size | reuqire time |
| --- | --- | --- |`)
}
console.log(
`| ${result.pkg} | ${result.size} | ${result.requireTime} |`,
)
} else {
if (!isFirst) {
isFirst = true
console.log('name\t\t\tinstall size\t\treuqire time')
}
console.log(`${result.pkg}\t\t\t${result.size}\t\t${result.requireTime}`)
}
})
program.runAndEmit().then(() => {
log.info('results', results)
let content = ''
if (opts.record) {
if (pkgs.length === 0) {
const packageJson = requirePkg(opts.cwd)
content += `## ${packageJson.version}\n`
}
if (opts.monorepo) {
const { loadMonorepoConfig } = require('./load-monorepo-packages')
const config = loadMonorepoConfig(opts.cwd)
content += `## ${config.version}\n`
}
content += `
| name | install size | reuqire time |
| --- | --- | --- |
${results.map(result => `| ${result.pkg} | ${result.size} | ${result.requireTime} |`).join('\n')}
`
const RECORD_FILE = 'DEPCOST.md'
const recordFile = path.join(opts.cwd, RECORD_FILE)
if (fs.existsSync(recordFile)) {
const existedContent = fs.readFileSync(recordFile, 'utf-8')
content = `${content.trim()}\n\n\n${existedContent}`
}
fs.writeFileSync(recordFile, content)
return content
}
if (opts.visualization) {
const VisualizationServer = require('./visualization/server')
const server = new VisualizationServer({
masterPkgName,
pkgs,
content,
dependencies,
devDependencies,
results,
})
server.bootstrap()
server.listen(null, null, async url => {
const open = require('open')
await open(url)
})
}
if (opts.html) {
const generateReportHTML = require('./visualization/html')
generateReportHTML(results, {
cwd: opts.cwd,
writeFile: true,
})
}
return {
content,
results,
dependencies,
devDependencies,
}
}).catch(error => {
process.exitCode = 1
console.log(require('chalk').red(error.stack))
})
}