Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(cli): only add react and react-native when missing in prebuild #22624

Merged
merged 3 commits into from
Jun 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
1 change: 1 addition & 0 deletions packages/@expo/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@

- Remove entry file modification/index.js generation from `expo prebuild`. Arbitrary entry files in development only work when using `expo-dev-client` or `.expo/.virtual-metro-entry` (SDK +49). ([#22044](https://github.com/expo/expo/pull/22044) by [@EvanBacon](https://github.com/EvanBacon))
- Drop `metro.config.js` copy step in `expo prebuild` in favor of `expo export:embed` and the new Xcode start script using Expo CLI--this only works when using Expo CLI for all bundling (SDK +49). ([#22045](https://github.com/expo/expo/pull/22045) by [@EvanBacon](https://github.com/EvanBacon))
- Skip overwriting `react` and `react-native` dependencies during `expo prebuild`. ([#22624](https://github.com/expo/expo/pull/22624) by [@byCedric](https://github.com/byCedric))

### 🎉 New features

Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,11 @@
import chalk from 'chalk';

import * as Log from '../../log';
import { isModuleSymlinked } from '../../utils/isModuleSymlinked';
import { hashForDependencyMap, updatePkgDependencies } from '../updatePackageJson';

jest.mock('../../utils/isModuleSymlinked');
jest.mock('../../log');

describe(hashForDependencyMap, () => {
it(`dependencies in any order hash to the same value`, () => {
Expand Down Expand Up @@ -44,6 +48,7 @@ describe(updatePkgDependencies, () => {
});
expect(pkg.dependencies).toStrictEqual({
...requiredPackages,
'react-native': 'version-from-project', // add-only package, do not overwrite
'optional-package': 'version-from-project-1',
'optional-package-2': 'version-from-template-2',
'optional-package-3': 'version-from-project-3',
Expand Down Expand Up @@ -105,9 +110,39 @@ describe(updatePkgDependencies, () => {
});
expect(pkg.dependencies).toStrictEqual({
...sdk44RequiredPackages,
'react-native': 'version-from-project', // add-only package, do not overwrite
'optional-package': 'version-from-project-1',
'optional-package-2': 'version-from-template-2',
'optional-package-3': 'version-from-project-3',
});
});
test('does not overwrite add-only packages when defined', () => {
const pkg = {
dependencies: {
expo: 'version-from-project',
'react-native': 'version-from-project',
},
devDependencies: {},
};
updatePkgDependencies('fake path', {
templatePkg: {
dependencies: {
...requiredPackages,
expo: 'version-from-template',
},
devDependencies: {},
},
pkg,
});
expect(pkg.dependencies).toStrictEqual({
...requiredPackages,
'react-native': 'version-from-project', // add-only package, do not overwrite
expo: 'version-from-template',
});
expect(Log.warn).toBeCalledWith(
expect.stringContaining(
`instead of recommended ${chalk.bold('react-native@version-from-template-required-1')}`
)
);
});
});
47 changes: 39 additions & 8 deletions packages/@expo/cli/src/prebuild/updatePackageJson.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ import chalk from 'chalk';
import crypto from 'crypto';
import fs from 'fs';
import path from 'path';
import { intersects as semverIntersects } from 'semver';

import * as Log from '../log';
import { isModuleSymlinked } from '../utils/isModuleSymlinked';
Expand Down Expand Up @@ -128,28 +129,50 @@ export function updatePkgDependencies(
...pkg.dependencies,
});

const addWhenMissingDependencies = ['react', 'react-native'].filter(
(depKey) => !!defaultDependencies[depKey]
);
const requiredDependencies = ['expo', 'expo-splash-screen', 'react', 'react-native'].filter(
(depKey) => !!defaultDependencies[depKey]
);

const symlinkedPackages: string[] = [];
const nonRecommendedPackages: string[] = [];

for (const dependenciesKey of requiredDependencies) {
if (
// If the local package.json defined the dependency that we want to overwrite...
pkg.dependencies?.[dependenciesKey]
) {
if (
// Then ensure it isn't symlinked (i.e. the user has a custom version in their yarn workspace).
isModuleSymlinked(projectRoot, { moduleId: dependenciesKey, isSilent: true })
) {
// If the local package.json defined the dependency that we want to overwrite...
if (pkg.dependencies?.[dependenciesKey]) {
// Then ensure it isn't symlinked (i.e. the user has a custom version in their yarn workspace).
if (isModuleSymlinked(projectRoot, { moduleId: dependenciesKey, isSilent: true })) {
// If the package is in the project's package.json and it's symlinked, then skip overwriting it.
symlinkedPackages.push(dependenciesKey);
continue;
}

// Do not modify manually skipped dependencies
if (skipDependencyUpdate.includes(dependenciesKey)) {
continue;
}

// Ensure the package only needs to be added when missing
if (addWhenMissingDependencies.includes(dependenciesKey)) {
let projectHasRecommended: boolean | null = null;
// Check if the version intersects with the recommended versions
try {
projectHasRecommended = semverIntersects(
pkg.dependencies[dependenciesKey],
String(defaultDependencies[dependenciesKey])
);
} catch {
// If the version is invalid, just warn the user
}
// When the versions can't be parsed `null`, or does not intersect `false`, warn the user
if (projectHasRecommended !== true) {
nonRecommendedPackages.push(`${dependenciesKey}@${defaultDependencies[dependenciesKey]}`);
}
// Do not modify add-only dependencies
continue;
}
}
combinedDependencies[dependenciesKey] = defaultDependencies[dependenciesKey];
}
Expand All @@ -162,6 +185,14 @@ export function updatePkgDependencies(
);
}

if (nonRecommendedPackages.length) {
Log.warn(
`\u203A Using current versions instead of recommended ${nonRecommendedPackages
.map((pkg) => chalk.bold(pkg))
.join(', ')}.`
);
}

const combinedDevDependencies: DependenciesMap = createDependenciesMap({
...defaultDevDependencies,
...pkg.devDependencies,
Expand Down