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 than yarn compared to handling transitive dependencies.

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

Eradicate duplicate dependencies.

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

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
  • Global: add it inside the readPackage function of the .pnpmfile.cjs file to force-remove its peer dependencies.

Windows only: issues when running npm scripts.

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

Why: Running a binary by specifying its path in an npm 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 from an npm script 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 nodejs shims instead of rn-nodeify

Why: Because nodeify updates package.json recursively by adding browser and react-native keys and this mutates the pnpm store.

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 watching symlinks.

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

Solution: @rnx-kit/metro-config provides a default config which watches every relevant folders instead of just watching the nested llm node_modules.

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