Skip to content

Commit

Permalink
feat: upgrade template and repo to Yarn 3 (#421)
Browse files Browse the repository at this point in the history
### Summary

This migrates the repo and the templates to Yarn 3 from Yarn 1.

- Yarn 1 is no longer receiving any updates or bug fixes, so it's better
to move to an actively maintained version.
- Previously the generated app was a fake monorepo that worked by
overriding the `yarn` binary. Now it works like a regular monorepo
without any hacks.

### Test plan

- Generate a native module project and make sure it builds and runs on
iOS & Android
- Make an Expo project and make sure it runs on iOS, Android & Web
  • Loading branch information
satya164 authored Sep 22, 2023
1 parent 2a92f26 commit f90ce89
Show file tree
Hide file tree
Showing 25 changed files with 12,891 additions and 6,806 deletions.
3 changes: 2 additions & 1 deletion .github/actions/setup/action.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,13 @@ runs:
with:
path: |
**/node_modules
.yarn/install-state.gz
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**/package.json') }}
restore-keys: |
${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
${{ runner.os }}-yarn-
- name: Install dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: yarn install --frozen-lockfile
run: yarn install --immutable
shell: bash
19 changes: 11 additions & 8 deletions .github/workflows/build-templates.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
--author-url https://test.test \
--repo-url https://test.test \
--type ${{ matrix.type }} \
--languages ${{ matrix.language }} \
--languages ${{ matrix.language }}
- name: Cache dependencies of library
id: library-yarn-cache
Expand All @@ -129,8 +129,11 @@ jobs:
if: steps.library-yarn-cache.outputs.cache-hit != 'true'
working-directory: ${{ env.work_dir }}
run: |
yarn install --cwd example
yarn install
touch yarn.lock # Without this Yarn will fail due to the parent directory being a Yarn workspace
rm -f example/yarn.lock # Workaround for cached yarn.lock from older version
yarn install --no-immutable
env:
POD_INSTALL: 0

- name: Get build target
working-directory: ${{ env.work_dir }}
Expand Down Expand Up @@ -163,8 +166,8 @@ jobs:
if: env.android_build == 1 || env.ios_build == 1
working-directory: ${{ env.work_dir }}
run: |
TURBO_CACHE_STATUS_ANDROID=$(node -p "($(yarn --silent turbo run build:android --cache-dir=".turbo/cache" --dry=json)).tasks.find(t => t.task === 'build:android').cache.status")
TURBO_CACHE_STATUS_IOS=$(node -p "($(yarn --silent turbo run build:ios --cache-dir=".turbo/cache" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status")
TURBO_CACHE_STATUS_ANDROID=$(node -p "($(yarn turbo run build:android --cache-dir=".turbo" --dry=json)).tasks.find(t => t.task === 'build:android').cache.status")
TURBO_CACHE_STATUS_IOS=$(node -p "($(yarn turbo run build:ios --cache-dir=".turbo" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status")
if [[ $TURBO_CACHE_STATUS_ANDROID == "HIT" ]]; then
echo "turbo_cache_hit_android=1" >> $GITHUB_ENV
Expand Down Expand Up @@ -227,7 +230,7 @@ jobs:
if: env.android_build == 1
working-directory: ${{ env.work_dir }}
run: |
yarn turbo run build:android --cache-dir=".turbo/cache"
yarn turbo run build:android --cache-dir=".turbo"
- name: Cache cocoapods
if: env.ios_build == 1 && env.turbo_cache_hit_ios != 1
Expand All @@ -246,12 +249,12 @@ jobs:
if: env.ios_build == 1 && env.turbo_cache_hit_ios != 1 && steps.library-cocoapods-cache.outputs.cache-hit != 'true'
working-directory: ${{ env.work_dir }}
run: |
yarn example pods
yarn pod-install example/ios
env:
NO_FLIPPER: 1

- name: Build example (iOS)
if: env.ios_build == 1
working-directory: ${{ env.work_dir }}
run: |
yarn turbo run build:ios --cache-dir=".turbo/cache"
yarn turbo run build:ios --cache-dir=".turbo"
8 changes: 8 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,14 @@ build/Release
node_modules/
jspm_packages/

# Yarn
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Typescript v1 declaration files
typings/

Expand Down
541 changes: 541 additions & 0 deletions .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs

Large diffs are not rendered by default.

28 changes: 28 additions & 0 deletions .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs

Large diffs are not rendered by default.

874 changes: 874 additions & 0 deletions .yarn/releases/yarn-3.6.1.cjs

Large diffs are not rendered by default.

9 changes: 9 additions & 0 deletions .yarnrc.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
nodeLinker: node-modules

plugins:
- path: .yarn/plugins/@yarnpkg/plugin-workspace-tools.cjs
spec: "@yarnpkg/plugin-workspace-tools"
- path: .yarn/plugins/@yarnpkg/plugin-interactive-tools.cjs
spec: "@yarnpkg/plugin-interactive-tools"

yarnPath: .yarn/releases/yarn-3.6.1.cjs
32 changes: 30 additions & 2 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -250,12 +250,12 @@ If your library depends on another react-native library containing native code,

- **Add the native library to `peerDependencies`**

This means that the user will need to install the native library and add it to their `package.json`. It makes sure that:
This means that the consumer of the library will need to install the native library and add it to the `dependencies` section of their `package.json`. It makes sure that:

- There are no version conflicts if another package also happens to use the same library, or if the user wants to use the library in their app. While there can be multiple versions of a JavaScript-only library, there can only be one version of a native library - so avoiding version conflicts is important.
- The package manager installs it in correct location so that autolinking can work properly.

Don't add the native library to `dependencies`, otherwise it may cause issues for the user even if it seems to work.
Don't add the native library to `dependencies` of your library, otherwise it may cause issues for the user even if it seems to work.

- **Add the native library to `devDependencies`**

Expand Down Expand Up @@ -339,6 +339,34 @@ For more accurate testing, we recommend following approaches:

You can find installation and usage instructions in the [Verdaccio documentation](https://verdaccio.org/docs/en/installation).

### Users get a warning when they install my library

If users are using Yarn 1, they may get a warning when installing your library:

```sh
warning Workspaces can only be enabled in private projects.
```

This is because the example app is configured as a Yarn workspace, and there is a [bug in Yarn 1](https://github.com/yarnpkg/yarn/issues/8580) which causes this warning to be shown for third-party packages. It has no impact for the consumers of the library and the warning can be ignored. If consumers would like to get rid of the warning, there are 2 options:

1. **Disable workspaces**

If the consumer doesn't use Yarn workspaces, they can disable it by adding the following to the `.yarnrc` file in the root of their project:

```rc
workspaces-experimental false
```

2. **Upgrade to Yarn 3**

Yarn 1 is no longer maintained, so it's recommended to upgrade to Yarn 3. Yarn 3 works with React Native projects with the `node-modules` linker. To upgrade, consumers can follow the [official upgrade guide](https://yarnpkg.com/migration/guide).

It's also necessary to use `node-modules` linker. To use it, consumers can add the following to the `.yarnrc.yml` file in the root of their project:

```yml
nodeLinker: node-modules
```
## Development workflow
This project uses a monorepo using `yarn`. To setup the project, run `yarn` in the root directory to install the required dependencies.
Expand Down
2 changes: 1 addition & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,10 @@
"type": "git",
"url": "git+https://github.com/react-navigation/react-navigation.git"
},
"packageManager": "[email protected]",
"engines": {
"node": ">= 18.0.0"
},
"packageManager": "^[email protected]",
"scripts": {
"lint": "eslint \"**/*.{js,ts,tsx}\"",
"typecheck": "tsc --noEmit",
Expand Down
4 changes: 1 addition & 3 deletions packages/create-react-native-library/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -24,9 +24,7 @@
},
"homepage": "https://github.com/callstack/react-native-builder-bob/blob/main/README.md",
"main": "lib/index.js",
"bin": {
"create-react-native-library": "bin/create-react-native-library"
},
"bin": "bin/create-react-native-library",
"files": [
"lib",
"templates"
Expand Down
8 changes: 6 additions & 2 deletions packages/create-react-native-library/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,10 @@ import { spawn } from './utils/spawn';

const FALLBACK_BOB_VERSION = '0.20.0';

const BINARIES = /(gradlew|\.(jar|keystore|png|jpg|gif))$/;
const BINARIES = [
/(gradlew|\.(jar|keystore|png|jpg|gif))$/,
/\$\.yarn(?![a-z])/,
];

const COMMON_FILES = path.resolve(__dirname, '../templates/common');
const JS_FILES = path.resolve(__dirname, '../templates/js-library');
Expand Down Expand Up @@ -573,7 +576,7 @@ async function create(argv: yargs.Arguments<any>) {

if (stats.isDirectory()) {
await copyDir(file, target);
} else if (!file.match(BINARIES)) {
} else if (!BINARIES.some((r) => r.test(file))) {
const content = await fs.readFile(file, 'utf8');

await fs.writeFile(target, ejs.render(content, options));
Expand Down Expand Up @@ -604,6 +607,7 @@ async function create(argv: yargs.Arguments<any>) {
await generateExampleApp({
type: example,
dest: folder,
slug: options.project.slug,
projectName: options.project.name,
arch,
reactNativeVersion,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,12 +50,14 @@ const PACKAGES_TO_ADD_WEB_DEV = {
export default async function generateExampleApp({
type,
dest,
slug,
projectName,
arch,
reactNativeVersion = 'latest',
}: {
type: 'expo' | 'native';
dest: string;
slug: string;
projectName: string;
arch: 'new' | 'mixed' | 'legacy';
reactNativeVersion?: string;
Expand Down Expand Up @@ -93,6 +95,8 @@ export default async function generateExampleApp({
await fs.readFile(path.join(directory, 'package.json'), 'utf8')
);

pkg.name = `${slug}-example`;

// Remove Jest config for now
delete pkg.jest;

Expand All @@ -101,8 +105,14 @@ export default async function generateExampleApp({
delete scripts.test;
delete scripts.lint;

const SCRIPTS_TO_ADD = {
'build:android':
'cd android && ./gradlew assembleDebug --no-daemon --console=plain -PreactNativeArchitectures=arm64-v8a',
'build:ios': `cd ios && xcodebuild -workspace ${projectName}Example.xcworkspace -scheme ${projectName}Example -configuration Debug -sdk iphonesimulator CC=clang CPLUSPLUS=clang++ LD=clang LDPLUSPLUS=clang++ GCC_OPTIMIZATION_LEVEL=0 GCC_PRECOMPILE_PREFIX_HEADER=YES ASSETCATALOG_COMPILER_OPTIMIZATION=time DEBUG_INFORMATION_FORMAT=dwarf COMPILER_INDEX_STORE_ENABLE=NO`,
};

if (type === 'native') {
scripts.pods = 'pod-install --quiet';
Object.assign(scripts, SCRIPTS_TO_ADD);
}

PACKAGES_TO_REMOVE.forEach((name) => {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -15,14 +15,13 @@ runs:
with:
path: |
**/node_modules
.yarn/install-state.gz
key: ${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}-${{ hashFiles('**/package.json') }}
restore-keys: |
${{ runner.os }}-yarn-${{ hashFiles('**/yarn.lock') }}
${{ runner.os }}-yarn-
- name: Install dependencies
if: steps.yarn-cache.outputs.cache-hit != 'true'
run: |
yarn install --cwd example --frozen-lockfile
yarn install --frozen-lockfile
run: yarn install --immutable
shell: bash
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ jobs:
- name: Check turborepo cache for Android
run: |
TURBO_CACHE_STATUS=$(node -p "($(yarn --silent turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:android').cache.status")
TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:android --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:android').cache.status")
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
Expand Down Expand Up @@ -123,7 +123,7 @@ jobs:
- name: Check turborepo cache for iOS
run: |
TURBO_CACHE_STATUS=$(node -p "($(yarn --silent turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status")
TURBO_CACHE_STATUS=$(node -p "($(yarn turbo run build:ios --cache-dir="${{ env.TURBO_CACHE_DIR }}" --dry=json)).tasks.find(t => t.task === 'build:ios').cache.status")
if [[ $TURBO_CACHE_STATUS == "HIT" ]]; then
echo "turbo_cache_hit=1" >> $GITHUB_ENV
Expand All @@ -143,7 +143,7 @@ jobs:
- name: Install cocoapods
if: env.turbo_cache_hit != 1 && steps.cocoapods-cache.outputs.cache-hit != 'true'
run: |
yarn example pods
yarn pod-install example/ios
env:
NO_FLIPPER: 1

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,14 @@ buck-out/
android/app/libs
android/keystores/debug.keystore

# Yarn
.yarn/*
!.yarn/patches
!.yarn/plugins
!.yarn/releases
!.yarn/sdks
!.yarn/versions

# Expo
.expo/

Expand Down
Loading

0 comments on commit f90ce89

Please sign in to comment.