babel-timing
Advanced tools
Comparing version 0.1.0 to 0.2.0
# Change log | ||
## 0.2.0 | ||
### Breaking Changes | ||
- Make `babelTiming` async | ||
- Replace `importPatterns` with `include` and `exclude` options | ||
- Change result API's: rename data as plugins | ||
- Make all file paths absolute | ||
## Minor changes | ||
- Follow imports with Rollup.js | ||
- Add `resolveMainFields` option | ||
- Add `verbose` option | ||
- Add `expandPackages` option | ||
- Improve CLI output UX | ||
- Transpile files during imports discovery phase | ||
## 0.1.0 | ||
Initial release |
51
cli.js
@@ -7,2 +7,6 @@ #!/usr/bin/env node | ||
function list(val) { | ||
return val.split(','); | ||
} | ||
program | ||
@@ -13,18 +17,39 @@ .version(pkg.version) | ||
.option('--follow-imports', 'follow and compile imported files') | ||
// .option('--follow-absolute-imports', 'follow and compile absolute imports') | ||
.option( | ||
'--import-patterns <comma-separated-list-of-glob-patterns>', | ||
'configure which imports to follow' | ||
'--include <comma-separated-list-of-glob-patterns>', | ||
'include provided import paths', | ||
list | ||
) | ||
.option('--output <return|console|json>', 'make results available as') | ||
.option( | ||
'--exclude <comma-separated-list-of-glob-patterns>', | ||
'exclude provided import paths', | ||
list | ||
) | ||
.option( | ||
'--resolve-main-fields <comma-separated-list-of-fields>', | ||
'determine which fields in imported package.json are checked', | ||
list | ||
) | ||
.option('--expand-packages', 'expand node_modules packages results') | ||
.option( | ||
'--output <return|console|json>', | ||
'make results available as', | ||
'console' | ||
) | ||
.option('--verbose', 'log warnings') | ||
.parse(process.argv); | ||
babelTiming(program.args, { | ||
babelConfig: program.babelConfig, | ||
followImports: program.followImports, | ||
// followAbsoluteImports: program.followAbsoluteImports, | ||
importPatterns: program.importPatterns | ||
? program.importPatterns.split(',') | ||
: undefined, | ||
output: program.output || 'console', | ||
}); | ||
babelTiming( | ||
program.args, | ||
({ | ||
babelConfig, | ||
followImports, | ||
importPatterns, | ||
include, | ||
exclude, | ||
resolveMainFields, | ||
expandPackages, | ||
output, | ||
verbose, | ||
} = program) | ||
); |
{ | ||
"name": "babel-timing", | ||
"version": "0.1.0", | ||
"version": "0.2.0", | ||
"description": "Measure Babel compilation time", | ||
@@ -9,3 +9,4 @@ "main": "src/index.js", | ||
"cli.js", | ||
"!__tests__" | ||
"!__tests__", | ||
"!__mocks__" | ||
], | ||
@@ -37,12 +38,21 @@ "cli": "./cli.js", | ||
"@babel/core": "^7.4.3", | ||
"babel-collect-imports": "git+https://github.com/szymonlesisz/babel-collect-imports.git", | ||
"cli-table": "^0.3.1", | ||
"ansi-diff-stream": "^1.2.1", | ||
"cli-table3": "^0.5.1", | ||
"colors": "^1.3.3", | ||
"commander": "^2.20.0", | ||
"find-babel-config": "^1.2.0", | ||
"glob": "^7.1.3", | ||
"keypress": "^0.2.1", | ||
"lodash.chunk": "^4.2.0", | ||
"lodash.mergewith": "^4.6.1", | ||
"multimatch": "^4.0.0", | ||
"reduce-flatten": "^2.0.0" | ||
"reduce-flatten": "^2.0.0", | ||
"rollup": "^1.10.1", | ||
"rollup-plugin-babel": "^4.3.2", | ||
"rollup-plugin-commonjs": "^9.3.4", | ||
"rollup-plugin-node-resolve": "^4.2.3" | ||
}, | ||
"devDependencies": { | ||
"@babel/preset-env": "^7.4.3", | ||
"@babel/preset-react": "^7.0.0", | ||
"husky": "^1.0.0", | ||
@@ -53,2 +63,5 @@ "jest": "^24.7.1", | ||
}, | ||
"jest": { | ||
"testEnvironment": "node" | ||
}, | ||
"husky": { | ||
@@ -69,3 +82,6 @@ "hooks": { | ||
] | ||
}, | ||
"engines": { | ||
"node": ">=7.6" | ||
} | ||
} |
# Babel timing | ||
Measure Babel compilation time file by file, plugin by plugin. [See screenshot](https://raw.githubusercontent.com/toomuchdesign/babel-timing/master/screenshot.png). | ||
[![Build status][ci-badge]][ci] | ||
Measure **Babel compilation time** file by file, plugin by plugin. [See screenshot](https://raw.githubusercontent.com/toomuchdesign/babel-timing/master/screenshot.png). | ||
Get some insights about Babel transpilation when your application or your tests take ages to build. | ||
**Note:** this tool is in **version 0**, any minor release might introduce breaking changes. | ||
@@ -30,3 +34,3 @@ | ||
const babelTiming = require('babel-timing').babelTiming; | ||
babelTiming(['path/to/file.js'], options); | ||
const results = await babelTiming(['path/to/file.js'], options); | ||
``` | ||
@@ -36,10 +40,10 @@ | ||
### `babelConfig` / `--babel-config` | ||
#### `babelConfig` / `--babel-config` | ||
Type: `string | false`<br /> | ||
Default: `false` | ||
Default: `undefined` | ||
Path to a custom [babel configuration file](https://babeljs.io/docs/en/options#configfile). By default Babel will try to load any existing valid configuration file. | ||
### `followImports` / `--follow-imports` | ||
#### `followImports` / `--follow-imports` | ||
@@ -49,15 +53,31 @@ Type: `bool`<br /> | ||
Follow imported files/modules (using [babel-collect-imports](https://github.com/babel-utils/babel-collect-imports)) and run `babel-timing` against them. | ||
Follow imported files/modules and run `babel-timing` against them. | ||
Currently only relative paths are considered. | ||
#### `include` / `--include` | ||
Type: `string[]` *(cli accepts a string containing a comma-separated list)*<br /> | ||
Default: `['**']` | ||
### `importPatterns` / `--import-patterns` | ||
Include paths (imported ones also) according to the [provided glob patterns](https://www.npmjs.com/package/glob#glob-primer). | ||
#### `exclude` / `--exclude` | ||
Type: `string[]` *(cli accepts a string containing a comma-separated list)*<br /> | ||
Default: `undefined` | ||
Default: `['**/modules/**']` | ||
Include/exclude import paths according to the [provided patterns](https://github.com/sindresorhus/multimatch#readme). | ||
Exclude paths (imported ones also) according to the [provided glob patterns](https://www.npmjs.com/package/glob#glob-primer). | ||
### `output` / `--output` | ||
#### `resolveMainFields` / `--resolve-main-fields` | ||
Type: `string[]` *(cli accepts a string containing a comma-separated list)*<br /> | ||
Default: `['browser', 'module', 'main']` | ||
Determine which fields in imported modules's `package.json` are checked. | ||
#### `expandPackages` / `--expand-packages` | ||
Type: `bool`<br /> | ||
Default: `false` | ||
Expand results relative to `node_modules` packages file by file. | ||
#### `output` / `--output` | ||
Type: `string`<br /> | ||
@@ -73,2 +93,8 @@ Default: `"return"` (`"console"` when called via CLI)<br /> | ||
#### `verbose` / `--verbose` | ||
Type: `bool`<br /> | ||
Default: `false` | ||
Log warnings. | ||
## How it works | ||
@@ -78,4 +104,2 @@ | ||
Optionally follow imports using [babel-collect-imports][babel-collect-imports]. | ||
### Results | ||
@@ -89,3 +113,3 @@ | ||
totalTime: number, | ||
data: { | ||
plugins: { | ||
plugin: string, | ||
@@ -128,7 +152,4 @@ timePerVisit: number, | ||
- Provide a way to consume `babel-timing` from other tools like `webpack`, `jest`, `rollup`, etc.. | ||
- Unwrap and compile `node_modules` packages (absolute paths) | ||
- Prevent nested import discovery | ||
- Find a more stable solution for making available pending [`babel-collect-imports` Babel v7 update](https://github.com/babel-utils/babel-collect-imports/pull/2) | ||
- Consider using a bundler instead of `babel-collect-import` | ||
[babel-collect-imports]: https://github.com/babel-utils/babel-collect-imports | ||
[ci-badge]: https://travis-ci.org/toomuchdesign/babel-timing.svg?branch=master | ||
[ci]: https://travis-ci.org/toomuchdesign/babel-timing |
@@ -6,14 +6,19 @@ const fs = require('fs'); | ||
const flatten = require('reduce-flatten'); | ||
const {collectImportsSync} = require('babel-collect-imports'); | ||
const {globPatternsToPaths, onlyUnique} = require('./utils'); | ||
const {globPatternsToPaths, onlyUnique, sortByProperty} = require('./utils'); | ||
const PluginsTimer = require('./PluginsTimer'); | ||
const renderer = require('./renderer'); | ||
const cliRenderer = require('./cliRenderer'); | ||
const getImports = require('./getImports'); | ||
const joinSamePackageResults = require('./joinSamePackageResults'); | ||
function babelTiming( | ||
async function babelTiming( | ||
filePatterns = [], | ||
{ | ||
babelConfig = false, | ||
babelConfig, | ||
followImports = false, | ||
importPatterns, | ||
include = ['**'], | ||
exclude = ['**/node_modules/**'], | ||
resolveMainFields = ['browser', 'module', 'main'], | ||
expandPackages = false, | ||
output = 'return', | ||
verbose = false, | ||
} = {} | ||
@@ -25,47 +30,63 @@ ) { | ||
if (followImports) { | ||
let importedFiles = files | ||
.map(file => { | ||
const {internal, external} = collectImportsSync(file); | ||
return internal; | ||
}) | ||
.reduce(flatten, []) | ||
.filter(onlyUnique); | ||
let importedFiles = await Promise.all( | ||
files.map(file => | ||
getImports(file, { | ||
babelConfig, | ||
resolveMainFields, | ||
include, | ||
exclude, | ||
verbose, | ||
}) | ||
) | ||
); | ||
if (importPatterns) { | ||
importedFiles = multimatch(importedFiles, importPatterns); | ||
} | ||
importedFiles = importedFiles.reduce(flatten, []).filter(onlyUnique); | ||
files = importedFiles; | ||
} | ||
const results = files | ||
.map(file => { | ||
const timer = new PluginsTimer(); | ||
// All file paths absolute | ||
files = files.map(file => path.resolve(file)); | ||
/* | ||
* Transform all gathered files one by one and collect | ||
* transform meta data using `wrapPluginVisitorMethod` | ||
* https://babeljs.io/docs/en/options#configfile | ||
*/ | ||
babel.transformSync(fs.readFileSync(file).toString(), { | ||
filename: file, | ||
configFile: babelConfig ? path.join(process.cwd(), babelConfig) : false, | ||
minified: true, | ||
compact: true, | ||
wrapPluginVisitorMethod: timer.wrapPluginVisitorMethod, | ||
}); | ||
if (Array.isArray(include)) { | ||
files = multimatch(files, include); | ||
} | ||
const data = timer.getResults(); | ||
if (Array.isArray(exclude)) { | ||
const negatedExclude = exclude.map(pattern => `!${pattern}`); | ||
files = multimatch(files, ['**', ...negatedExclude]); | ||
} | ||
return { | ||
name: file, | ||
totalTime: PluginsTimer.getTotalTime(data), | ||
data, | ||
}; | ||
}) | ||
.sort((a, b) => { | ||
if (a.totalTime < b.totalTime) return 1; | ||
if (a.totalTime > b.totalTime) return -1; | ||
return 0; | ||
let results = files.map(file => { | ||
const timer = new PluginsTimer(); | ||
/* | ||
* Transform all gathered files one by one and collect | ||
* transform meta data using `wrapPluginVisitorMethod` | ||
* https://babeljs.io/docs/en/options#configfile | ||
*/ | ||
babel.transformSync(fs.readFileSync(file).toString(), { | ||
filename: file, | ||
configFile: babelConfig ? path.join(process.cwd(), babelConfig) : false, | ||
minified: true, | ||
compact: true, | ||
wrapPluginVisitorMethod: timer.wrapPluginVisitorMethod, | ||
}); | ||
return { | ||
name: file, | ||
plugins: timer.getResults(), | ||
}; | ||
}); | ||
if (!expandPackages) { | ||
results = joinSamePackageResults(results); | ||
} | ||
results = results | ||
.map(entry => ({ | ||
...entry, | ||
totalTime: PluginsTimer.getTotalTime(entry.plugins), | ||
})) | ||
.sort(sortByProperty('totalTime')); | ||
switch (output) { | ||
@@ -76,3 +97,3 @@ case 'return': { | ||
case 'console': { | ||
renderer(results); | ||
cliRenderer(results); | ||
return; | ||
@@ -79,0 +100,0 @@ } |
@@ -0,1 +1,5 @@ | ||
const mergeWith = require('lodash.mergewith'); | ||
const flatten = require('reduce-flatten'); | ||
const {onlyUnique, sortByProperty} = require('./utils'); | ||
// interface results { | ||
@@ -51,11 +55,7 @@ // plugin: string | ||
plugin: pluginAlias, | ||
timePerVisit: entry.time / entry.visits, | ||
...entry, | ||
}; | ||
}) | ||
.sort((a, b) => { | ||
if (a.time < b.time) return 1; | ||
if (a.time > b.time) return -1; | ||
return 0; | ||
}); | ||
.map(PluginsTimer.addTimePerVisitProperty) | ||
.sort(sortByProperty('time')); | ||
} | ||
@@ -71,4 +71,38 @@ | ||
} | ||
// To be used in .map | ||
static addTimePerVisitProperty(entry) { | ||
return { | ||
...entry, | ||
timePerVisit: entry.time / entry.visits, | ||
}; | ||
} | ||
static mergeResults(...resultArrays) { | ||
function mergeStrategy(objValue, srcValue) { | ||
if (typeof objValue === 'string') { | ||
return objValue; | ||
} | ||
if (typeof objValue === 'number') { | ||
return objValue + srcValue; | ||
} | ||
} | ||
const results = resultArrays.reduce(flatten, []); | ||
return ( | ||
results | ||
// Get list of plugin names | ||
.map(entry => entry.plugin) | ||
.filter(onlyUnique) | ||
// Merge data entries with same plugin name | ||
.map(pluginName => { | ||
const samePlugin = results.filter(data => data.plugin === pluginName); | ||
return mergeWith(...samePlugin, mergeStrategy); | ||
}) | ||
.map(PluginsTimer.addTimePerVisitProperty) | ||
.sort(sortByProperty('time')) | ||
); | ||
} | ||
} | ||
module.exports = PluginsTimer; |
const glob = require('glob'); | ||
const fs = require('fs'); | ||
@@ -8,3 +9,3 @@ function globPatternsToPaths(patterns) { | ||
paths.push(...glob.sync(pattern)); | ||
} else { | ||
} else if (fs.existsSync(pattern)) { | ||
paths.push(pattern); | ||
@@ -20,3 +21,30 @@ } | ||
function sortByProperty(prop) { | ||
return (a, b) => { | ||
if (a[prop] < b[prop]) return 1; | ||
if (a[prop] > b[prop]) return -1; | ||
return 0; | ||
}; | ||
} | ||
function hasEntryWithProperty(propName, value, arr) { | ||
let i; | ||
for (i = 0; i < arr.length; i++) { | ||
if (arr[i][propName] === value) { | ||
return true; | ||
} | ||
} | ||
return false; | ||
} | ||
function valueInRange(value, {min = -Infinity, max = Infinity} = {}) { | ||
if (value > max) return max; | ||
if (value < min) return min; | ||
return value; | ||
} | ||
exports.hasEntryWithProperty = hasEntryWithProperty; | ||
exports.globPatternsToPaths = globPatternsToPaths; | ||
exports.onlyUnique = onlyUnique; | ||
exports.sortByProperty = sortByProperty; | ||
exports.valueInRange = valueInRange; |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Git dependency
Supply chain riskContains a dependency which resolves to a remote git URL. Dependencies fetched from git URLs are not immutable and can be used to inject untrusted code or reduce the likelihood of a reproducible install.
Found 1 instance in 1 package
24449
15
594
149
0
16
6
2
1
+ Addedansi-diff-stream@^1.2.1
+ Addedcli-table3@^0.5.1
+ Addedfind-babel-config@^1.2.0
+ Addedkeypress@^0.2.1
+ Addedlodash.chunk@^4.2.0
+ Addedlodash.mergewith@^4.6.1
+ Addedrollup@^1.10.1
+ Addedrollup-plugin-babel@^4.3.2
+ Added@types/estree@1.0.6(transitive)
+ Added@types/node@22.13.4(transitive)
+ Added@types/resolve@0.0.8(transitive)
+ Addedacorn@7.4.1(transitive)
+ Addedansi-diff-stream@1.2.1(transitive)
+ Addedansi-regex@2.1.13.0.1(transitive)
+ Addedbuffer-from@1.1.2(transitive)
+ Addedbuiltin-modules@3.3.0(transitive)
+ Addedcli-table3@0.5.1(transitive)
+ Addedcore-util-is@1.0.3(transitive)
+ Addedestree-walker@0.6.1(transitive)
+ Addedfind-babel-config@1.2.2(transitive)
+ Addedfunction-bind@1.1.2(transitive)
+ Addedhasown@2.0.2(transitive)
+ Addedis-core-module@2.16.1(transitive)
+ Addedis-fullwidth-code-point@2.0.0(transitive)
+ Addedis-module@1.0.0(transitive)
+ Addedisarray@1.0.0(transitive)
+ Addedjson5@1.0.2(transitive)
+ Addedkeypress@0.2.1(transitive)
+ Addedlodash.chunk@4.2.0(transitive)
+ Addedlodash.mergewith@4.6.2(transitive)
+ Addedmagic-string@0.25.9(transitive)
+ Addedminimist@1.2.8(transitive)
+ Addedobject-assign@4.1.1(transitive)
+ Addedpath-exists@3.0.0(transitive)
+ Addedpath-parse@1.0.7(transitive)
+ Addedprocess-nextick-args@2.0.1(transitive)
+ Addedreadable-stream@2.3.8(transitive)
+ Addedresolve@1.22.10(transitive)
+ Addedrollup@1.32.1(transitive)
+ Addedrollup-plugin-babel@4.4.0(transitive)
+ Addedrollup-plugin-commonjs@9.3.4(transitive)
+ Addedrollup-plugin-node-resolve@4.2.4(transitive)
+ Addedrollup-pluginutils@2.8.2(transitive)
+ Addedsafe-buffer@5.1.2(transitive)
+ Addedsourcemap-codec@1.4.8(transitive)
+ Addedstring-width@2.1.1(transitive)
+ Addedstring_decoder@1.1.1(transitive)
+ Addedstrip-ansi@4.0.0(transitive)
+ Addedsupports-preserve-symlinks-flag@1.0.0(transitive)
+ Addedthrough2@2.0.5(transitive)
+ Addedundici-types@6.20.0(transitive)
+ Addedutil-deprecate@1.0.2(transitive)
+ Addedxtend@4.0.2(transitive)
- Removedbabel-collect-imports@git+https://github.com/szymonlesisz/babel-collect-imports.git
- Removedcli-table@^0.3.1
- Removedcli-table@0.3.11(transitive)
- Removedcolors@1.0.3(transitive)