diff --git a/.changeset/curvy-cars-pretend.md b/.changeset/curvy-cars-pretend.md new file mode 100644 index 000000000..805328b3b --- /dev/null +++ b/.changeset/curvy-cars-pretend.md @@ -0,0 +1,5 @@ +--- +"@callstack/repack": patch +--- + +Add `--config-cmd` to options for bundle command for compatibility with RN >= 0.76 diff --git a/.changeset/rare-planes-lie.md b/.changeset/rare-planes-lie.md new file mode 100644 index 000000000..cd9e4d39a --- /dev/null +++ b/.changeset/rare-planes-lie.md @@ -0,0 +1,8 @@ +--- +"@callstack/repack": minor +"@callstack/repack-init": minor +--- + +Use `@react-native-community/cli` explictly iOS project settings (through `CLI_PATH`). + +Drop (unofficial) support for modyfing Android config for RN versions < 0.71. diff --git a/packages/init/src/index.ts b/packages/init/src/index.ts index f992ca540..365a98d2c 100644 --- a/packages/init/src/index.ts +++ b/packages/init/src/index.ts @@ -4,7 +4,6 @@ import checkReactNative from './tasks/checkReactNative.js'; import createBundlerConfig from './tasks/createBundlerConfig.js'; import ensureProjectExists from './tasks/ensureProjectExists.js'; import handleReactNativeConfig from './tasks/handleReactNativeConfig.js'; -import modifyAndroid from './tasks/modifyAndroid.js'; import modifyIOS from './tasks/modifyIOS.js'; import logger, { enableVerboseLogging } from './utils/logger.js'; @@ -31,7 +30,8 @@ export default async function run({ try { const { cwd, rootDir } = await ensureProjectExists(); const packageManager = await checkPackageManager(rootDir); - const reactNativeVersion = checkReactNative(cwd); + + checkReactNative(cwd); await addDependencies(bundler, cwd, packageManager, repackVersion); @@ -39,8 +39,6 @@ export default async function run({ handleReactNativeConfig(bundler, cwd); - modifyAndroid(cwd, reactNativeVersion); - modifyIOS(cwd); logger.done('Setup complete. Thanks for using Re.Pack!'); diff --git a/packages/init/src/tasks/modifyAndroid.ts b/packages/init/src/tasks/modifyAndroid.ts deleted file mode 100644 index d8120e252..000000000 --- a/packages/init/src/tasks/modifyAndroid.ts +++ /dev/null @@ -1,121 +0,0 @@ -import fs from 'node:fs'; -import path from 'node:path'; -import dedent from 'dedent'; -import semver, { type SemVer } from 'semver'; - -import logger from '../utils/logger.js'; - -const defaultOldConfig = dedent` - project.ext.react = [ - bundleCommand: "webpack-bundle", - ]`; - -const defaultNewConfig = dedent` - react { - bundleCommand = "webpack-bundle" - }`; - -function modifyOldConfig(config: string): string { - logger.info('Modifying android/app/build.gradle for React-Native < 0.71.0'); - - // Make sure we capture actual config and not the commented out one - const applyReactGradleRegex = - /(?= 0.71.0'); - - const androidConfig = 'android {'; - const reactConfigIndex = config.indexOf('react {'); - - if (reactConfigIndex === -1) { - // Add the default react config if it doesn't exist - return config.replace( - androidConfig, - defaultNewConfig + '\n\n' + androidConfig - ); - } - - const bundleCommandRegex = /\/\/\sbundleCommand\s*=\s*".*?"/; - if (bundleCommandRegex.test(config)) { - // Replace the commented out bundleCommand - return config.replace( - bundleCommandRegex, - 'bundleCommand = "webpack-bundle"' - ); - } - - const existingBundleCommandRegex = /bundleCommand\s*=\s*".*?"/; - if (existingBundleCommandRegex.test(config)) { - // Replace existing bundleCommand - return config.replace( - existingBundleCommandRegex, - 'bundleCommand = "webpack-bundle"' - ); - } - - // Otherwise, add the bundleCommand to the existing config - return config.replace( - 'react {', - 'react {\n bundleCommand: "webpack-bundle"' - ); -} - -/** - * Modifies the android part of the project to support Re.Pack - * - * @param cwd path for the root directory of the project - * @param reactNativeVersion version of react-native in project - */ -export default function modifyAndroid(cwd: string, reactNativeVersion: SemVer) { - const buildGradlePath = path.join(cwd, 'android', 'app', 'build.gradle'); - const config = fs.readFileSync(buildGradlePath, 'utf-8'); - - if (!fs.existsSync(buildGradlePath)) { - throw Error( - 'File android/app/build.gradle not found. Make sure you are running this command from the root of your project' - ); - } - - logger.info('Found android/app/build.gradle'); - - let updatedConfig: string; - if (semver.minor(reactNativeVersion) >= 71) { - updatedConfig = modifyNewConfig(config); - } else { - updatedConfig = modifyOldConfig(config); - } - - fs.writeFileSync(buildGradlePath, updatedConfig); - logger.success( - 'Added "webpack-bundle" as bundleCommand to android/app/build.gradle' - ); -} diff --git a/packages/init/src/tasks/modifyIOS.ts b/packages/init/src/tasks/modifyIOS.ts index 35b1e33a1..4c45a2ea7 100644 --- a/packages/init/src/tasks/modifyIOS.ts +++ b/packages/init/src/tasks/modifyIOS.ts @@ -1,5 +1,6 @@ import fs from 'node:fs'; import path from 'node:path'; +import dedent from 'dedent'; import xcode from 'xcode'; import logger from '../utils/logger.js'; @@ -41,24 +42,29 @@ function getBundleReactNativePhase( return bundleReactNative; } -function modifyBundleReactNativeShellScript( +function replaceBundleReactNativeShellScript( phase: ShellScriptBuildPhase ): ShellScriptBuildPhase { - const shellScriptContent = phase.shellScript; - const shellScriptContentLines = shellScriptContent.split('\\n'); + const script = dedent` + set -e - const bundleCommand = 'export BUNDLE_COMMAND=webpack-bundle'; + if [[ -f "$PODS_ROOT/../.xcode.env" ]]; then + source "$PODS_ROOT/../.xcode.env" + fi + if [[ -f "$PODS_ROOT/../.xcode.env.local" ]]; then + source "$PODS_ROOT/../.xcode.env.local" + fi - if (shellScriptContentLines.includes(bundleCommand)) { - logger.info( - `${phase.name} phase in project.pbxproj already contains ${bundleCommand}` - ); - return phase; - } + export CLI_PATH="$("$NODE_BINARY" --print "require('path').dirname(require.resolve('@react-native-community/cli/package.json')) + '/build/bin.js'")" + + WITH_ENVIRONMENT="$REACT_NATIVE_PATH/scripts/xcode/with-environment.sh" + REACT_NATIVE_XCODE="$REACT_NATIVE_PATH/scripts/react-native-xcode.sh" - shellScriptContentLines.splice(1, 0, '', bundleCommand); + /bin/sh -c "$WITH_ENVIRONMENT $REACT_NATIVE_XCODE" + `; + + phase.shellScript = `"${script.replace(/"/g, '\\"').split('\n').join('\\n')}\\n"`; - phase.shellScript = shellScriptContentLines.join('\\n'); return phase; } @@ -67,7 +73,7 @@ function modifyPbxprojConfig(pbxprojPath: string) { project.parseSync(); const bundleReactNativePhase = getBundleReactNativePhase(project); - modifyBundleReactNativeShellScript(bundleReactNativePhase); + replaceBundleReactNativeShellScript(bundleReactNativePhase); return project.writeSync(); } @@ -93,7 +99,10 @@ export default function modifyIOS(cwd: string) { const updatedConfig = modifyPbxprojConfig(projectPbxProjPath); fs.writeFileSync(projectPbxProjPath, updatedConfig); - logger.success( - `Added "webpack-bundle" as BUNDLE_COMMAND to build phase shellScript in ${relativeProjectPbxProjPath}` + + logger.info( + `Added "@react-native-community/cli" as CLI_PATH to build phase shellScript in ${relativeProjectPbxProjPath}` ); + + logger.success('Successfully modified iOS project files'); } diff --git a/packages/repack/src/commands/options.ts b/packages/repack/src/commands/options.ts index 622ebbfa8..5387ee271 100644 --- a/packages/repack/src/commands/options.ts +++ b/packages/repack/src/commands/options.ts @@ -113,11 +113,16 @@ export const bundleCommandOptions = [ description: 'Directory name where to store assets referenced in the bundle', }, - // noop, but kept for compatibility + // noop, needed for compatibility { name: '--reset-cache', description: '(unsupported) Resets the transformation cache', }, + // noop, needed for compatibility + { + name: '--config-cmd', + description: '(unsupported) Command to generate a JSON project config', + }, // options specific to Re.Pack { name: '--json ',