Сконфигурируйте несколько трансформаторов / резольверов, используя метро
Я пытаюсь добавить несколько преобразователей и преобразователей, используя metro для моего собственного собственного реактивного проекта, как мне объединить их в моем файле metro.config.js?
Предыстория: я хочу, чтобы работал и sass-трансформер, и svg-трансформер.
Я пробовал конфигурации отдельно, и это, кажется, работает, но я не понимаю, как их объединить, чтобы они работали одновременно. Я предполагаю, что они должны быть в одном модуле.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 ответа
Я решил это, создав собственный преобразователь следующим образом:
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"]
}
};
})();
Не знаю, если это лучший способ, но, похоже, работает
Я решаю эту проблему с помощью mergeConfig из 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);
})();
Попробуй это:
const { getDefaultConfig, mergeConfig } = require('metro-config');
const config1 = {};
const config2 = {};
module.exports = mergeConfig(config1, config2);
Как предложил Грегори,
mergeConfig
кажется намного более чистым подходом:https://developerayo.github.io/metro/docs/en/configuration#merging-example