admin管理员组

文章数量:1186135

I'm trying to add multiple resolvers and transformers using metro for my react native project, how do I combine them in my metro.config.js file?

Background: I want to get both a sass transformer to work as well as a svg transformer.

I've tried the configurations separately and that seems to work, but I'm confused to how I combine them so they both work at the same time. I'm assuming they need to be in the same module.exports, because when they both are in the same file I get errors for my svg's

These are the configs I'm trying to combine:

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

module.exports = (async () => {
  const {
    resolver: { sourceExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-sass-transformer")
    },
    resolver: {
      sourceExts: [...sourceExts, "scss", "sass"]
    }
  };
})();

When I try to run it with the code as above, that is two module exports in the metro.config.js, it seems that only the sass transformer works, when I try to draw an svg I get the following error:

Invariant violation: Element type is invalid: Expected a string (for built-in components) or a class/function (for composite components) but got number.

I'm trying to add multiple resolvers and transformers using metro for my react native project, how do I combine them in my metro.config.js file?

Background: I want to get both a sass transformer to work as well as a svg transformer.

I've tried the configurations separately and that seems to work, but I'm confused to how I combine them so they both work at the same time. I'm assuming they need to be in the same module.exports, because when they both are in the same file I get errors for my svg's

These are the configs I'm trying to combine:

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

module.exports = (async () => {
  const {
    resolver: { sourceExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      babelTransformerPath: require.resolve("react-native-sass-transformer")
    },
    resolver: {
      sourceExts: [...sourceExts, "scss", "sass"]
    }
  };
})();

When I try to run it with the code as above, that is two module exports in the metro.config.js, it seems that only the sass transformer works, when I try to draw an svg I get the following error:

Invariant violation: Element type is invalid: Expected a string (for built-in components) or a class/function (for composite components) but got number.
Share Improve this question edited Sep 15, 2021 at 18:25 Emile Bergeron 17.4k5 gold badges84 silver badges131 bronze badges asked Aug 26, 2019 at 11:15 DanielDaniel 4816 silver badges16 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 22

I solved it by creating a custom transformer as follows:

customTransformer.js :

// default transformer: https://metrobundler.dev/docs/configuration/#babeltransformerpath
var upstreamTransformer = require("metro-babel-transformer");
var sassTransformer = require("react-native-sass-transformer");
var svgTransformer = require("react-native-svg-transformer");

module.exports.transform = function({ src, filename, options }) {
  if (filename.endsWith(".scss") || filename.endsWith(".sass")) {
    return sassTransformer.transform({ src, filename, options });
  } else if (filename.endsWith(".svg")) {
    return svgTransformer.transform({ src, filename, options });
  }  else {
    return upstreamTransformer.transform({ src, filename, options });
  }
};

And in my metro.config.js:

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

module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts }
  } = await getDefaultConfig();
  return {
    transformer: {
      babelTransformerPath: require.resolve("./customTransformer.js")
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== "svg" && ext!=="scss"),
      sourceExts: [...sourceExts, "svg", "scss", "sass"]
    }
  };
})();

No idea if this is the best way, but it seems to work

I solve this problem using mergeConfig from metro-config

const { getDefaultConfig, mergeConfig } = require('metro-config');
/* ... */
module.exports = (async () => {
  const {
    resolver: { sourceExts, assetExts },
  } = await getDefaultConfig();
  const svgTransformer = {
    transformer: {
      babelTransformerPath: require.resolve('react-native-svg-transformer'),
    },
    resolver: {
      assetExts: assetExts.filter(ext => ext !== 'svg'),
      sourceExts: [...sourceExts, 'svg'],
    },
  };

  const obfuscatingTransformer = {
    transformer: {
      getTransformOptions: async () => ({
        transform: {
          experimentalImportSupport: false,
          inlineRequires: false,
        },
      }),
    },
    ...jsoMetroPlugin,
  };

  return mergeConfig(svgTransformer, obfuscatingTransformer);
})();

Try this one:

const { getDefaultConfig, mergeConfig } = require('metro-config');

const config1 = {};
const config2 = {};

module.exports = mergeConfig(config1, config2);

It will return the merged configuration of two or more configuration objects.

本文标签: javascriptConfigure multiple transformersresolvers using metroStack Overflow