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.
- package/README.md +2 -1
- package/index.js +32 -13
- 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
|
|
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 =
|
|
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
|
-
.
|
|
36
|
-
|
|
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
|
|
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((
|
|
60
|
+
.flatMap((dir) => {
|
|
50
61
|
const pak = JSON.parse(
|
|
51
|
-
fs.readFileSync(path.join(
|
|
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((
|
|
67
|
-
peers.map(
|
|
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
|
|
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
|
-
|
|
77
|
-
|
|
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.
|
|
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/)",
|