Skip to content

Commit d997097

Browse files
fix(samples): Share monorepo config, remove broken promises resolve, add react to blocked packages (#4494)
1 parent 40c35c5 commit d997097

File tree

13 files changed

+113
-189
lines changed

13 files changed

+113
-189
lines changed

dev-packages/utils/index.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
module.exports = {};

dev-packages/utils/metro.js

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
const path = require('path');
2+
const exclusionList = require('metro-config/src/defaults/exclusionList');
3+
4+
/**
5+
* Packages used by the sample apps
6+
*/
7+
const getMonorepoPackages = monorepoRoot => {
8+
return {
9+
'@sentry/react-native': path.resolve(monorepoRoot, 'packages/core'),
10+
};
11+
};
12+
13+
/**
14+
* Block given packages present in the monorepo packages to avoid conflicts with the sample apps
15+
*/
16+
const getBlockList = (monorepoPackages, excludedPackages) => {
17+
return Object.values(monorepoPackages)
18+
.map(p => excludedPackages.map(e => new RegExp(`${p}/node_modules/${e}/.*`)))
19+
.flat();
20+
};
21+
22+
const withMonorepo = config => {
23+
const projectRoot = config.projectRoot;
24+
if (!projectRoot) {
25+
throw new Error('projectRoot is required');
26+
}
27+
28+
const monorepoRoot = path.resolve(projectRoot, '../..');
29+
const monorepoPackages = getMonorepoPackages(monorepoRoot);
30+
31+
config.resolver = config.resolver || {};
32+
33+
const blockList = [
34+
...((Array.isArray(config.resolver.blockList) && config.resolver.blockList) ||
35+
(!!config.resolver.blockList && [config.resolver.blockList]) ||
36+
[]),
37+
...getBlockList(monorepoPackages, ['react-native', 'react']),
38+
new RegExp('.*\\android\\.*'), // Required for Windows in order to run the Sample.
39+
];
40+
config.resolver.blockList = exclusionList(blockList);
41+
42+
config.watchFolders = [...(config.watchFolders || []), projectRoot, ...Object.values(monorepoPackages)];
43+
44+
config.resolver.extraNodeModules = {
45+
...config.resolver.extraNodeModules,
46+
...monorepoPackages,
47+
'react-native': path.resolve(projectRoot, 'node_modules/react-native'),
48+
react: path.resolve(projectRoot, 'node_modules/react'),
49+
};
50+
51+
config.resolver.nodeModulesPaths = [
52+
...(config.resolver.nodeModulesPaths || []),
53+
path.resolve(projectRoot, 'node_modules'),
54+
...Object.values(monorepoPackages).map(p => path.resolve(p, 'node_modules')),
55+
];
56+
57+
return config;
58+
};
59+
60+
module.exports = {
61+
withMonorepo,
62+
};

dev-packages/utils/package.json

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
{
2+
"name": "sentry-react-native-samples-utils",
3+
"version": "0.0.1",
4+
"description": "Internal Samples Utils",
5+
"main": "index.js",
6+
"license": "MIT",
7+
"private": true,
8+
"dependencies": {
9+
"metro-config": "^0.81.0"
10+
}
11+
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
"packages/core",
4646
"dev-packages/e2e-tests",
4747
"dev-packages/type-check",
48+
"dev-packages/utils",
4849
"samples/react-native",
4950
"samples/react-native-macos",
5051
"samples/expo",
Lines changed: 3 additions & 34 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,12 @@
1-
const path = require('path');
2-
const exclusionList = require('metro-config/src/defaults/exclusionList');
3-
4-
const projectRoot = __dirname;
5-
const monorepoRoot = path.resolve(projectRoot, '../..');
6-
7-
// Only list the packages within your monorepo that your app uses. No need to add anything else.
8-
// If your monorepo tooling can give you the list of monorepo workspaces linked
9-
// in your app workspace, you can automate this list instead of hardcoding them.
10-
const monorepoPackages = {
11-
'@sentry/react-native': path.resolve(monorepoRoot, 'packages/core'),
12-
};
1+
const { withMonorepo } = require('sentry-react-native-samples-utils/metro');
132

143
/**
154
* Metro configuration for React Native
165
* https://github.com/facebook/react-native
176
*
187
* @format
198
*/
20-
module.exports = {
9+
module.exports = withMonorepo({
2110
transformer: {
2211
getTransformOptions: async () => ({
2312
transform: {
@@ -27,24 +16,4 @@ module.exports = {
2716
}),
2817
},
2918
projectRoot: __dirname,
30-
// 1. Watch the local app directory, and only the shared packages (limiting the scope and speeding it up)
31-
// Note how we change this from `monorepoRoot` to `projectRoot`. This is part of the optimization!
32-
watchFolders: [projectRoot, ...Object.values(monorepoPackages)],
33-
resolver: {
34-
blockList: exclusionList([
35-
...Object.values(monorepoPackages).map(p => new RegExp(`${p}/node_modules/react-native/.*`)),
36-
]),
37-
// Add the monorepo workspaces as `extraNodeModules` to Metro.
38-
// If your monorepo tooling creates workspace symlinks in the `node_modules` directory,
39-
// you can either add symlink support to Metro or set the `extraNodeModules` to avoid the symlinks.
40-
// See: https://metrobundler.dev/docs/configuration/#extranodemodules
41-
extraNodeModules: {
42-
...monorepoPackages,
43-
'react-native': path.resolve(projectRoot, 'node_modules/react-native'),
44-
},
45-
nodeModulesPaths: [
46-
path.resolve(projectRoot, 'node_modules'),
47-
...Object.values(monorepoPackages).map(p => path.resolve(p, 'node_modules')),
48-
],
49-
},
50-
};
19+
});

performance-tests/TestAppSentry/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@
1515
"devDependencies": {
1616
"@babel/core": "^7.12.9",
1717
"@babel/runtime": "^7.12.5",
18-
"metro-react-native-babel-preset": "^0.72.3"
18+
"metro-react-native-babel-preset": "^0.72.3",
19+
"sentry-react-native-samples-utils": "workspace:^"
1920
},
2021
"jest": {
2122
"preset": "react-native"

samples/expo/metro.config.js

Lines changed: 3 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
// Learn more https://docs.expo.io/guides/customizing-metro
22
const { getDefaultConfig } = require('@expo/metro-config');
3-
const path = require('path');
4-
53
const { getSentryExpoConfig } = require('@sentry/react-native/metro');
64

5+
const { withMonorepo } = require('sentry-react-native-samples-utils/metro');
6+
77
/** @type {import('expo/metro-config').MetroConfig} */
88
const config = getSentryExpoConfig(__dirname, {
99
// [Web-only]: Enables CSS support in Metro.
@@ -12,40 +12,4 @@ const config = getSentryExpoConfig(__dirname, {
1212
annotateReactComponents: true,
1313
});
1414

15-
const projectRoot = __dirname;
16-
const monorepoRoot = path.resolve(projectRoot, '../..');
17-
18-
// Only list the packages within your monorepo that your app uses. No need to add anything else.
19-
// If your monorepo tooling can give you the list of monorepo workspaces linked
20-
// in your app workspace, you can automate this list instead of hardcoding them.
21-
const monorepoPackages = {
22-
'@sentry/react-native': path.resolve(monorepoRoot, 'packages/core'),
23-
};
24-
25-
const exclusionList = [...Object.values(monorepoPackages).map(p => new RegExp(`${p}/node_modules/react-native/.*`))];
26-
27-
if (config.resolver.blacklistRE) {
28-
config.resolver.blacklistRE.push(...exclusionList);
29-
} else {
30-
config.resolver.blacklistRE = exclusionList;
31-
}
32-
33-
// 1. Watch the local app directory, and only the shared packages (limiting the scope and speeding it up)
34-
// Note how we change this from `monorepoRoot` to `projectRoot`. This is part of the optimization!
35-
config.watchFolders = [projectRoot, ...Object.values(monorepoPackages)];
36-
37-
// Add the monorepo workspaces as `extraNodeModules` to Metro.
38-
// If your monorepo tooling creates workspace symlinks in the `node_modules` directory,
39-
// you can either add symlink support to Metro or set the `extraNodeModules` to avoid the symlinks.
40-
// See: https://metrobundler.dev/docs/configuration/#extranodemodules
41-
config.resolver.extraNodeModules = {
42-
...monorepoPackages,
43-
'react-native': path.resolve(projectRoot, 'node_modules/react-native'),
44-
};
45-
46-
config.resolver.nodeModulesPaths = [
47-
path.resolve(projectRoot, 'node_modules'),
48-
...Object.values(monorepoPackages).map(p => path.resolve(p, 'node_modules')),
49-
];
50-
51-
module.exports = config;
15+
module.exports = withMonorepo(config);

samples/expo/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,8 @@
3737
"@babel/core": "^7.26.0",
3838
"@babel/preset-env": "^7.26.0",
3939
"@sentry/babel-plugin-component-annotate": "^2.18.0",
40-
"@types/node": "20.10.4"
40+
"@types/node": "20.10.4",
41+
"sentry-react-native-samples-utils": "workspace:^"
4142
},
4243
"overrides": {
4344
"react-refresh": "~0.14.0"
Lines changed: 7 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,20 @@
1-
const path = require('path');
21
const { withSentryConfig } = require('@sentry/react-native/metro');
32
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
4-
const exclusionList = require('metro-config/src/defaults/exclusionList');
53

6-
const projectRoot = __dirname;
7-
const monorepoRoot = path.resolve(projectRoot, '../..');
8-
9-
// Only list the packages within your monorepo that your app uses. No need to add anything else.
10-
// If your monorepo tooling can give you the list of monorepo workspaces linked
11-
// in your app workspace, you can automate this list instead of hardcoding them.
12-
const monorepoPackages = {
13-
'@sentry/react-native': path.resolve(monorepoRoot, 'packages/core'),
14-
};
4+
const { withMonorepo } = require('sentry-react-native-samples-utils/metro');
155

166
/**
177
* Metro configuration
188
* https://facebook.github.io/metro/docs/configuration
199
*
2010
* @type {import('metro-config').MetroConfig}
2111
*/
22-
const config = {
23-
projectRoot: __dirname,
24-
// 1. Watch the local app directory, and only the shared packages (limiting the scope and speeding it up)
25-
// Note how we change this from `monorepoRoot` to `projectRoot`. This is part of the optimization!
26-
watchFolders: [projectRoot, ...Object.values(monorepoPackages)],
27-
resolver: {
28-
resolverMainFields: ['react-native', 'main'],
29-
resolveRequest: (context, moduleName, platform) => {
30-
if (moduleName.includes('promise/')) {
31-
return context.resolveRequest(
32-
{
33-
...context,
34-
// Ensures the promise module is resolved from the sample's node_modules.
35-
allowHaste: false,
36-
disableHierarchicalLookup: true,
37-
},
38-
moduleName,
39-
platform,
40-
);
41-
}
42-
return context.resolveRequest(context, moduleName, platform);
43-
},
44-
blockList: exclusionList([
45-
new RegExp('.*\\android\\.*'), // Required for Windows in order to run the Sample.
46-
...Object.values(monorepoPackages).map(
47-
p => new RegExp(`${p}/node_modules/react-native/.*`),
48-
),
49-
]),
50-
// Add the monorepo workspaces as `extraNodeModules` to Metro.
51-
// If your monorepo tooling creates workspace symlinks in the `node_modules` directory,
52-
// you can either add symlink support to Metro or set the `extraNodeModules` to avoid the symlinks.
53-
// See: https://metrobundler.dev/docs/configuration/#extranodemodules
54-
extraNodeModules: {
55-
...monorepoPackages,
56-
'react-native': path.resolve(projectRoot, 'node_modules/react-native'),
57-
},
58-
nodeModulesPaths: [
59-
path.resolve(projectRoot, 'node_modules'),
60-
...Object.values(monorepoPackages).map(p =>
61-
path.resolve(p, 'node_modules'),
62-
),
63-
],
64-
},
65-
};
12+
const config = {};
13+
14+
const mergedConfig = mergeConfig(getDefaultConfig(__dirname), config);
6615

67-
const m = mergeConfig(getDefaultConfig(__dirname), config);
68-
module.exports = withSentryConfig(m, {
16+
const sentryConfig = withSentryConfig(mergedConfig, {
6917
annotateReactComponents: true,
7018
});
19+
20+
module.exports = withMonorepo(sentryConfig);

samples/react-native-macos/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,7 @@
4949
"eslint": "^8.19.0",
5050
"jest": "^29.6.3",
5151
"prettier": "2.8.8",
52+
"sentry-react-native-samples-utils": "workspace:^",
5253
"typescript": "5.0.4"
5354
},
5455
"engines": {

samples/react-native/metro.config.js

Lines changed: 7 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -1,70 +1,20 @@
1-
const path = require('path');
21
const { withSentryConfig } = require('@sentry/react-native/metro');
32
const { getDefaultConfig, mergeConfig } = require('@react-native/metro-config');
4-
const exclusionList = require('metro-config/src/defaults/exclusionList');
53

6-
const projectRoot = __dirname;
7-
const monorepoRoot = path.resolve(projectRoot, '../..');
8-
9-
// Only list the packages within your monorepo that your app uses. No need to add anything else.
10-
// If your monorepo tooling can give you the list of monorepo workspaces linked
11-
// in your app workspace, you can automate this list instead of hardcoding them.
12-
const monorepoPackages = {
13-
'@sentry/react-native': path.resolve(monorepoRoot, 'packages/core'),
14-
};
4+
const { withMonorepo } = require('sentry-react-native-samples-utils/metro');
155

166
/**
177
* Metro configuration
188
* https://reactnative.dev/docs/metro
199
*
2010
* @type {import('metro-config').MetroConfig}
2111
*/
22-
const config = {
23-
projectRoot: __dirname,
24-
// 1. Watch the local app directory, and only the shared packages (limiting the scope and speeding it up)
25-
// Note how we change this from `monorepoRoot` to `projectRoot`. This is part of the optimization!
26-
watchFolders: [projectRoot, ...Object.values(monorepoPackages)],
27-
resolver: {
28-
resolverMainFields: ['react-native', 'main'],
29-
resolveRequest: (context, moduleName, platform) => {
30-
if (moduleName.includes('promise/')) {
31-
return context.resolveRequest(
32-
{
33-
...context,
34-
// Ensures the promise module is resolved from the sample's node_modules.
35-
allowHaste: false,
36-
disableHierarchicalLookup: true,
37-
},
38-
moduleName,
39-
platform,
40-
);
41-
}
42-
return context.resolveRequest(context, moduleName, platform);
43-
},
44-
blockList: exclusionList([
45-
new RegExp('.*\\android\\.*'), // Required for Windows in order to run the Sample.
46-
...Object.values(monorepoPackages).map(
47-
p => new RegExp(`${p}/node_modules/react-native/.*`),
48-
),
49-
]),
50-
// Add the monorepo workspaces as `extraNodeModules` to Metro.
51-
// If your monorepo tooling creates workspace symlinks in the `node_modules` directory,
52-
// you can either add symlink support to Metro or set the `extraNodeModules` to avoid the symlinks.
53-
// See: https://metrobundler.dev/docs/configuration/#extranodemodules
54-
extraNodeModules: {
55-
...monorepoPackages,
56-
'react-native': path.resolve(projectRoot, 'node_modules/react-native'),
57-
},
58-
nodeModulesPaths: [
59-
path.resolve(projectRoot, 'node_modules'),
60-
...Object.values(monorepoPackages).map(p =>
61-
path.resolve(p, 'node_modules'),
62-
),
63-
],
64-
},
65-
};
12+
const config = {};
13+
14+
const mergedConfig = mergeConfig(getDefaultConfig(__dirname), config);
6615

67-
const m = mergeConfig(getDefaultConfig(__dirname), config);
68-
module.exports = withSentryConfig(m, {
16+
const sentryConfig = withSentryConfig(mergedConfig, {
6917
annotateReactComponents: true,
7018
});
19+
20+
module.exports = withMonorepo(sentryConfig);

samples/react-native/package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,7 @@
6363
"patch-package": "^8.0.0",
6464
"prettier": "2.8.8",
6565
"react-test-renderer": "18.3.1",
66+
"sentry-react-native-samples-utils": "workspace:^",
6667
"typescript": "5.0.4"
6768
},
6869
"engines": {

0 commit comments

Comments
 (0)