pwd > ninjaPixel/v2/man-drawer/lodash-codemod

lodash codemod

Published

Bummed that you can’t treeshake lodash away? Well you can use jscodeshift to run a codemod which will explicitly import all of the lodash functions that you're using.

I've taken the codemod from blog.laurenashpole.com:

export default (fileInfo, api) => {
  const j = api.jscodeshift;
  const root = j(fileInfo.source);
  let specifiers = [];

  root
    .find(j.ImportDeclaration, isLodashImport)
    .forEach((path) => specifiers.push(...path.node.specifiers.map((specifier) => specifier.local.name)))
    .remove();

  root
    .find(j.CallExpression, isLodashExpression)
    .forEach((path) => specifiers.push(path.node.callee.property.name))
    .replaceWith((path) => replaceExpression(path, j));

  if (specifiers.length) {
    cleanSpecifiers(specifiers).forEach((specifier) => {
      root.find(j.Declaration).at(0).get()
        .insertBefore(createImport(j, specifier));
    });
  }

  return root.toSource();
};

function isLodashImport (node) {
  return node.source.value.startsWith('lodash');
}

function isLodashExpression (node) {
  return node.callee.type === 'MemberExpression' && node.callee.object && node.callee.object.name === '_';
}

function replaceExpression (path, j) {
  return j.callExpression(j.identifier(path.node.callee.property.name), path.node.arguments);
}

function cleanSpecifiers (specifiers) {
  return specifiers.filter((specifier, i) => {
    return specifier !== '_' && specifiers.indexOf(specifier) === i;
  });
}

function createImport (j, specifier) {
  return j.importDeclaration(
    [j.importDefaultSpecifier(j.identifier(specifier))],
    j.stringLiteral(`lodash/${specifier}`)
  );
}

Name this file lodash-import-codemod.js and put it in the root of your project (no need to commit it to git, as you're just using this as a tool to refactor some code). Then run the following to do the code mod on all your .tsx files:

npx jscodeshift -t ./lodash-import-codemod.js --extensions=tsx --parser=tsx  .

and then run this to do it on all your TypeScript files:

npx jscodeshift -t ./lodash-import-codemod.js --extensions=ts --parser=ts  .

Just be aware that this could result in some name collisions. For example, if you have a variable in your code named groupBy and the file also uses the _.groupBy method, after running the codemod, you will also import the groupBy function from lodash, so you’ll either need to change the name that you use to import it, or just rename your constant to something else.