Plugins de Configuração
Um guia prático para plugins de app.config que modificam Info.plist, AndroidManifest.xml e Gradle - a maneira segura de CNG de conectar módulos nativos sem desvios manuais em ios/ e android/.
Busque em todas as páginas da documentação
Um guia prático para plugins de app.config que modificam Info.plist, AndroidManifest.xml e Gradle - a maneira segura de CNG de conectar módulos nativos sem desvios manuais em ios/ e android/.
Cartão de receita de referência rápida - pronto para copiar e colar.
// app.config.ts
import type { ExpoConfig } from "expo/config";
export default ({ config }: { config: ExpoConfig }): ExpoConfig => ({
...config,
plugins: [
// Plugins de permissão embutidos (Info.plist + AndroidManifest)
[
"expo-camera",
{
cameraPermission: "Permitir que $(PRODUCT_NAME) escaneie códigos de barras de produtos",
microphonePermission: false,
},
],
// Propriedades em tempo de compilação (Gradle, propriedades do Podfile)
[
"expo-build-properties",
{
ios: { deploymentTarget: "15.1" },
android: { minSdkVersion: 24, compileSdkVersion: 35 },
},
],
// Plugin local para alterações nativas personalizadas
"./plugins/with-custom-url-scheme",
],
});# Aplica plugins e inspeciona a saída
npx expo prebuild --clean
git diff ios/ android/ # revisa as alterações nativas geradas
# Verificação de idempotência - a segunda execução não deve produzir novo diff
npx expo prebuild
git diff ios/ android/ # espera vazioQuando usar isso:
NSCameraUsageDescription) exigidas por módulos nativos.queries para visibilidade de pacotes.minSdkVersion do Gradle, regras do ProGuard ou alvos de implantação do iOS para um SDK nativo.// app.config.ts
import type { ExpoConfig } from "expo/config";
export default ({ config }: { config: ExpoConfig }): ExpoConfig => ({
...config,
name: "ConfigPluginCookbook",
slug: "config-plugin-cookbook",
plugins: [
[
"expo-camera",
{
cameraPermission:
"Permitir que ConfigPluginCookbook tire fotos para seu perfil",
microphonePermission:
"Permitir que ConfigPluginCookbook grave áudio com vídeo",
recordAudioAndroid: true,
},
],
],
});Após npx expo prebuild, o iOS recebe:
<!-- ios/<App>/Info.plist (gerado) -->
<key>NSCameraUsageDescription</key>
<string>Permitir que ConfigPluginCookbook tire fotos para seu perfil</string>
<key>NSMicrophoneUsageDescription</key>
<string>Permitir que ConfigPluginCookbook grave áudio com vídeo</string>O Android recebe:
<!-- android/app/src/main/AndroidManifest.xml (trecho gerado) -->
<uses-permission android:name="android.permission.CAMERA" />
<uses-permission android:name="android.permission.RECORD_AUDIO" />// plugins/with-custom-url-scheme.ts
import type { ConfigPlugin } from "expo/config-plugins";
import {
AndroidConfig,
IOSConfig,
createRunOncePlugin,
withAndroidManifest,
withInfoPlist,
} from "expo/config-plugins";
const SCHEME = "myshop";
const withCustomUrlScheme: ConfigPlugin = (config) => {
config = withInfoPlist(config, (mod) => {
const urlTypes = mod.modResults.CFBundleURLTypes ?? [];
const exists = urlTypes.some(
(entry) =>
Array.isArray(entry.CFBundleURLSchemes) &&
entry.CFBundleURLSchemes.includes(SCHEME)
);
if (!exists) {
urlTypes.push({
CFBundleURLName: "com.example.myshop",
CFBundleURLSchemes: [SCHEME],
});
mod.modResults.CFBundleURLTypes = urlTypes;
}
return mod;
});
config = withAndroidManifest(config, (mod) => {
const manifest = mod.modResults;
const app = AndroidConfig.Manifest.getMainApplicationOrThrow(manifest);
// Filtro de intenção de deep link
AndroidConfig.Manifest.addIntentFilter(app, {
action: "android.intent.action.VIEW",
category: ["android.intent.category.DEFAULT", "android.intent.category.BROWSABLE"],
data: [{ scheme: SCHEME }],
});
return mod;
});
return config;
};
export default createRunOncePlugin(withCustomUrlScheme, "with-custom-url-scheme", "1.0.0");// app.config.ts - registra o plugin local
import type { ExpoConfig } from "expo/config";
export default ({ config }: { config: ExpoConfig }): ExpoConfig => ({
...config,
plugins: ["./plugins/with-custom-url-scheme"],
});O que isso demonstra:
withInfoPlist muta metadados do iOS de forma idempotente - verifica antes de anexar tipos de URL.withAndroidManifest adiciona filtros de intenção sem desvio de anexação de regex.createRunOncePlugin evita a aplicação duplicada quando o prebuild é executado várias vezes.npx expo prebuild --clean - o contrato CNG por Noções Básicas de Prebuild.// trecho de app.config.ts - SDK nativo requer compileSdk mais alto
plugins: [
[
"expo-build-properties",
{
android: {
minSdkVersion: 24,
compileSdkVersion: 35,
targetSdkVersion: 35,
extraProguardRules: `
-keep class com.vendor.sdk.** { *; }
`,
},
ios: {
deploymentTarget: "15.1",
useFrameworks: "static",
},
},
],
],Veja Aplicando Patch em Projetos Nativos para estratégias avançadas de sobrevivência do Gradle.
app.config.ts / app.json
│
▼
plugins: [ "expo-camera", "./plugins/with-custom-url-scheme" ]
│
▼ (sequencial, na ordem do array)
Plugins Mod: withInfoPlist, withAndroidManifest, withGradleProperties, …
│
▼
ios/ android/ escritos no disco
| Auxiliar Mod | Arquivo de Destino | Uso Típico |
|---|---|---|
withInfoPlist | Info.plist | Descrições de uso, esquemas de URL, modos de segundo plano |
withAndroidManifest | AndroidManifest.xml | Permissões, filtros de intenção, queries |
withGradleProperties | gradle.properties | Argumentos JVM, flags do Android |
withAppBuildGradle | app/build.gradle | Dependências, opções de empacotamento |
withEntitlementsPlist | .entitlements | Domínios associados, push, grupos de chaves |
Quando dois plugins modificam a mesma chave, plugins posteriores vencem. Documente a ordem em app.config.ts:
plugins: [
"expo-router", // Deve ser executado antes de plugins que adicionam ativos de splash
"expo-camera", // Permissões primeiro
"./plugins/with-custom-url-scheme", // Deep links específicos do aplicativo após o roteador
[
"expo-build-properties", // Propriedades de compilação por último - podem depender da estrutura anterior
{ android: { minSdkVersion: 24 } },
],
],// app.config.ts - dinâmico (consciente do ambiente)
import type { ExpoConfig } from "expo/config";
export default ({ config }: { config: ExpoConfig }): ExpoConfig => ({
...config,
extra: {
apiUrl: process.env.EXPO_PUBLIC_API_URL,
},
plugins: [
[
"react-native-maps",
{
iosGoogleMapsApiKey: process.env.GOOGLE_MAPS_IOS_KEY ?? "",
},
],
],
});Segredos pertencem a variáveis de ambiente EAS, não a arquivos .env commitados referenciados no tempo de prebuild em CI.
# Logs detalhados do prebuild
EXPO_DEBUG=1 npx expo prebuild --clean
# Diff apenas do Info.plist
npx expo prebuild --platform ios --clean
diff ios/MyApp/Info.plist ios/MyApp/Info.plist.bak 2>/dev/null || true
# Valida com doctor
npx expo-doctorNS*UsageDescription - o iOS trava no momento da solicitação de permissão. Correção: Use o plugin de configuração da biblioteca ou adicione entradas withInfoPlist.createRunOncePlugin.--clean. Correção: Mova a alteração para um plugin conforme Plugins de Configuração em CNG.<queries>. Correção: withAndroidManifest adiciona entradas queries.| Alternativa | Use Quando | Não Use Quando |
|---|---|---|
| Plugin de configuração embutido do Expo | A biblioteca envia expo-camera, expo-location, etc. | A biblioteca do fornecedor não tem plugin |
Mod expo/config-plugins local | Entitlements ou entradas de manifesto únicas | Grande fork nativo - escreva um módulo Expo adequado |
expo-build-properties | Versões do SDK, ProGuard, alvo de implantação | Cirurgia complexa de múltiplos arquivos Gradle |
| Edições manuais nativas Brownfield | Aplicativo legado não em CNG | Aplicativos greenfield padrão SDK 57 |
Uma função registrada na matriz plugins de app.config que é executada durante npx expo prebuild e modifica arquivos de projeto nativos programaticamente.
Plugins embutidos são distribuídos dentro de pacotes do SDK Expo (expo-camera, expo-build-properties). Plugins personalizados residem em seu repositório - comumente plugins/with-*.ts.
Sim. O EAS Build executa o prebuild (a menos que desabilitado), executando o mesmo pipeline de plugins que o npx expo prebuild local.
Execute npx expo prebuild duas vezes. git diff ios/ android/ após a segunda execução deve estar vazio.
Um módulo nativo implementa chamadas JS-para-nativo em tempo de execução. Um plugin de configuração configura o projeto nativo para que o módulo compile e tenha permissões - eles geralmente são distribuídos juntos.
expo-build-propertiesVersões da Stack: Esta página foi escrita para React 19.2.3, React Native 0.86.0 e Expo SDK 57 (
expo~57.0.4).
Revisado por Chris St. John·Última atualização: 16 de jul. de 2026