diff --git a/README.md b/README.md index fbb39ae..1a52001 100644 --- a/README.md +++ b/README.md @@ -35,6 +35,12 @@ Make sure that you have installed the `react-native-svg` library: ### Step 2: Install react-native-svg-transformer library +```sh +npm install --save-dev react-native-svg-transformer +``` + +or + ```sh yarn add --dev react-native-svg-transformer ``` @@ -57,7 +63,7 @@ module.exports = (() => { config.transformer = { ...transformer, - babelTransformerPath: require.resolve("react-native-svg-transformer") + babelTransformerPath: require.resolve("react-native-svg-transformer/expo") }; config.resolver = { ...resolver, @@ -91,7 +97,9 @@ const { assetExts, sourceExts } = defaultConfig.resolver; */ const config = { transformer: { - babelTransformerPath: require.resolve("react-native-svg-transformer") + babelTransformerPath: require.resolve( + "react-native-svg-transformer/react-native" + ) }, resolver: { assetExts: assetExts.filter((ext) => ext !== "svg"), @@ -119,7 +127,9 @@ module.exports = (async () => { } = await getDefaultConfig(); return { transformer: { - babelTransformerPath: require.resolve("react-native-svg-transformer") + babelTransformerPath: require.resolve( + "react-native-svg-transformer/react-native" + ) }, resolver: { assetExts: assetExts.filter((ext) => ext !== "svg"), @@ -129,6 +139,24 @@ module.exports = (async () => { })(); ``` +#### React Native projects using Expo modules + +Some React Native projects are using [Expo modules](https://docs.expo.dev/bare/installing-expo-modules/) without using [expo-cli](https://docs.expo.dev/more/expo-cli/). + +In such projects Expo's transformer is selected by default, and can be overwritten to correctly use React Native's transformer by adding `react-native` to the require path: + +```diff +-require.resolve("react-native-svg-transformer") ++require.resolve("react-native-svg-transformer/react-native") +``` + +You can also force Expo's transformer to always be used: + +```diff +-require.resolve("react-native-svg-transformer") ++require.resolve("react-native-svg-transformer/expo") +``` + ### Using TypeScript If you are using TypeScript, you need to add this to your `declarations.d.ts` file (create one if you don't have one already): @@ -190,15 +218,17 @@ You can then use your image as a component: To use `Jest` to test your React Native components that import `.svg` images, you need to add this configuration that mocks the SVG images that are transformed to React components: +`__mocks__/svgMock.js`: + ```js -// __mocks__/svgMock.js module.exports = "SvgMock"; ``` Then, depending on where you have your Jest configuration: +`package.json`: + ```json -// package.json { "jest": { "moduleNameMapper": { @@ -210,8 +240,9 @@ Then, depending on where you have your Jest configuration: or +`jest.config.js`: + ```js -// jest.config.js module.exports = { moduleNameMapper: { "\\.svg": "/__mocks__/svgMock.js" diff --git a/expo/index.js b/expo/index.js new file mode 100644 index 0000000..b3c3d99 --- /dev/null +++ b/expo/index.js @@ -0,0 +1,3 @@ +const { createTransformer, expoTransformer } = require("../index.js"); + +module.exports.transform = createTransformer(expoTransformer); diff --git a/index.js b/index.js index 196cbd5..9dd500b 100644 --- a/index.js +++ b/index.js @@ -5,19 +5,20 @@ const resolveConfigDir = require("path-dirname"); * `metro-react-native-babel-transformer` has recently been migrated to the React Native * repository and published under the `@react-native/metro-babel-transformer` name. * The new package is default on `react-native` >= 0.73.0, so we need to conditionally load it. - * - * Additionally, Expo v50.0.0 has begun using @expo/metro-config/babel-transformer as its upstream transformer. - * To avoid breaking projects, we should prioritze that package if it is available. */ -const upstreamTransformer = (() => { +const reactNativeTransformer = (() => { + try { + return require("@react-native/metro-babel-transformer"); + } catch (error) { + return require("metro-react-native-babel-transformer"); + } +})(); + +const expoTransformer = (() => { try { return require("@expo/metro-config/babel-transformer"); } catch (error) { - try { - return require("@react-native/metro-babel-transformer"); - } catch (error) { - return require("metro-react-native-babel-transformer"); - } + return null; } })(); @@ -43,17 +44,32 @@ const defaultSVGRConfig = { } }; -module.exports.transform = async ({ src, filename, ...rest }) => { - if (filename.endsWith(".svg")) { - const config = await resolveConfig(resolveConfigDir(filename)); - const svgrConfig = config - ? { ...defaultSVGRConfig, ...config } - : defaultSVGRConfig; - return upstreamTransformer.transform({ - src: await transform(src, svgrConfig), - filename, - ...rest - }); - } - return upstreamTransformer.transform({ src, filename, ...rest }); +function createTransformer(transformer) { + return async ({ src, filename, ...rest }) => { + if (filename.endsWith(".svg")) { + const config = await resolveConfig(resolveConfigDir(filename)); + const svgrConfig = config + ? { ...defaultSVGRConfig, ...config } + : defaultSVGRConfig; + return transformer.transform({ + src: await transform(src, svgrConfig), + filename, + ...rest + }); + } + return transformer.transform({ src, filename, ...rest }); + }; +} + +module.exports = { + reactNativeTransformer, + expoTransformer, + createTransformer, + transform: createTransformer( + /* + * Expo v50.0.0 has begun using @expo/metro-config/babel-transformer as its upstream transformer. + * To avoid breaking projects, we should prioritze that package if it is available. + **/ + expoTransformer || reactNativeTransformer + ) }; diff --git a/package.json b/package.json index e05422e..34f1408 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,8 @@ "author": "Krister Kari", "license": "MIT", "files": [ + "expo/index.js", + "react-native/index.js", "index.js", "CHANGELOG.md", "README.md" @@ -55,7 +57,8 @@ 2, "double" ], - "no-else-return": 2 + "no-else-return": 2, + "space-before-function-paren": 0 } }, "prettier": { diff --git a/react-native/index.js b/react-native/index.js new file mode 100644 index 0000000..4ab82fc --- /dev/null +++ b/react-native/index.js @@ -0,0 +1,3 @@ +const { createTransformer, reactNativeTransformer } = require("../index.js"); + +module.exports.transform = createTransformer(reactNativeTransformer);