Frederik Winkelsdorf
Frederik Winkelsdorf

Reputation: 4573

How to append extension in metro.config.js for Metro Bundler?

I'm trying to bundle markdown files without creating much overhead (i.e. not adding them manually to the asset bundles in Xcode and Android Studio, not using 3rd party dependencies).

My idea was to allow require() to include them by adjusting the metro bundler settings in metro.config.js:

/**
 * Metro configuration for React Native
 * https://github.com/facebook/react-native
 *
 * @format
 */

module.exports = {
    transformer: {
        getTransformOptions: async () => ({
            transform: {
                experimentalImportSupport: false,
                inlineRequires: false,
            },
        }),
    },
    resolver: {
        assetExts: [`md`] // < include md
    }
};

Sadly metro bundler replaces the array of given defaults with what's set here.

I don't want to explicitly repeat the default asset extension list which lists about 20+ file extensions, especially since I want to stick to the defaults otherwise. See: https://github.com/facebook/metro/blob/master/packages/metro-config/src/defaults/defaults.js.

Appending to the array does not work, too.

Using RN 0.59.3.

Anything I'm missing?

Upvotes: 9

Views: 19384

Answers (3)

علی داودی
علی داودی

Reputation: 421

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;

This works on RN 0.72.3

Good luck

Upvotes: 1

fengelhardt
fengelhardt

Reputation: 1653

Other way you could do this is use the same syntax as react-native-svg-transformer

  1. Make metro.config.js asynchronous
  2. call the getDefaultConfig
  3. Pull off the assetExts key

Example

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

module.exports = (async () => {
    const {
        resolver: { assetExts },
    } = await getDefaultConfig()
    return {
        transformer: {
            getTransformOptions: async () => ({
                transform: {
                    experimentalImportSupport: false,
                    inlineRequires: false,
                },
            }),
        },
        resolver: {
            assetExts: [...assetExts, 'md'],
        },
    }
})()

Upvotes: 3

Frederik Winkelsdorf
Frederik Winkelsdorf

Reputation: 4573

Found the answer on how to include the defaults here: https://stackoverflow.com/a/55118654/844907.

/**
 * Metro configuration for React Native
 * https://github.com/facebook/react-native
 *
 * @format
 */

// get defaults assetExts array
const defaultAssetExts = require("metro-config/src/defaults/defaults").assetExts;

module.exports = {
    transformer: {
        getTransformOptions: async () => ({
            transform: {
                experimentalImportSupport: false,
                inlineRequires: false,
            },
        }),
    },
    resolver: {
        assetExts: [
            ...defaultAssetExts, // <- array spreading defaults
            'md'
        ]
    }
};

Upvotes: 20

Related Questions