Skrive den første config-pluginen
Opprett en withMyPlugin-funksjon ved hjelp av hjelpefunksjonene i @expo/config-plugins, legg den til i plugins-arrayet i app.json, og kjør expo prebuild for å kontrollere det native resultatet.
Skrive den første config-pluginen er en gratis leksjon i React Native Academy på CoddyKit. Dette er leksjon 2 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i React Native Academy, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i React Native Academy inneholder totalt 4 leksjoner.
Prosjektoppsett for en config-plugin
De kan skrive en config-plugin som en fil i prosjektet Deres eller som en separat npm-pakke. For prosjektspesifikke plugins oppretter De en plugins/-mappe i prosjektroten og legger plugin-filen der. Referer til den i app.json ved hjelp av en relativ bane. Denne tilnærmingen holder plugin-modulen sammen med appen og krever ingen publisering.
# Project structure
your-expo-app/
plugins/
withCustomPermissions.js <- your plugin
app.json
App.tsx
# app.json reference
{
'expo': {
'plugins': [
['./plugins/withCustomPermissions', { 'reason': 'Scan QR codes' }]
]
}
}Signaturen til funksjonen withMyPlugin
Alle config-plugins er synkrone funksjoner som tar to argumenter: config (hele Expo-konfigurasjonsobjektet) og et valgfritt options-objekt som sendes fra app.json. Funksjonen må returnere det (endrede) konfigurasjonsobjektet. De lenker Expos innebygde modifikatorhjelpere sammen i denne funksjonen for å gjøre bestemte endringer i native-filer, og returnerer deretter resultatet fra det siste modifikatorkallet.
// plugins/withCustomPermissions.js
const { withInfoPlist } = require('@expo/config-plugins');
/**
* @param {import('@expo/config-plugins').ExpoConfig} config
* @param {{ reason: string }} options
*/
function withCustomPermissions(config, options = {}) {
const reason = options.reason || 'This app requires camera access.';
return withInfoPlist(config, (iosConfig) => {
iosConfig.modResults['NSCameraUsageDescription'] = reason;
return iosConfig;
});
}
module.exports = withCustomPermissions;Forstå modResults
Inne i en mod-callback, som den som sendes til withInfoPlist, mottar De et config-objekt der config.modResults inneholder den tolkede native-filen som et JavaScript-objekt. For withInfoPlist er dette et vanlig objekt som gjenspeiler plist-ordboken. For withAndroidManifest er det et tolket XML-dokument. De endrer modResults direkte og returnerer config-objektet – Expo serialiserer det automatisk tilbake til det native filformatet.
const { withInfoPlist } = require('@expo/config-plugins');
module.exports = function withAppTrackingPermission(config) {
return withInfoPlist(config, (iosConfig) => {
// modResults is the parsed Info.plist dictionary
const plist = iosConfig.modResults;
// Add multiple keys at once
plist['NSUserTrackingUsageDescription'] =
'We use tracking to improve your ad experience.';
plist['ITSAppUsesNonExemptEncryption'] = false;
return iosConfig;
});
};Endre AndroidManifest.xml
Bruk withAndroidManifest til å endre AndroidManifest.xml. modResults er et XML-objekt som er tolket av biblioteket xmldom. Expos AndroidConfig-hjelpere tilbyr hjelpefunksjoner som addUsesPermission, addMetaDataItemToMainActivity og getMainApplication, som opererer på denne XML-strukturen. Derfor trenger De sjelden å manipulere XML DOM direkte.
const { withAndroidManifest, AndroidConfig } = require('@expo/config-plugins');
const { addUsesPermission } = AndroidConfig.Permissions;
module.exports = function withBluetoothPermissions(config) {
return withAndroidManifest(config, (androidConfig) => {
const manifest = androidConfig.modResults;
// Add multiple permissions
addUsesPermission(manifest, 'android.permission.BLUETOOTH');
addUsesPermission(manifest, 'android.permission.BLUETOOTH_ADMIN');
addUsesPermission(manifest, 'android.permission.BLUETOOTH_SCAN');
return androidConfig;
});
};Teste plugin-modulen Deres med expo prebuild
Kjør npx expo prebuild --clean for å teste plugin-modulen Deres og inspisere de genererte native-filene. Bruk --clean for å starte med et rent utgangspunkt. Etter prebuild åpner De de genererte filene for å kontrollere at endringene ble utført. For plist-endringer kontrollerer De ios/YourApp/Info.plist. For manifest-endringer kontrollerer De android/app/src/main/AndroidManifest.xml. Rett eventuelle problemer i plugin-filen og kjør prebuild på nytt til resultatet er riktig.
# Test the plugin
npx expo prebuild --clean --platform ios
# Verify the change in Info.plist
plutil -p ios/MyApp/Info.plist | grep -A1 Camera
# Output:
# "NSCameraUsageDescription" => "Scan QR codes."
# For Android
cat android/app/src/main/AndroidManifest.xml | grep BLUETOOTHLegge til filer i det native-prosjektet
Noen plugins må kopiere filer inn i det native-prosjektet – for eksempel en Google Services JSON-fil eller en egendefinert font. Bruk withDangerousMod for vilkårlige filsystemoperasjoner under prebuild. Dette er en nødløsning for endringer som ikke dekkes av andre hjelpere. Bruk den med måte, og dokumenter bivirkningene tydelig.
const { withDangerousMod } = require('@expo/config-plugins');
const path = require('path');
const fs = require('fs');
module.exports = function withGoogleServicesJson(config) {
return withDangerousMod(config, [
'android',
async (dangerousConfig) => {
const projectRoot = dangerousConfig.modRequest.projectRoot;
const src = path.join(projectRoot, 'google-services.json');
const dest = path.join(projectRoot, 'android', 'app', 'google-services.json');
if (!fs.existsSync(src)) {
throw new Error('google-services.json not found in project root');
}
fs.copyFileSync(src, dest);
return dangerousConfig;
},
]);
};Få tilgang til konfigurasjonsverdier i en plugin
config-objektet som sendes til plugin-modulen Deres, inneholder hele Expo-konfigurasjonen, inkludert verdier fra app.json. De kan lese config.name, config.version, config.ios.bundleIdentifier, config.android.package og eventuelle extra-felt De har definert. Dette gjør at plugin-modulen kan være datadrevet og basere seg på appkonfigurasjonen i stedet for hardkodede verdier.
module.exports = function withAppMetadata(config) {
const appName = config.name;
const bundleId = config.ios?.bundleIdentifier;
const version = config.version;
return withInfoPlist(config, (iosConfig) => {
iosConfig.modResults['CFBundleDisplayName'] = appName;
// Log for debugging during prebuild
console.log(
'[withAppMetadata] Setting display name to:', appName,
'for bundle:', bundleId, 'v' + version
);
return iosConfig;
});
};Endre build.gradle med withAppBuildGradle
For å endre build.gradle-filen på Android-appnivå bruker De withAppBuildGradle. Egenskapen modResults.contents inneholder filen som en rå tekststreng, og De bruker strengmanipulering eller regulære uttrykk til å sette inn endringene. Denne tilnærmingen er nødvendig for å legge til Gradle-avhengigheter, plugin-deklarasjoner eller egendefinerte byggkonfigurasjoner som hjelpefunksjonene på høyere nivå ikke dekker.
const { withAppBuildGradle } = require('@expo/config-plugins');
module.exports = function withGooglePlayServicesPlugin(config) {
return withAppBuildGradle(config, (gradleConfig) => {
const contents = gradleConfig.modResults.contents;
// Add google-services plugin if not already present
if (!contents.includes('com.google.gms.google-services')) {
gradleConfig.modResults.contents = contents.replace(
'apply plugin: "com.android.application"',
'apply plugin: "com.android.application"\napply plugin: "com.google.gms.google-services"'
);
}
return gradleConfig;
});
};Endre Xcode-prosjektet med withXcodeProject
For endringer i selve Xcode-prosjektfilen – som å legge til en byggefase, koble til et native-bibliotek eller legge til en funksjon – bruker De withXcodeProject. modResults er et XcodeProject-objekt fra npm-pakken xcode. Dette er den mest komplekse moden og krever kjennskap til Xcode-prosjektformatet. Foretrekk hjelpefunksjoner på høyere nivå når slike finnes.
const { withXcodeProject } = require('@expo/config-plugins');
module.exports = function withRunScript(config) {
return withXcodeProject(config, (xcode) => {
const project = xcode.modResults;
const target = project.getFirstTarget().uuid;
// Add a run script build phase
project.addBuildPhase(
[],
'PBXShellScriptBuildPhase',
'Bundle React Native code and images',
target,
{ shellPath: '/bin/sh', shellScript: 'echo Running custom script' }
);
return xcode;
});
};Entitlements med withEntitlementsPlist
iOS-entitlements er funksjonsdeklarasjoner i en .entitlements-fil som må samsvare med provisioning-profilen Deres. Bruk withEntitlementsPlist til å legge til entitlements som Push Notifications, iCloud, HealthKit eller App Groups. Uten riktige entitlements mislykkes funksjoner stille ved kjøring på enheten, selv om koden ser riktig ut.
const { withEntitlementsPlist } = require('@expo/config-plugins');
module.exports = function withPushNotifications(config) {
return withEntitlementsPlist(config, (iosConfig) => {
const entitlements = iosConfig.modResults;
// Enable push notifications capability
entitlements['aps-environment'] = 'production';
// App Groups for sharing data with extensions
if (!entitlements['com.apple.security.application-groups']) {
entitlements['com.apple.security.application-groups'] = [];
}
entitlements['com.apple.security.application-groups'].push(
'group.com.yourapp.shared'
);
return iosConfig;
});
};Sette sammen en komplett plugin
Plugins i virkelige prosjekter må ofte endre flere native-filer på tvers av begge plattformene. Sett sammen hjelpefunksjonene i rekkefølge, og send resultatet fra hver funksjon videre til den neste. Legg til tydelig validering av inndata øverst, og logg fremdriftsmeldinger slik at utviklere kan se hvilke endringer plugin-modulen gjorde under prebuild. Returner den endelige konfigurasjonen etter alle endringene.
const {
withInfoPlist,
withAndroidManifest,
withEntitlementsPlist,
AndroidConfig,
} = require('@expo/config-plugins');
module.exports = function withPaymentSDK(config, opts = {}) {
if (!opts.merchantId) {
throw new Error('withPaymentSDK requires a merchantId option.');
}
// iOS
config = withInfoPlist(config, (c) => {
c.modResults['PaymentMerchantId'] = opts.merchantId;
return c;
});
config = withEntitlementsPlist(config, (c) => {
c.modResults['com.apple.developer.in-app-payments'] = [opts.merchantId];
return c;
});
// Android
config = withAndroidManifest(config, (c) => {
AndroidConfig.Permissions.addUsesPermission(
c.modResults, 'android.permission.INTERNET'
);
return c;
});
return config;
};Hurtigsjekk
Test forståelsen Deres av konseptene innen React Native Mobile Development fra denne leksjonen.
Oppsummering av leksjonen
I denne leksjonen lærte De: hvordan De skriver en config-plugin-funksjon som tar config og options og returnerer den endrede konfigurasjonen, hvordan De bruker withInfoPlist, withAndroidManifest, withEntitlementsPlist og withDangerousMod og hvordan De tester plugin-modulen Deres med expo prebuild --clean. De så også hvordan flere mods kan settes sammen til en komplett plugin på tvers av plattformer. Neste gang utforsker vi hvordan AndroidManifest og Info.plist endres i detalj.
Lær deg JavaScript med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 30
- Leksjoner
- 120
Ofte stilte spørsmål
Er leksjonen «Skrive den første config-pluginen» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien React Native Academy, inkludert «Skrive den første config-pluginen», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i React Native Academy inneholder totalt 4 leksjoner.
Hva lærer jeg i «Skrive den første config-pluginen»?
Opprett en withMyPlugin-funksjon ved hjelp av hjelpefunksjonene i @expo/config-plugins, legg den til i plugins-arrayet i app.json, og kjør expo prebuild for å kontrollere det native resultatet. Du øver på React Native Academy med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med React Native Academy?
Ingen tidligere erfaring er nødvendig. React Native Academy på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 2 av 4.
Hvor lang tid tar leksjonen «Skrive den første config-pluginen»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne React Native Academy-leksjonen?
Ja. Alle React Native Academy-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- Hva er config plugins, og når brukes de
- Skrive den første config-pluginen
- Endre AndroidManifest og Info.plist
- Distribuere config plugins som npm-pakker