Skip to content

feat: add metro transformer#1999

Merged
andrii-bodnar merged 12 commits into
mainfrom
@vonovak/metro-transformer
Oct 11, 2024
Merged

feat: add metro transformer#1999
andrii-bodnar merged 12 commits into
mainfrom
@vonovak/metro-transformer

Conversation

@vonovak
Copy link
Copy Markdown
Collaborator

@vonovak vonovak commented Aug 12, 2024

Description

This adds the equivalent of webpack loader for metro bundler used in react native apps.

I'm targeting the main branch but could easily switch to next if desirable.

Types of changes

  • Bugfix (non-breaking change which fixes an issue)
  • New feature (non-breaking change which adds functionality)
  • Breaking change (fix or feature that would cause existing functionality to not work as expected)
  • Documentation update
  • Examples update

Fixes # (issue)

Checklist

  • I have read the CONTRIBUTING and CODE_OF_CONDUCT docs
  • I have added tests that prove my fix is effective or that my feature works
  • I have added the necessary documentation (if appropriate)

@vercel
Copy link
Copy Markdown

vercel Bot commented Aug 12, 2024

The latest updates on your projects. Learn more about Vercel for Git ↗︎

Name Status Preview Comments Updated (UTC)
js-lingui ✅ Ready (Inspect) Visit Preview 💬 Add feedback Oct 10, 2024 1:58pm

@github-actions
Copy link
Copy Markdown

github-actions Bot commented Aug 12, 2024

size-limit report 📦

Path Size
./packages/core/dist/index.mjs 2.88 KB (0%)
./packages/detect-locale/dist/index.mjs 723 B (0%)
./packages/react/dist/index.mjs 1.68 KB (0%)
./packages/remote-loader/dist/index.mjs 7.26 KB (0%)

@vonovak vonovak changed the base branch from main to next September 10, 2024 20:46
@vonovak vonovak changed the base branch from next to main September 10, 2024 20:46
@vonovak vonovak marked this pull request as ready for review September 10, 2024 20:49
Comment thread packages/metro-transformer/package.json Outdated
@andrii-bodnar
Copy link
Copy Markdown
Contributor

@vonovak thank you!

Looks very nice to me, just left a small comment in the package.json file.

I was thinking about including it in the v5 release but realized that there is no reason to postpone it, and it would probably be better to ship it in v4 so that users can already use it. I hope it will not cause a lot of conflicts when merging main into next.

Comment thread packages/metro-transformer/src/expo/index.ts
@vonovak
Copy link
Copy Markdown
Collaborator Author

vonovak commented Sep 29, 2024

I was thinking about including it in the v5 release but realized that there is no reason to postpone it, and it would probably be better to ship it in v4 so that users can already use it. I hope it will not cause a lot of conflicts when merging main into next.

@andrii-bodnar I don't mind merging into next and shipping with v5, but I think you're right. It can be mentioned in v5 release notes as one of the new features anyway. I don't think it should cause conflicts, maybe just in yarn.lock file.

Comment thread packages/metro-transformer/package.json Outdated
Comment thread packages/metro-transformer/package.json Outdated
Comment thread packages/metro-transformer/src/react-native/index.ts Outdated
Comment thread website/docs/ref/metro-transformer.mdx Outdated
@andrii-bodnar
Copy link
Copy Markdown
Contributor

andrii-bodnar commented Oct 9, 2024

@vonovak I plan to release 4.12.0 soon, it would be great to include this PR in it.

By the way, I was looking for some topics to improve the Lingui blog. This seems to be a great one. Would you like to write a little blog post about the Metro transformer?

P.S. I can share the background that I use for covers if needed.

Comment thread packages/metro-transformer/src/react-native/index.ts Outdated
@andrii-bodnar andrii-bodnar merged commit cc7fe27 into main Oct 11, 2024
@andrii-bodnar andrii-bodnar deleted the @vonovak/metro-transformer branch October 11, 2024 08:33
@efstathiosntonas
Copy link
Copy Markdown

Hey guys, how to configure this in case there's another babelTransformPath like:

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');

const defaultConfig = getDefaultConfig(__dirname);
const { assetExts, sourceExts } = defaultConfig.resolver;

metroConfig = (() => {
  return {
    transformer: {
      babelTransformerPath: require.resolve('react-native-svg-transformer/react-native')
    },
    resolver: {
      assetExts: [...assetExts.filter((ext) => ext !== 'svg'), 'bin', 'lottie'],
      sourceExts: [...sourceExts, 'svg']
    }
  };
})();

module.exports = mergeConfig(defaultConfig, metroConfig);

@efstathiosntonas
Copy link
Copy Markdown

nvm, figured it out:

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');

const defaultConfig = getDefaultConfig(__dirname);
const { assetExts, sourceExts } = defaultConfig.resolver;

metroConfig = (() => {
  return {
    transformer: {
      babelTransformerPath: require.resolve('@lingui/metro-transformer/react-native')
    },
    resolver: {
      assetExts: [...assetExts.filter((ext) => ext !== 'svg'), 'bin', 'lottie'],
      sourceExts: [...sourceExts, 'svg']
    }
  };
})();

linguiConfig = (() => {
  return {
    transformer: {
      babelTransformerPath: require.resolve('@lingui/metro-transformer/react-native')
    },
    resolver: {
      sourceExts: [...sourceExts, 'po', 'pot']
    }
  };
})();

module.exports = mergeConfig(defaultConfig, metroConfig, linguiConfig);

I think this should go into the docs, could save some time for the fellow devs.

@vonovak
Copy link
Copy Markdown
Collaborator Author

vonovak commented Oct 12, 2024

Hello,
@efstathiosntonas thanks for suggestion; I'm afraid that what you provided isn't going to work - it's more likely that one config will overwrite the other.

I'd recommend this: https://stackoverflow.com/a/57660231/2070942

edit: also see the comment "I tried to use mergeConfig from the metro docs, but since it doesn't deeply merge the objects, the transformers always get overwritten by whichever config you merge in last."

@efstathiosntonas
Copy link
Copy Markdown

efstathiosntonas commented Oct 12, 2024

@vonovak thanks for the heads up, I’ve already tried the split version based on file extensions but a few errors showed up.

Let me try again and try to fix it since it seems to be the only solution. Will leave a comment with my findings.

@efstathiosntonas
Copy link
Copy Markdown

efstathiosntonas commented Oct 13, 2024

@vonovak I ended up with this and works as a charm for both svg imports and lingui po(t).

customTransformer.js:

const upstreamTransformer = require('metro-babel-transformer'); // no need to npm install this pkg, it's already included in metro
const linguiTransformer = require('@lingui/metro-transformer/react-native');
const svgTransformer = require('react-native-svg-transformer');

module.exports.transform = function ({ src, filename, options }) {
  if (filename.endsWith('.po' || filename.endsWith('.pot'))) {
    return linguiTransformer.transform({ src, filename, options });
  } else if (filename.endsWith('.svg')) {
    return svgTransformer.transform({ src, filename, options });
  } else {
    return upstreamTransformer.transform({ src, filename, options });
  }
};

metro.config.js:

const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');

const defaultConfig = getDefaultConfig(__dirname);
const { assetExts, sourceExts } = defaultConfig.resolver;

metroConfig = (() => {
  return {
    transformer: {
      babelTransformerPath: require.resolve('./customTransformer.js')
    },
    resolver: {
      assetExts: [...assetExts.filter((ext) => ext !== 'svg')],
      sourceExts: [...sourceExts, 'svg', 'po', 'pot']
    }
  };
})();

module.exports = mergeConfig(defaultConfig, metroConfig);

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants