react-native-monorepo-config 0.1.2 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (3) hide show
  1. package/README.md +2 -1
  2. package/index.js +32 -13
  3. package/package.json +1 -1
package/README.md CHANGED
@@ -30,6 +30,7 @@ Here, `my-app` is a React Native app, and `a` and `b` are libraries that are use
30
30
  To configure Metro for `my-app`, you can create a `metro.config.js` file in the `my-app` directory with the following content:
31
31
 
32
32
  ```js
33
+ const path = require('path');
33
34
  const { getDefaultConfig } = require('@react-native/metro-config'); // Import from `@expo/metro-config` if using Expo CLI
34
35
  const { withMetroConfig } = require('react-native-monorepo-config');
35
36
 
@@ -70,7 +71,7 @@ module.exports = {
70
71
 
71
72
  This configuration will setup a few things:
72
73
 
73
- - Configure Metro to watch for changes in other packages in the monorepo instead of just the current package. This may slow down the bundling process, in large monorepos. In that case, you can override `watchFolders` to add specific folders to watch instead.
74
+ - Configure Metro to watch for changes in other packages in the monorepo instead of only the current package. This may slow down the bundling process in large monorepos. In that case, you can override `watchFolders` to add specific folders to watch instead.
74
75
  - Block packages defined in `peerDependencies` of other packages in the monorepo to avoid duplicate versions from being loaded. Loading duplicate versions of some packages such as `react` can cause issues. Make sure to specify `peerDependencies` for your packages appropriately.
75
76
  - If the packages defined in `peerDependencies` have been hoisted to the monorepo root, point Metro to them so they can be found.
76
77
  - Configure Metro's resolve to prioritize `package.json#source` or the `source` condition in `package.json#exports` so that the app can import source code directly from other packages in the monorepo. To utilize this, make sure to add `"source": "src/index.ts"` or `"exports": { ".": { "source": "./src/index.ts" } }` to the `package.json` of the packages you want to import from.
package/index.js CHANGED
@@ -23,8 +23,14 @@ export function withMetroConfig(baseConfig, { root, dirname }) {
23
23
  );
24
24
  }
25
25
 
26
+ if (!Array.isArray(pkg.workspaces)) {
27
+ throw new Error(
28
+ `The 'workspaces' field in the 'package.json' at '${root}' must be an array.`
29
+ );
30
+ }
31
+
26
32
  // Get the list of monorepo packages except current package
27
- const packages = (pkg.workspaces.packages || pkg.workspaces)
33
+ const packages = pkg.workspaces
28
34
  .flatMap((pattern) =>
29
35
  glob.sync(pattern, {
30
36
  cwd: root,
@@ -32,23 +38,28 @@ export function withMetroConfig(baseConfig, { root, dirname }) {
32
38
  ignore: [`**/node_modules`, `**/.git`, `**/.yarn`],
33
39
  })
34
40
  )
35
- .filter((p) => {
36
- const dir = path.join(root, p);
37
-
38
- // Ignore current package
41
+ .map((p) => path.join(root, p))
42
+ .filter((dir) => {
43
+ // Exclude current package
39
44
  if (path.relative(dir, dirname) === '') {
40
45
  return false;
41
46
  }
42
47
 
43
- // Ignore packages that don't have a package.json
48
+ // Ignore folders that don't have a package.json
44
49
  return fs.existsSync(path.join(dir, 'package.json'));
45
50
  });
46
51
 
52
+ // If monorepo root contains a name, add it to the list of packages
53
+ // Necessary if the root is a package itself
54
+ if (pkg.name) {
55
+ packages.push(root);
56
+ }
57
+
47
58
  // Get the list of peer dependencies for all packages in the monorepo
48
59
  const peers = packages
49
- .flatMap((it) => {
60
+ .flatMap((dir) => {
50
61
  const pak = JSON.parse(
51
- fs.readFileSync(path.join(root, it, 'package.json'), 'utf8')
62
+ fs.readFileSync(path.join(dir, 'package.json'), 'utf8')
52
63
  );
53
64
 
54
65
  return pak.peerDependencies ? Object.keys(pak.peerDependencies) : [];
@@ -63,18 +74,26 @@ export function withMetroConfig(baseConfig, { root, dirname }) {
63
74
  const blockList = new RegExp(
64
75
  '(' +
65
76
  packages
66
- .flatMap((it) =>
67
- peers.map((m) => `^${escape(path.join(it, 'node_modules', m))}\\/.*$`)
77
+ .flatMap((dir) =>
78
+ peers.map(
79
+ (m) => `^${escape(path.join(dir, 'node_modules', m))}\\/.*$`
80
+ )
68
81
  )
69
82
  .join('|') +
70
83
  ')$'
71
84
  );
72
85
 
73
- // When we import a package from the monorepo, metro won't be able to find their deps if they are hoisted
86
+ // When we import a package from the monorepo, metro may not be able to find the deps in blockList
74
87
  // We need to specify them in `extraNodeModules` to tell metro where to find them
75
88
  const extraNodeModules = peers.reduce((acc, name) => {
76
- if (fs.existsSync(path.join(root, 'node_modules', name))) {
77
- acc[name] = path.join(root, 'node_modules', name);
89
+ // First, try to find the package in the current package's node_modules
90
+ // As a fallback, try to find it in the monorepo root
91
+ const dir = [dirname, root]
92
+ .map((d) => path.join(d, 'node_modules', name))
93
+ .find((d) => fs.existsSync(d));
94
+
95
+ if (dir) {
96
+ acc[name] = dir;
78
97
  }
79
98
 
80
99
  return acc;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "react-native-monorepo-config",
3
- "version": "0.1.2",
3
+ "version": "0.1.4",
4
4
  "description": "Configure Metro for a React Native app in a monorepo",
5
5
  "repository": "https://github.com/satya164/react-native-monorepo-config",
6
6
  "author": "Satyajit Sahoo <satyajit.happy@gmail.com> (https://github.com/satya164/)",