Skip to content

Commit faef38d

Browse files
committed
Update metro-issues.mdx
1 parent 6caeca7 commit faef38d

1 file changed

Lines changed: 127 additions & 102 deletions

File tree

docs/troubleshooting/metro-issues.mdx

Lines changed: 127 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -8,53 +8,64 @@ description: "Bundler Polyfill Issues - React Native Metro | Documentation - Web
88
import TabItem from "@theme/TabItem";
99
import Tabs from "@theme/Tabs";
1010

11-
While setting up a new web3 project from scratch, you might face multiple issues with the bundler. This issue is caused because the core packages like
12-
`eccrypto` have certain dependencies, which are not present within the build environment. For rectifying this, the go-to method has been to just add
13-
the missing modules directly into the package, and edit the bundler configuration to take advantage of that.
14-
15-
Although this method works, it increases the bundle size significantly. Causing slow loading speeds and a bad user experience. It is important to note
16-
that these modules, even while the build fails, are still present within the browser environment. Many libraries like Web3Auth are written in a way to
17-
take advantage of this fact. Hence, even if the build doesn't contain the polyfill, the library should still work as expected. However, if you are
18-
using a library that does not take advantage of this fact, you might face issues while using the library.
19-
20-
Hence, you need to be mindful of the fact that you only require certain node polyfills to be added to your project, while testing each of its
21-
functionalities. At the same time, you need to tell the bundler to ignore the missing modules, and not include them in the build.
11+
While setting up a new web3 project from scratch, you might face multiple issues with the bundler.
12+
This issue is caused because the core packages like `eccrypto` have certain dependencies, which are
13+
not present within the build environment. For rectifying this, the go-to method has been to just add
14+
the missing modules directly into the package, and edit the bundler configuration to take advantage
15+
of that.
16+
17+
Although this method works, it increases the bundle size significantly. Causing slow loading speeds
18+
and a bad user experience. It is important to note that these modules, even while the build fails,
19+
are still present within the browser environment. Many libraries like Web3Auth are written in a way
20+
to take advantage of this fact. Hence, even if the build doesn't contain the polyfill, the library
21+
should still work as expected. However, if you are using a library that does not take advantage of
22+
this fact, you might face issues while using the library.
23+
24+
Hence, you need to be mindful of the fact that you only require certain node polyfills to be added
25+
to your project, while testing each of its functionalities. At the same time, you need to tell the
26+
bundler to ignore the missing modules, and not include them in the build.
2227

2328
In this guide, we have added instructions for adding the polyfills in React Native Metro.
2429

2530
## Install the missing modules
2631

27-
Check for the missing libraries in your build and included packages, and accordingly polyfill them. For Web3Auth, you need to polyfill the `buffer`,
28-
`process`, `crypto` and `stream` libraries. For the rest of the libraries, we are installing a dummy module called `empty-module` which helps us get
29-
rid of the warnings while building the project.
32+
Check for the missing libraries in your build and included packages, and accordingly polyfill them.
33+
For Web3Auth, you need to polyfill the `buffer`, `process`, `crypto` and `stream` libraries. For the
34+
rest of the libraries, we are installing a dummy module called `empty-module` which helps us get rid
35+
of the warnings while building the project.
3036

3137
```bash npm2yarn
3238
npm install --save empty-module readable-stream crypto-browserify react-native-get-random-values buffer process
3339
```
3440

3541
:::warning
3642

37-
There might be a possibility that you might need to polyfill more libraries, in case you're using any other blockchain library alongside Web3Auth that
38-
requires them. Generally, the libraries like `browserify-zlib`, `assert`, `stream-http`, `https-browserify`, `os-browserify`, `url` are the ones that
39-
might be required.
43+
There might be a possibility that you might need to polyfill more libraries, in case you're using
44+
any other blockchain library alongside Web3Auth that requires them. Generally, the libraries like
45+
`browserify-zlib`, `assert`, `stream-http`, `https-browserify`, `os-browserify`, `url` are the ones
46+
that might be required.
4047

4148
:::
4249

4350
## Update your `metro.config.js`
4451

45-
To make use of the polyfilled modules while building the application, you need to reconfigure your metro bundler config.
52+
To make use of the polyfilled modules while building the application, you need to reconfigure your
53+
metro bundler config.
4654

4755
:::info Expo Managed Workflow
4856

