5

我正在尝试使用 Metro 为我的 react 本机项目添加多个解析器和转换器,如何将它们组合到我的 metro.config.js 文件中?

背景:我想让一个 sass 变压器和一个 svg 变压器都能工作。

我已经分别尝试了这些配置,这似乎可行,但我对如何组合它们感到困惑,因此它们都可以同时工作。我假设它们需要在同一个 module.exports 中,因为当它们都在同一个文件中时,我的 svg 会出现错误

这些是我试图结合的配置:

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"]
    }
  };
})();

当我尝试使用上面的代码运行它时,即 metro.config.js 中的两个模块导出,似乎只有 sass 转换器工作,当我尝试绘制 svg 时,出现以下错误:

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

3 回答 3

15

我通过创建一个自定义变压器解决了这个问题,如下所示:

customTransformer.js:

// For React Native version 0.59 or later
var upstreamTransformer = require("metro-react-native-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 });
  }
};

在我的 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"]
    }
  };
})();

不知道这是否是最好的方法,但它似乎有效

于 2019-08-26T14:48:18.860 回答
2

试试这个:

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

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

module.exports = mergeConfig(config1, config2);

它将返回两个或多个配置对象的合并配置。

于 2020-10-16T08:51:12.430 回答
0

我使用 metro-config 中的 mergeConfig 解决了这个问题

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);
})();
于 2022-01-24T18:34:16.833 回答