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

Breaking: Remove Expo SDK 51 config, switch to app.config.ts #462

Merged
merged 32 commits into from
Jan 24, 2025
Merged
Changes from 13 commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
c39362d
Remove Expo app.json configuration
ProchaLu Nov 18, 2024
08e5933
Add Expo Router settings
ProchaLu Jan 9, 2025
1f5114f
Merge branch 'main' of https://github.com/upleveled/eslint-config-upl…
ProchaLu Jan 9, 2025
5285bc0
Add RSC config to app.json
ProchaLu Jan 9, 2025
046310f
Merge branch 'main' of https://github.com/upleveled/eslint-config-upl…
ProchaLu Jan 10, 2025
e517f2e
Add rsc, expo-splash and eslint-disable
ProchaLu Jan 10, 2025
4eba886
Add RSC to install log
ProchaLu Jan 14, 2025
c1dab94
Remove RSC
ProchaLu Jan 15, 2025
1ef7305
Remove RSC in comments
ProchaLu Jan 15, 2025
a263039
Convert app.json to app.config.ts
ProchaLu Jan 20, 2025
b51e448
Fix lint error, trailing /
ProchaLu Jan 22, 2025
c305cdd
Merge branch 'main' of https://github.com/upleveled/eslint-config-upl…
ProchaLu Jan 22, 2025
ab38f32
Use variable instead of path
ProchaLu Jan 22, 2025
722d8ce
Format file with Prettier
ProchaLu Jan 22, 2025
d0dc9db
Update app.config comment with issue link
ProchaLu Jan 22, 2025
135ab51
Update bin/expo-setup.js
ProchaLu Jan 22, 2025
42491bb
Update bin/expo-setup.js
ProchaLu Jan 22, 2025
dad5d73
Run expo-setup with eslint install
ProchaLu Jan 23, 2025
abc0e43
Remove script exec
ProchaLu Jan 23, 2025
aac3141
Revert to use replace instead of Prettier
ProchaLu Jan 23, 2025
d3caa1d
Add Prettier to expo-setup script
ProchaLu Jan 24, 2025
f9a3a41
Merge branch 'main' of https://github.com/upleveled/eslint-config-upl…
ProchaLu Jan 24, 2025
f8cdd74
Refactor expo-setup script to use promisified exec for adding Prettier
ProchaLu Jan 24, 2025
c23acfc
Add Prettier comment
ProchaLu Jan 24, 2025
758ed1f
Add empty line
ProchaLu Jan 24, 2025
3ee4cbc
Update comment
ProchaLu Jan 24, 2025
de6c878
Refactor inline variables
ProchaLu Jan 24, 2025
78bb7ef
Update bin/expo-setup.js
ProchaLu Jan 24, 2025
ca81b51
Move import to code usage
ProchaLu Jan 24, 2025
67a1833
Update bin/expo-setup.js
karlhorky Jan 24, 2025
decbd22
Update bin/expo-setup.js
karlhorky Jan 24, 2025
a6a2863
Remove .trim
ProchaLu Jan 24, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 21 additions & 25 deletions bin/expo-setup.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,13 @@
// Enable Expo non-default options for performance:
//
// 1. app.json - Enable New Architecture for iOS and Android
// - https://docs.expo.dev/guides/new-architecture/
// 1. app.json - Convert to app.config.ts
// - https://docs.expo.dev/workflow/configuration/
// 2. .env.development, .env.production, eas.json - Enable the new Metro resolver available starting in Expo SDK 51
// - https://github.com/EvanBacon/pillar-valley/commit/ede321ef7addc67e4047624aedb3e92af3cb5060
// - https://archive.ph/MG03E
//
// TODO: Remove when Expo enables New Architecture and new Metro resolver by default
import { readFile, writeFile } from 'node:fs/promises';
import { readFile, unlink, writeFile } from 'node:fs/promises';
import isPlainObject from 'is-plain-obj';

const appFilePath = 'app.json';
Expand All @@ -19,28 +19,24 @@ if (!isPlainObject(appJson) || !isPlainObject(appJson.expo)) {
);
}

appJson.expo.experiments ||= {};
// eslint-disable-next-line @typescript-eslint/no-unsafe-member-access -- Set to empty object in previous line, if falsy
appJson.expo.experiments.typedRoutes = true;

appJson.expo.plugins = [
[
'expo-build-properties',
{
ios: {
newArchEnabled: true,
},
android: {
newArchEnabled: true,
},
},
],
];
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@ProchaLu is this equivalent with the new setting you mentioned comes by default:

This PR updates the project configuration to align with changes introduced in Expo SDK 52. With SDK 52, the extra configuration steps required for SDK 51 are no longer needed. Running pnpm create expo-app@latest . now initializes the app.json file with:

  • expo.newArchEnabled = true

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

A Boolean value that indicates whether the app should use the new architecture. Defaults to true.
https://docs.expo.dev/versions/latest/config/app/#newarchenabled

There is still the possibility to add the specific iOS / Android newArchEnabled settings, but we want to use the newArchEnabled = true in both.

Copy link
Member

@karlhorky karlhorky Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok, that doesn't mention that it's the same as expo-build-properties anywhere, but it's probably the same, so let's stick with that

