Настройка кода во время сборки в React Native с помощью Create React Native App and Expo

Как правило, есть ли способ настроить код приложения на этапе сборки?

В частности, обычно требуется отправлять запросы из приложения в локальный сервер ([1], [2], [3], [4]).

  • localhost не работает, поскольку сервер и приложение находятся на разных хостах (при использовании эмулятора Android или реального физического устройства).
  • Фактический IP-адрес хоста в той же сети работает, но в проекте с несколькими разработчиками постоянно менять постоянный IP-адрес в коде на IP-адрес своей машины разработки сложно.

С помощью Webpack подобный случай можно решить с помощью DefinePlugin, заменив заполнитель IP-адресом. адрес машины, на которой происходит сборка.


person stsloth    schedule 08.06.2018    source источник


Ответы (1)


В итоге мы использовали несколько хакерский подход, вдохновленный преобразователями, такими как react-native-typescript-transformer или < a href="https://www.npmjs.com/package/react-native-sass-transformer" rel="nofollow noreferrer">react-native-sass-transformer. Его идея в значительной степени эквивалентна упомянутому DefinePlugin Webpack.

Во-первых, несколько файлов-трансформеров в каталоге проекта (вы можете называть их как хотите, просто обновите ссылки):

configBuildReplacements.js

// whatever logic you need

module.exports = {
    API_HOST_PLACEHOLDER: `http://${getLocalNetworkAddress()}:3000`,
    SOME_OTHER_DYNAMIC_VALUE: someFun(),
}

configBuildReplaceTransformer.js

const semver = require('semver')    

let upstreamTransformer = null

const reactNativeVersionString = require('react-native/package.json').version
const reactNativeMinorVersion = semver(reactNativeVersionString).minor

if (reactNativeMinorVersion >= 56) {
    upstreamTransformer = require('metro/src/reactNativeTransformer')
}
else if (reactNativeMinorVersion >= 52) {
    upstreamTransformer = require('metro/src/transformer')
}
else if (reactNativeMinorVersion >= 47) {
    upstreamTransformer = require('metro-bundler/src/transformer')
}
else if (reactNativeMinorVersion === 46) {
    upstreamTransformer = require('metro-bundler/build/transformer')
}
else {
    // handle RN <= 0.45
    const oldUpstreamTransformer = require('react-native/packager/transformer')
    upstreamTransformer = {
        transform({ src, filename, options }) {
            return oldUpstreamTransformer.transform(src, filename, options)
        },
    }
}


module.exports.transform = function (src, filename, options) {
    // handle RN >= 0.46
    if (typeof src === 'object') {
        ({ src, filename, options } = src)
    }

    const replacements = require('./configBuildReplacements')

    const modifiedSrc = Object.keys(replacements).reduce(
        (src, replacementKey) => src.replace(
            new RegExp(replacementKey, 'g'),
            replacements[replacementKey],
        ),
        src,
    )

    return upstreamTransformer.transform({
        src: modifiedSrc,
        filename,
        options,
    })
}

Экспортированная функция transform использует экспортированный объект из предыдущего файла configBuildReplacements.js в качестве словаря для замены ключевых подстрок подстроками значений в исходном коде перед передачей этого кода в преобразователь по умолчанию (вышестоящий).

И чтобы подключить этот новый трансформатор к проекту:

  • с Expo добавьте параметр упаковщика transformer к app.json:

    {
      "expo": {
        "packagerOpts": {
          "transformer": "configBuildReplaceTransformer.js"
        }
      }
    }
    
  • без Expo добавьте getTransformModulePath() к rn-cli.config.js (это путь по умолчанию к необязательному файлу конфигурации для React Native CLI, который на момент написания этой статьи крайне плохо документирован):

    module.exports = {
        getTransformModulePath() {
            return require.resolve('./configBuildReplaceTransformer')
        },        
    }
    

После этого, как и в случае с DefinePlugin, код типа

get('API_HOST_PLACEHOLDER/info')

станет чем-то вроде

get('http://192.168.42.23:3000/info')
person stsloth    schedule 12.08.2018