5

I am currently trying to use React Native SVG to render SVG components in my RN app. However, the metro.config.js configuration causes some errors I cannot seem to resolve.

I have installed react-native-svg and react-native-svg-transformer and combined the metro config file as such:

const { getDefaultConfig } = require("metro-config");

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      getTransformOptions: async () => ({
        transform: {
          experimentalImportSupport: false,
          inlineRequires: false
        }
      }),
      babelTransformerPath: require.resolve("react-native-svg-transformer")
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== "svg"),
      sourceExts: [...sourceExts, "svg"]
    }
  };
})();

However, I always get the following error:

[Sun Feb 13 2022 17:49:52.470]  ERROR    ReferenceError: Can't find variable: config
[Sun Feb 13 2022 17:49:52.472]  ERROR    Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication)
[Sun Feb 13 2022 17:49:52.473]  ERROR    Invariant Violation: Module AppRegistry is not a registered callable module (calling runApplication)

I tried restarting with npm start -- --reset-cache and after playing around with the config file, I noticed that it was the async that was causing the issue. The variable couldn't be found since the parent function isn't awaiting. I can't get around this when using getDefaultConfig(). How can I get around this?

Justin Li
  • 93
  • 1
  • 8

3 Answers3

3

This works on RN 0.72.3

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

/**
 * Metro configuration
 * https://facebook.github.io/metro/docs/configuration
 *
 * @type {import('metro-config').MetroConfig}
 */
const config = async () => {
  const defaultConfig = await getDefaultConfig(__dirname);
  const {
    resolver: {sourceExts, assetExts},
  } = defaultConfig;

  return mergeConfig(defaultConfig, {
    transformer: {
      babelTransformerPath: require.resolve('react-native-svg-transformer'),
      getTransformOptions: async () => ({
        transform: {
          experimentalImportSupport: false,
          inlineRequires: true,
        },
      }),
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== 'svg'),
      sourceExts: [...sourceExts, 'svg'],
    },
  });
};

module.exports = config;
  • Remember that Stack Overflow isn't just intended to solve the immediate problem, but also to help future readers find solutions to similar problems, which requires understanding the underlying code. This is especially important for members of our community who are beginners, and not familiar with the syntax. Given that, **can you [edit] your answer to include an explanation of what you're doing** and why you believe it is the best approach? – Jeremy Caney Jul 24 '23 at 04:24
1

This works for me:

const { assetExts, sourceExts } = require('metro-config/src/defaults/defaults');
const blacklist = require('metro-config/src/defaults/blacklist');
const { getDefaultConfig, mergeConfig } = require("metro-config");

const cfg = async () => await getDefaultConfig();

module.exports = mergeConfig(cfg, {
    transformer: {
        getTransformOptions: async () => ({
            transform: {
                experimentalImportSupport: false,
                inlineRequires: false
            }
        }),
        babelTransformerPath: require.resolve("react-native-svg-transformer")
    },
    resolver: {
        assetExts: assetExts.filter(ext => ext !== "svg"),
        sourceExts: [...sourceExts, "svg"],
        blacklistRE: blacklist([/ios\/build\/.*/])
    }
});
Thijs
  • 587
  • 5
  • 16
0

Just set inlineRequires to true

The full setup should look next:

const { getDefaultConfig } = require("metro-config");

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      getTransformOptions: async () => ({
        transform: {
          experimentalImportSupport: false,
          inlineRequires: true
        }
      }),
      babelTransformerPath: require.resolve("react-native-svg-transformer")
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== "svg"),
      sourceExts: [...sourceExts, "svg"]
    }
  };
})();