if you can easily verify that the app is running in the New Architecture, that would be a helpful additional step

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

In the docs from "Enable the New Architecture in an existing project":
SDK 52:

To enable it on both Android and iOS, use the newArchEnabled at the root of the expo object in your app config. You can selectively enable it for a single platform by setting, for example, "android": { "newArchEnabled": true }.

SDK 51:

To enable it, you need to install the expo-build-properties plugin and set newArchEnabled on target platforms.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

ok good, that's probably enough proof, thanks!


await writeFile(appFilePath, JSON.stringify(appJson, null, 2), 'utf8');
console.log(
'✅ Enabled New Architecture and typedRoutes experiment in app.json',
);
const expoConfig =
`import { ExpoConfig } from "expo/config";

const config: ExpoConfig = ${JSON.stringify(appJson.expo, null, 2)
.replace(/"([^"]+)":/g, '$1:')
.replace(/"(.*?)"/g, `'$1'`)
.replace(/([}\]])(\s*[}\]])/g, '$1,$2')
.replace(/}(\s+\])/g, '},$1')
.replace(/(?<!,)(\n\s*[}\]])/g, ',$1')};

Copy link
Member

@karlhorky karlhorky Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

switch to Prettier for this, don't write our own home-grown formatting code

Prettier is installed in bin/install.js, so you should be able to import + use this version:

// The VS Code Prettier extension uses Prettier v2 internally,
// but Preflight uses the latest Prettier version, which causes
// crashes and formatting conflicts:
// https://github.com/prettier/prettier-vscode/pull/3069#issuecomment-1817589047
// https://github.com/prettier/prettier-vscode/issues/3298
// https://github.com/upleveled/preflight/issues/429
'prettier',

Copy link
Member Author

@ProchaLu ProchaLu Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I can run the Prettier with await promisify(exec)('npx prettier --write app.config.ts');

This command runs local Prettier and formats the app.config.ts file.

722d8ce

Copy link
Member

@karlhorky karlhorky Jan 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

let's use the Prettier API since we're already executing JS

Copy link
Member Author

@ProchaLu ProchaLu Jan 23, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

To use Prettier, ESLint needs to be installed first. However, the current Command Line Cheatsheet places the ESLint installation as the final step (step 4). Since we require Prettier to format app.config.ts during the transition from app.json, this causes a problem.

Changing the order of steps in the cheatsheet is not an option.

Potential solutions without creating a CLI:

  • Stick with app.json and wait for Expo to address the issue and uses app.config.ts
  • Use a script with the replace method instead of Prettier to format app.config.ts
  • Provide the script for students to copy, run manually, and delete after execution (maybe bad)
  • Manually switching or reordering the setup steps introduces too much complexity and room for errors

The best solution right now seems to be using the replace method, avoiding unnecessary dependencies, avoid changing the Command Line Cheatsheet and reducing the risk of errors.

Reverted and used replace instead again.
aac3141

Update:

Also tested with a echo command to create the file, but students still have to remove the app.json file manually, or use a rm -rf command

echo -e "import { type ExpoConfig } from \"expo/config\";\n\nconst config: ExpoConfig = {\n  name: '$(\jq -r '.expo.name' app.json)',\n  slug: '$(\jq -r '.expo.slug' app.json)',\n  version: '1.0.0',\n  orientation: 'portrait',\n  icon: './assets/images/icon.png',\n  scheme: 'myapp',\n  userInterfaceStyle: 'automatic',\n  newArchEnabled: true,\n  ios: {\n    supportsTablet: true,\n  },\n  android: {\n    adaptiveIcon: {\n      foregroundImage: './assets/images/adaptive-icon.png',\n      backgroundColor: '#ffffff',\n    },\n  },\n  web: {\n    bundler: 'metro',\n    output: 'static',\n    favicon: './assets/images/favicon.png',\n  },\n  plugins: [\n    'expo-router',\n    [\n      'expo-splash-screen',\n      {\n        image: './assets/images/splash-icon.png',\n        imageWidth: 200,\n        resizeMode: 'contain',\n        backgroundColor: '#ffffff',\n      },\n    ],\n  ],\n  experiments: {\n    typedRoutes: true,\n  },\n};\n\nexport default config;" > app.config.ts

rm app.json 

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We came to the solution to add Prettier in the expo-setup script, and format the app.config.ts file with it. f8cdd74

export default config;
`.trim() + '\n';

await writeFile('app.config.ts', expoConfig, 'utf8');
console.log('✅ Converted app.json to app.config.ts');
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

since we're taking over converting to app.config.ts, we need to have a code comment in this code to point to an Expo issue or PR that create-expo-app / create-expo (mention both names in the issue / PR if you create it) should be the config format that is generated - active maintainers of create-expo-app can be tagged on this issue / PR (maybe Simek is active, not sure)

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Created an issue in the Expo for generating app.config.ts as the default configuration format and updated the code comment to include the issue link.

d0dc9db


await unlink(appFilePath);
console.log('✅ Deleted app.json');

await writeFile('.env.development', 'EXPO_USE_FAST_RESOLVER=1', 'utf8');
console.log('✅ Enabled new Metro resolver in .env.development');
Expand Down
Loading