49-
You will have to create `metro.config.js` for Expo Managed Workflow, as it is not present by default. Also, note that polyfilling is not supported
50-
with "Expo Go" app. It is compatible only with Custom Dev Client and EAS builds.
57+
You will have to create `metro.config.js` for Expo Managed Workflow, as it is not present by
58+
default. Read through this documentation to learn more about
59+
[**Customizing Metro Bundler**](https://docs.expo.dev/guides/customizing-metro/).
5160

52-
Please run `npx expo prebuild` to generate native code based on the version of expo a project has installed, before moving forward.
61+
Note that polyfilling is not supported with "Expo Go" app. It is compatible only with Custom Dev
62+
Client and EAS builds. Please [**prebuild your expo app**](https://docs.expo.dev/workflow/prebuild/)
63+
to generate native code based on the version of expo a project has installed, before moving forward.
5364

5465
:::
5566

56-
You can copy the following code in your `metro.config.js` file. This will tell the bundler to ignore the missing modules and include the ones that are
57-
needed.
67+
You can copy the following code in your `metro.config.js` file. This will tell the bundler to ignore
68+
the missing modules and include the ones that are needed.
5869

5970
#### `metro.config.js`
6071

@@ -68,87 +79,62 @@ needed.
6879
<TabItem value="bare">
6980

7081
```tsx title="metro.config.js"
71-
const { getDefaultConfig } = require("metro-config");
72-
73-
module.exports = (async () => {
74-
const {
75-
resolver: { sourceExts, assetExts },
76-
} = await getDefaultConfig(__dirname);
77-
78-
const defaultSourceExts = [...sourceExts, "svg", "mjs", "cjs"];
79-
80-
return {
81-
resolver: {
82-
extraNodeModules: {
83-
assert: require.resolve("empty-module"), // assert can be polyfilled here if needed
84-
http: require.resolve("empty-module"), // stream-http can be polyfilled here if needed
85-
https: require.resolve("empty-module"), // https-browserify can be polyfilled here if needed
86-
os: require.resolve("empty-module"), // os-browserify can be polyfilled here if needed
87-
url: require.resolve("empty-module"), // url can be polyfilled here if needed
88-
zlib: require.resolve("empty-module"), // browserify-zlib can be polyfilled here if needed
89-
path: require.resolve("empty-module"),
90-
crypto: require.resolve("crypto-browserify"),
91-
stream: require.resolve("readable-stream"),
92-
},
93-
94-
assetExts: assetExts.filter((ext) => ext !== "svg"),
95-
96-
sourceExts: process.env.TEST_REACT_NATIVE ? ["e2e.js"].concat(defaultSourceExts) : defaultSourceExts,
97-
},
98-
transformer: {
99-
getTransformOptions: async () => ({
100-
transform: {
101-
experimentalImportSupport: false,
102-
inlineRequires: true,
103-
},
104-
}),
82+
const { getDefaultConfig, mergeConfig } = require("@react-native/metro-config");
83+
84+
const defaultConfig = getDefaultConfig(__dirname);
85+
86+
const config = {
87+
resolver: {
88+
extraNodeModules: {
89+
assert: require.resolve("empty-module"), // assert can be polyfilled here if needed
90+
http: require.resolve("empty-module"), // stream-http can be polyfilled here if needed
91+
https: require.resolve("empty-module"), // https-browserify can be polyfilled here if needed
92+
os: require.resolve("empty-module"), // os-browserify can be polyfilled here if needed
93+
url: require.resolve("empty-module"), // url can be polyfilled here if needed
94+
zlib: require.resolve("empty-module"), // browserify-zlib can be polyfilled here if needed
95+
path: require.resolve("empty-module"),
96+
crypto: require.resolve("crypto-browserify"),
97+
stream: require.resolve("readable-stream"),
10598
},
106-
};
107-
})();
99+
sourceExts: [...defaultConfig.resolver.sourceExts, "svg"],
100+
},
101+
};
102+
103+
module.exports = mergeConfig(defaultConfig, config);
108104
```
109105

110106
</TabItem>
111107

112108
<TabItem value="expo">
113109

114110
```tsx title="metro.config.js"
111+
// Learn more https://docs.expo.io/guides/customizing-metro
115112
const { getDefaultConfig } = require("expo/metro-config");
116113

117-
module.exports = (async () => {
118-
const {
119-
resolver: { sourceExts, assetExts },
120-
} = await getDefaultConfig(__dirname);
121-
122-
const defaultSourceExts = [...sourceExts, "svg", "mjs", "cjs"];
123-
124-
return {
125-
resolver: {
126-
extraNodeModules: {
127-
assert: require.resolve("empty-module"), // assert can be polyfilled here if needed
128-
http: require.resolve("empty-module"), // stream-http can be polyfilled here if needed
129-
https: require.resolve("empty-module"), // https-browserify can be polyfilled here if needed
130-
os: require.resolve("empty-module"), // os-browserify can be polyfilled here if needed
131-
url: require.resolve("empty-module"), // url can be polyfilled here if needed
132-
zlib: require.resolve("empty-module"), // browserify-zlib can be polyfilled here if needed
133-
path: require.resolve("empty-module"),
134-
crypto: require.resolve("crypto-browserify"),
135-
stream: require.resolve("readable-stream"),
136-
},
137-
138-
assetExts: assetExts.filter((ext) => ext !== "svg"),
139-
140-
sourceExts: process.env.TEST_REACT_NATIVE ? ["e2e.js"].concat(defaultSourceExts) : defaultSourceExts,
141-
},
142-
transformer: {
143-
getTransformOptions: async () => ({
144-
transform: {
145-
experimentalImportSupport: false,
146-
inlineRequires: true,
147-
},
148-
}),
149-
},
150-
};
151-
})();
114+
/** @type {import('expo/metro-config').MetroConfig} */
115+
const config = getDefaultConfig(__dirname);
116+
117+
config.resolver.extraNodeModules = {
118+
assert: require.resolve("empty-module"), // assert can be polyfilled here if needed
119+
http: require.resolve("empty-module"), // stream-http can be polyfilled here if needed
120+
https: require.resolve("empty-module"), // https-browserify can be polyfilled here if needed
121+
os: require.resolve("empty-module"), // os-browserify can be polyfilled here if needed
122+
url: require.resolve("empty-module"), // url can be polyfilled here if needed
123+
zlib: require.resolve("empty-module"), // browserify-zlib can be polyfilled here if needed
124+
path: require.resolve("empty-module"),
125+
crypto: require.resolve("crypto-browserify"),
126+
stream: require.resolve("readable-stream"),
127+
buffer: require.resolve("buffer"),
128+
};
129+
130+
config.transformer.getTransformOptions = () => ({
131+
transform: {
132+
experimentalImportSupport: false,
133+
inlineRequires: true,
134+
},
135+
});
136+
137+
module.exports = config;
152138
```
153139

154140
</TabItem>
@@ -178,11 +164,50 @@ module.exports = (async () => {
178164

179165
- Then, import the dependencies to `index.js` of your project.
180166

181-
```tsx title="index.js"
182-
import { AppRegistry } from "react-native";
183-
import "./globals";
184-
import "react-native-get-random-values";
185-
import App from "./App";
186-
import { name as appName } from "./app.json";
187-
AppRegistry.registerComponent(appName, () => App);
188-
```
167+
:::info
168+
169+
For Expo apps, you need to create an entry point, ie. the index.js file. This can be done by
170+
following the steps
171+
[**here**](https://docs.expo.dev/versions/latest/sdk/register-root-component/#what-if-i-want-to-name-my-main-app-file-something-other-than-appjs)
172+
173+
:::
174+
175+
<Tabs
176+
defaultValue="bare"
177+
values={[
178+
{ label: "Bare React Native", value: "bare" },
179+
{ label: "Expo", value: "expo" },
180+
]}
181+
>
182+
<TabItem value="bare">
183+
184+
```tsx title="index.js"
185+
import { AppRegistry } from "react-native";
186+
import "./globals";
187+
import "react-native-get-random-values";
188+
import App from "./App";
189+
import { name as appName } from "./app.json";
190+
AppRegistry.registerComponent(appName, () => App);
191+
```
192+
193+
</TabItem>
194+
195+
<TabItem value="expo">
196+
197+
```tsx title="index.js"
198+
import "@ethersproject/shims";
199+
import "@expo/metro-runtime";
200+
import "react-native-get-random-values";
201+
import "./globals";
202+
203+
import { App } from "expo-router/build/qualified-entry";
204+
import { renderRootComponent } from "expo-router/build/renderRootComponent";
205+
206+
// This file should only import and register the root. No components or exports
207+
// should be added here.
208+
renderRootComponent(App);
209+
```
210+
211+
</TabItem>
212+
213+
</Tabs>

0 commit comments

Comments
 (0)