UNPKG

tachometer

Version:
161 lines (137 loc) 4.62 kB
/** * @license * Copyright (c) 2019 The Polymer Project Authors. All rights reserved. * This code may only be used under the BSD style license found at * http://polymer.github.io/LICENSE.txt The complete set of authors may be found * at http://polymer.github.io/AUTHORS.txt The complete set of contributors may * be found at http://polymer.github.io/CONTRIBUTORS.txt Code distributed by * Google as part of the polymer project is also subject to an additional IP * rights grant found at http://polymer.github.io/PATENTS.txt */ require('source-map-support').install(); import * as path from 'path'; import ansi = require('ansi-escape-sequences'); import * as semver from 'semver'; import commandLineUsage = require('command-line-usage'); import {optDefs, parseFlags} from './flags'; import {BenchmarkSpec} from './types'; import {makeConfig} from './config'; import {Server} from './server'; import {ResultStatsWithDifferences} from './stats'; import {prepareVersionDirectory, makeServerPlans} from './versions'; import {manualMode} from './manual'; import {automaticMode} from './automatic'; import {runNpm} from './util'; const installedVersion = (): string => require(path.join('..', 'package.json')).version; export async function main(argv: string[]): Promise<Array<ResultStatsWithDifferences>|undefined> { // Don't block anything on a network query to NPM. const latestVersionPromise = latestVersionFromNpm(); let results; try { results = await realMain(argv); } catch (e) { console.error(e); process.exitCode = 1; } try { notifyIfOutdated(await latestVersionPromise); } catch (e) { // Don't set a non-zero exit code just because the NPM query failed. Maybe // we're behind a firewall and can't contact NPM. console.error(`\nFailed to check NPM for latest version:\n${e}`); } return results; } async function latestVersionFromNpm(): Promise<string> { const stdout = await runNpm(['info', 'tachometer@latest', 'version']); return stdout.toString('utf8').trim(); } function notifyIfOutdated(latestVersion: string) { const iv = installedVersion(); if (semver.lt(iv, latestVersion)) { console.log(ansi.format(` [bold magenta]{Update available!} The latest version of tachometer is [green]{${latestVersion}} You are running version [yellow]{${iv}} See what's new at [cyan]{https://github.com/Polymer/tachometer/blob/master/CHANGELOG.md}`)); } } async function realMain(argv: string[]): Promise<Array<ResultStatsWithDifferences>|undefined> { const opts = parseFlags(argv); if (opts.help) { console.log(commandLineUsage([ { header: 'tach', content: `v${installedVersion()}\nhttps://github.com/PolymerLabs/tachometer`, }, { header: 'Usage', content: ` Run a benchmark from a local file: $ tach foo.html Compare a benchmark with different URL parameters: $ tach foo.html?i=1 foo.html?i=2 Benchmark index.html in a directory: $ tach foo/bar Benchmark a remote URL's First Contentful Paint time: $ tach http://example.com `, }, { header: 'Options', optionList: optDefs, }, ])); return; } if (opts.version) { console.log(installedVersion()); return; } const config = await makeConfig(opts); if (config.legacyJsonFile) { console.log( `Please use --json-file instead of --save. ` + `--save will be removed in the next major version.`); } const plans = await makeServerPlans( config.root, opts['npm-install-dir'], config.benchmarks); const servers = new Map<BenchmarkSpec, Server>(); const promises = []; for (const {npmInstalls, mountPoints, specs} of plans) { promises.push(...npmInstalls.map( (install) => prepareVersionDirectory( install, config.forceCleanNpmInstall, ))); promises.push((async () => { const server = await Server.start({ host: opts.host, ports: opts.port, root: config.root, npmInstalls, mountPoints, resolveBareModules: config.resolveBareModules, cache: config.mode !== 'manual', }); for (const spec of specs) { servers.set(spec, server); } })()); } await Promise.all(promises); if (config.mode === 'manual') { await manualMode(config, servers); } else { try { return await automaticMode(config, servers); } finally { const allServers = new Set<Server>([...servers.values()]); await Promise.all([...allServers].map((server) => server.close())); } } }