Skip to content

Issues, Workarounds and Tricks

Julien Elbaz edited this page Feb 16, 2022 · 14 revisions

A non-exhaustive list of things we had to do in order to make the monorepo work.

Non specific

A lot of packages are not declaring their dependencies properly

Why: pnpm is stricter compared to yarn when handling transitive dependencies.

Solution: Add them as dependencies or devDependencies in the related package.json file.

Eradicate duplicate dependencies

Why: pnpm hoists dependencies in a workspace context and can duplicate them for instance if they have different peer dependencies versions.

Solution:

  • LLM: force metro to resolve a dependency from the LLM node_modules by adding it to the FORCED_DEPENDENCIES array in the metro.config.js file.
  • LLD: force webpack to resolve a dependency from the LLD node_modules by adding a special alias in the webpack config file.
  • Global: add the dependency inside the readPackage function of the .pnpmfile.cjs file to force-remove its peer dependencies.

Windows only: issues when running binaries from package.json scripts

'XXX' is not recognized as an internal or external command

Why: Running a binary by specifying its path in a script will not work on Windows. It is needed to prepend the command with a call to node.exe.

Solution: Use the x-ref homemade package to run binaries in a cross-platform compatible way.

Eradicate yarn.lock files

Why: We use pnpm now and some tooling we use (namely turborepo) crawls all the folders and searches for yarn lockfiles to determine which package manager to use.

Solution: Delete each and every yarn lockfile.

LLM

Use node-libs-react-native node.js shims instead of rn-nodeify

Why: Because nodeify updates package.json files recursively by adding browser and react-native keys and this mutates packages stored inside the pnpm store and interferes with packages consumed by other modules in the monorepo (like LLD).

Solution: Use node-libs-react-native which means adding some requires in the metro.config.js file and an import in the entry file.

Watchman has issues with symlinks

Why: See https://github.com/facebook/watchman/issues/105

Solution: @rnx-kit/metro-config provides a default config which watches every relevant workspace folders instead of just watching a single node_modules directory from LLM.

The metro bundler cannot resolve symlinks properly

Why: See https://github.com/facebook/metro/issues/1

Solution: Use @rnx-kit/metro-resolver-symlinks as a main resolver in the metro.config.js file.

@rnx-kit/metro-resolver-symlinks has issues with packages that do not export package.json

Why: The symlink resolver uses the node.js resolver under the hood and tries to resolve the location of the package.json file for each module. For packages that use subpath exports it will not work if they do not provide a path for the package.json file as subpath exports are exclusive. See https://nodejs.org/api/packages.html#subpath-exports

Solution: Add a fallback resolver in the metro.config.js file.

Expo autolinking fails to locate dependencies

Why: Expo uses a custom algorithm to crawl dependencies and link them if they include compatible files. But it will fail for most deps because of the pnpm workspace node modules structure and symlinks.

Solution: Add custom NODE_PATH environment variables pointing to relevant directories. This is added in the Podfile for ios builds and in the Fastfile for android builds.

Unable to locate and require ruby scripts from the Podfile

Why: we require ruby scripts from dependencies based on their node_modules location and with pnpm it could be tricky to hardcode it.

Solution: run a small node script to resolve the location from ruby.

Wrong RCTBridgeModule import

Why: RNAnalytics redefined this header symbols for an unknown reason…

Solution: Patch on postinstall the RNAnalytics.h file to force importing the right header <React/RCTBridgeModule.h>.

LLD

Use npm to rebuild deps instead of pnpm

Why: pnpm will not rebuild dependencies properly and there will be a mismatch between the local nodejs version and the electron one.

Specific package installs when bundling the app

Why: Electron bundler crawls production dependencies and packs them inside an .asar file inside the binary. With the standard pnpm install with symbolic links and hoisting it will fail to copy the packages properly.

Solution: Use the --package-import-method=copy and --node-linker=hoisted flags when bundling the app.

Github action: install all dependencies insteads of a subset

In the build_app.yml github action workflow, using pnpm i --filter="live-desktop..." --no-frozen-lockfile --unsafe-perm to install only the smallest subset of depencencies results in an error while trying to build the app later on.

ERROR  Cannot read property 'name' of undefined

Workaround: Use pnpm i while pnpm fixes this.

Clone this wiki locally