-
-
Save huntie/85ea491763b444bfa1bdc8e997fc2765 to your computer and use it in GitHub Desktop.
/** | |
* Metro Bundler configuration | |
* https://facebook.github.io/metro/docs/en/configuration | |
* | |
* eslint-env node, es6 | |
*/ | |
const exclusionList = require('metro-config/src/defaults/exclusionList'); | |
const getWorkspaces = require('get-yarn-workspaces'); | |
const path = require('path'); | |
function getConfig(appDir, options = {}) { | |
const workspaces = getWorkspaces(appDir); | |
// Add additional Yarn workspace package roots to the module map | |
// https://bit.ly/2LHHTP0 | |
const watchFolders = [ | |
path.resolve(appDir, '..', 'node_modules'), | |
...workspaces.filter( | |
workspaceDir => !(workspaceDir === appDir), | |
), | |
]; | |
return { | |
watchFolders, | |
resolver: { | |
blockList: exclusionList([ | |
// Ignore other resolved react-native installations outside of | |
// myapp-native - this prevents a module naming collision when mapped. | |
/^((?!myapp-native).)+[\/\\]node_modules[/\\]react-native[/\\].*/, | |
// Ignore react-native-svg dependency in myapp-ui, mapped below. | |
// react-native-svg must only be included once due to a side-effect. It | |
// has not been hoisted as it requires native module linking here. | |
// http://bit.ly/2LJ7V4b | |
/myapp-ui[\/\\]node_modules[/\\]react-native-svg[/\\].*/, | |
]), | |
extraNodeModules: { | |
// Resolve all react-native module imports to the locally-installed version | |
'react-native': path.resolve(appDir, 'node_modules', 'react-native'), | |
// Resolve additional nohoist modules depended on by other packages | |
'react-native-svg': path.resolve( | |
appDir, | |
'node_modules', | |
'react-native-svg', | |
), | |
// Resolve core-js imports to the locally installed version | |
'core-js': path.resolve(appDir, 'node_modules', 'core-js'), | |
}, | |
}, | |
}; | |
} | |
module.exports = getConfig(__dirname); |
{ | |
"name": "myapp-native", | |
"version": "1.0.0", | |
"private": true, | |
"scripts": { | |
"postinstall": "jetify", | |
"start": "react-native start", | |
"android": "react-native run-android", | |
"ios": "react-native run-ios", | |
"pods": "cd ios; pod install" | |
}, | |
"workspaces": { | |
"nohoist": [ | |
"@react-native-community/async-storage", | |
"react-native", | |
"react-native/**", | |
"react-native-dev-menu", | |
"react-native-svg", | |
"jetifier" | |
] | |
}, | |
"dependencies": { | |
"@react-native-community/async-storage": "^1.6.1", | |
"myapp-settings": "1.0.0", | |
"myapp-ui": "1.0.0", | |
"react": "16.9.0", | |
"react-native": "0.61.5", | |
"react-native-dev-menu": "^4.0.0", | |
"react-native-svg": "^9.12.0" | |
}, | |
"devDependencies": { | |
"get-yarn-workspaces": "^1.0.2", | |
"metro-config": "^0.56.0" | |
} | |
} |
Is there a reason not to use a glob which includes additional react native packages? i.e something like:
// ...
"nohoist": [
"react-native",
"react-native/**",
"react-native-*",
"react-native-*/**",
"@react-native-*",
"@react-native-*/**"
]
@huntie I'm trying to wrap my head around the blacklistRE patterns (due to the react-native-svg issue). Are they paths relative to the project root? Could you list the folder structure (and package names) for the project that these patterns would work for? My project structure looks like this:
apps/
app-one/
package.json
app-two/
package.json
libs/
icons/
package.json
package.json
And I'm trying to figure out how to ignore a package from /libs/icons
@AdamGerthel Yes, blacklistRE
entries are relative to the project root.
- Line 30 matches any
react-native
installation that is not the one undermyapp-native/
(the app workspace). Instances ofreact-native
from other workspaces are therefore excluded. - Line 36 matches a specific
react-native-svg
installation in another package, in this examplemyapp-ui/
. Therefore this instance is excluded and the version ofreact-native-svg
that exists inmyapp-native/
is used.
(Line 36 could also have used the negative lookahead approach in line 30.)
Basically, both of these entries create a mapping where there is only one choice of which version of a dependency to bundle - in each case the one local to the app workspace.
Hope that helps 😄
@huntie ok, so that's good because that means that I've understood it correctly :) The thing I'm not entirely getting is the structure of the regex and how to apply it in my project.
Line 30 works in my project, but line 36 doesn't. I'm still getting the Invariant Violation: Tried to register two views with the same name RNSVGSvgView
error, meaning that I'm probably getting the regex for my folder structure wrong since it's apparently importing react-native-svg twice. So, for clarity, what would the equivalent of /myapp-ui[\/\\]node_modules[/\\]react-native-svg[/\\].*/
be in the folder structure example I listed in my previous comment? I would assume that this would work:
/libs[\/\\]icons[\/\\]node_modules[/\\]react-native-svg[/\\].*/
But I haven't be able to get working. I feel like I've tried every regex I can think of but nothing seems to exclude it. I've even tried absolute paths. I'm also not sure how (if) I can debug it other than: Reset metro cache, rebuild and hope for the best :D
Any ideas? The name of the package is not the same as the name of the folder, but that shouldn't matter since it's asking for a path, right?
@AdamGerthel That regex looks right to me - another thing you might want to check is whether there is a react-native-svg
conflict between app-one/
and app-two/
(your versions), plus whether there is a duplicate react-native-svg
installation within dependencies app-one/
.
Hopefully you can find from the debug output from what workspace the invariant violation is triggered.
This needs updating for the new metro-config/src/defaults/exclusionList
module and the blocklist
property in Metro's config.
Thanks for pointing this out @steveluscher, now updated. Funnily enough I now work on Metro 😄
Thanks so much for this article and Gist, Alex! Helped a lot! First result for me with "React Native Workspaces"!