Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We鈥檒l occasionally send you account related emails.

Already on GitHub? Sign in to your account

Auto import fbt in babel plugin #194

Open
alexandernanberg opened this issue Feb 11, 2021 · 5 comments
Open

Auto import fbt in babel plugin #194

alexandernanberg opened this issue Feb 11, 2021 · 5 comments
Labels
enhancement New feature or request

Comments

@alexandernanberg
Copy link
Contributor

馃殌 Feature Proposal

Add support to auto import fbt in the babel plugin. Similar to how the new react automatic runtime feature in @babel/plugin-transform-react-jsx

Motivation

Personally I often forget to import fbt until the compilation fails, making this automatic would improve the DX for at least me.

This would also fix use with "organize imports" in VS Code, where it removed the fbt import since it can't see it's being used.

Example

// input

function App() {
  return (
    <fbt desc="lorem text">Lorem ipsum dolor</fbt>
  )
}

// output

import fbt from 'fbt'

function App() {
  return (
    <fbt desc="lorem text">Lorem ipsum dolor</fbt>
  )
}

Pitch

It makes sense for this feature to be in the core babel plugin, I guess it's possible to create a custom plugin but then you need to be careful about ordering etc

@kayhadrin kayhadrin added the enhancement New feature or request label Feb 11, 2021
@kayhadrin
Copy link
Collaborator

Since we've got code to detect the lack of fbt import, it makes sense that we could try to add it automatically in the transformed JS output.

We might have to give new configuration options in babel-plugin-fbt to let people customize how to actually do that import if their setup is not standard though.

@alexandernanberg
Copy link
Contributor Author

Created a stand-alone plugin for now, if it works out well I might create a PR sometime in the future

module.exports = function fbtImportPlugin({ types: t }) {
  let root;

  return {
    visitor: {
      Program(path) {
        root = path;
      },
      JSXElement(path) {
        const hasFbtImport = !path.context.scope.getBinding('fbt');

        if (path.node.openingElement.name.name === 'fbt' && hasFbtImport) {
          const importDeclaration = t.importDeclaration(
            [t.importDefaultSpecifier(t.identifier('fbt'))],
            t.stringLiteral('fbt')
          );
          const [importPath] = root.unshiftContainer('body', importDeclaration);
          // Babel doesn't automatically update the bindings when we insert the
          // import statement, so manually update the binding here.
          root.scope.registerBinding('module', importPath);
        }
      },
    },
  };
};
// .babelrc
{
  "plugins": [
    "./babel-plugin-fbt-import", // need to be before the other fbt plugins
    "babel-plugin-fbt-runtime",
    [
      "babel-plugin-fbt",
      {
        "extraOptions": { "__self": true, "__source": true }
      }
    ]
  ]
}

@kayhadrin
Copy link
Collaborator

Nice!
This makes me think we should probably make an eslint rule for this.
In general, I find that it's easier to make people import fbt explicitly in their code so that the Flow type checks work properly.

@alexandernanberg
Copy link
Contributor Author

So a rule to disallow having an <fbt /> without explicitly importing it? Don't know much about Flow, but for TS the auto import would be quite nice. It would solve the issue described here under "The nasty bit" (not needing to add eslint-disable-next-line @typescript-eslint/no-unused-expressions fbt) to every file.

@alexandernanberg
Copy link
Contributor Author

I've published the code as babel-plugin-fbt-import on npm now, and code can be found here https://github.com/alexandernanberg/babel-plugin-fbt-import

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request
Projects
None yet
Development

No branches or pull requests

2 participants