如何在Cordova config.xml中访问Xcode变量?多Target动态注入
Absolutely, you can pull in Xcode Target-specific variables into your Cordova config.xml and set up dynamic injection for different builds—this is a common setup for Cordova apps that need multiple flavors, and I’ve used this approach successfully for several projects. Here’s the step-by-step optimal implementation:
Core Idea
Cordova doesn’t natively support reading Xcode Target variables directly in config.xml, but we can use Cordova build hooks alongside Xcode environment variables to dynamically modify the config.xml (or related iOS native files) before each build, injecting values specific to the selected Target.
Step 1: Define Custom Variables in Xcode Targets
First, set up unique values for each Target in Xcode:
- Open your Cordova-generated Xcode project, select the Target you want to configure.
- Go to Build Settings, scroll down to the User-Defined section (add it if it doesn’t exist).
- Create custom variables like
CORDOVA_APP_NAME,CORDOVA_API_URL,CORDOVA_BUNDLE_ID_SUFFIX—assign distinct values for each Target (e.g.,CORDOVA_API_URLcould behttps://api-staging.comfor your Staging Target,https://api-production.comfor Production).
Step 2: Create a Cordova Build Hook Script
We’ll use a before_prepare hook to replace placeholder values in config.xml with the Xcode Target’s variables. Here’s how:
- If your project doesn’t have a
hooksfolder, create one at the root of your Cordova project. - Add a Node.js script (e.g.,
01_replace_config_placeholders.js) to thehooks/before_preparedirectory:module.exports = function(context) { const fs = require('fs'); const path = require('path'); const configPath = path.join(context.opts.projectRoot, 'config.xml'); let configContent = fs.readFileSync(configPath, 'utf8'); // Pull values from environment variables (set by Xcode or build scripts) const appName = process.env.CORDOVA_APP_NAME || 'My Default App'; const apiUrl = process.env.CORDOVA_API_URL || 'https://default-api.com'; const bundleIdSuffix = process.env.CORDOVA_BUNDLE_ID_SUFFIX || ''; // Replace placeholders in config.xml configContent = configContent.replace(/{{APP_NAME}}/g, appName); configContent = configContent.replace(/{{API_URL}}/g, apiUrl); configContent = configContent.replace(/{{BUNDLE_ID_SUFFIX}}/g, bundleIdSuffix); // Write the modified config back fs.writeFileSync(configPath, configContent, 'utf8'); }; - Make sure the script has execute permissions (run
chmod +x hooks/before_prepare/01_replace_config_placeholders.jsif needed on macOS/Linux).
Step 3: Add Placeholders to Your Base config.xml
Update your root config.xml to use the placeholders we’ll replace:
<widget id="com.yourcompany.app{{BUNDLE_ID_SUFFIX}}" version="1.0.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0"> <name>{{APP_NAME}}</name> <description>My awesome app</description> <preference name="API_URL" value="{{API_URL}}" /> <!-- Rest of your config --> </widget>
Step 4: Link Xcode Targets to the Hook
To ensure the hook gets the right variables when building from Xcode:
- For each Target, go to Build Phases and add a Run Script phase (drag it before the
CordovaPreparephase). - In the script, set the environment variables specific to the Target, then trigger Cordova’s prepare step:
# Set variables for this Target export CORDOVA_APP_NAME="My Staging App" export CORDOVA_API_URL="https://api-staging.com" export CORDOVA_BUNDLE_ID_SUFFIX=".staging" # Run Cordova prepare to trigger the hook cordova prepare ios
Key Notes & Optimizations
- Backup Your Base config.xml: Since the hook modifies the file directly, keep a backup (or use Git to track changes) so you can revert if needed.
- CI/CD Compatibility: For automated builds, set the same environment variables in your CI pipeline (e.g., GitHub Actions, GitLab CI) based on the build target, then run
cordova build ios --target=<your-target>to trigger the hook. - Alternative: Modify Native iOS Files: If you need to inject values directly into
Info.plistor other native files, extend the hook script to modify those instead of (or alongside)config.xml.
This setup gives you a single shared config.xml that adapts dynamically to whichever Xcode Target you select for building—exactly what you’re looking for.
内容的提问来源于stack exchange,提问作者justin henricks

