Skip to content

Instantly share code, notes, and snippets.

@lelandrichardson
Last active May 12, 2017 15:58
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save lelandrichardson/c7a68950ec10576e174543413bb6e711 to your computer and use it in GitHub Desktop.
Save lelandrichardson/c7a68950ec10576e174543413bb6e711 to your computer and use it in GitHub Desktop.
Find RN Imports
const walk = require('babylon-walk');
const babylon = require('babylon');
const glob = require('glob');
const fs = require('fs');
const path = require('path');
const zip = (a, b, fn) => a.forEach((el, i) => fn(el, b[i], i));
const promisify = fn => new Promise((res, rej) => {
const done = (err, val) => (err ? rej(err) : res(val));
fn(done);
});
const getFile = fpath => promisify(cb => fs.readFile(fpath, 'utf8', cb));
const getFiles = fpath => promisify(cb => fs.readdir(fpath, cb));
const getGlobbedFiles = (g, opts) => promisify(cb => glob(g, opts, cb));
function getAST(data, file) {
let tree;
try {
tree = babylon.parse(data, {
sourceType: 'module',
plugins: [
'jsx',
'flow',
'objectRestSpread',
'exportExtensions',
'classProperties',
],
});
return tree;
} catch (e) {
console.error(file, e);
return null;
}
}
function getReactNativeImports(tree, collector) {
walk.simple(tree, {
ImportDeclaration: (node) => {
if (node.source.value === 'react-native') {
const names = node.specifiers
.filter(spec => spec.type === 'ImportSpecifier')
.map(spec => spec.imported.name);
collector.push(...names);
}
},
});
return collector;
}
function getReactNativeImportsFromPath(file, collector) {
return getFile(file)
.then(str => getAST(str, file))
.then(tree => getReactNativeImports(tree, collector));
}
const results = [];
getGlobbedFiles(process.argv[2], { dot: false, absolute: true })
.then(files => Promise.all(files.map(f => getReactNativeImportsFromPath(f, results))))
.then(() => {
const amounts = {};
results.forEach(name => {
if (!amounts[name]) {
amounts[name] = 0;
}
amounts[name] += 1;
});
process.stdout.write(`name\tcount\n`);
Object.keys(amounts).forEach(key => {
process.stdout.write(`${key}\t${amounts[key]}\n`);
});
});

To run this, you will first need to install the following npm packages:

npm i babylon babylon-walk glob

Then, with the script in the current directory in find-rn-imports.js, you would want to run it, passing in a glob pattern to hit all of the source code files in your repo. For instance I ran something like:

node ./find-rn-imports.js '!(node_modules|test)/**/*.js'

The output of that script will indicate which react native APIs you are importing and how many times in your code base (though this assumes you are using import and not require).

@sahrens
Copy link

sahrens commented May 8, 2017

I also had to change the matcher to handle our requires since we still haven't switched, so I used a whitelist on the module names, so might have missed some.

@sahrens
Copy link

sahrens commented May 12, 2017

Also note with our numbers up there we have some different internal implementations, e.g. for Image.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment