You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
@@ -103,14 +94,15 @@ To configure your project manually, follow these steps:
103
94
104
95
-`source`: The path to the source code. It is used by `react-native-builder-bob` to detect the correct output files and provide better error messages.
105
96
-`main`: The entry point for the CommonJS build. This is used by Node - such as tests, SSR etc.
106
-
-`module`: The entry point for the ES module build. This is used by bundlers such as webpack.
107
-
-`types`: The entry point for the TypeScript definitions. This is used by TypeScript to typecheck the code using your library.
108
97
-`files`: The files to include in the package when publishing with `npm`.
109
-
-`exports`: The entry points for tools that support the `exports` field in `package.json` - such as Node.js 12+ & modern browsers. See [the ESM support guide](./esm.md) for more details.
98
+
-`exports`: The entry points for tools that support the `exports` field in `package.json` - such as Node.js 12+ & modern browsers:
110
99
111
-
Make sure to change specify correct files according to the targets you have enabled.
100
+
-`exports['.'].types`: The entry point for the TypeScript definitions.
101
+
-`exports['.'].default`: The entry point for the ES module build. This is used by modern tools
102
+
103
+
See [the ESM support guide](./esm.md) for more details.
112
104
113
-
> If you're building TypeScript definition files, also make sure that the `types` field points to a correct path. Depending on the project configuration, the path can be different for you than the example snippet (e.g. `lib/typescript/index.d.ts` if you have only the `src` directory and `rootDir` is not set).
105
+
Make sure to change specify correct files according to the targets you have enabled.
114
106
115
107
5. Add the output directory to `.gitignore` and `.eslintignore`
116
108
@@ -173,13 +165,15 @@ Example:
173
165
174
166
Various targets to build for. The available targets are:
175
167
176
-
#### `commonjs`
168
+
#### `module`
169
+
170
+
Enable compiling source files with Babel and use ES module system (`import`/`export`).
177
171
178
-
Enable compiling source files with Babel and use CommonJS module system.
172
+
This is useful for modern bundlers that understand ES modules. Bundlers such as [webpack](https://webpack.js.org) can also tree-shake code using ES modules.
179
173
180
-
This is useful for running the code in Node (SSR, tests etc.). The output file should be referenced in the `main` field and `exports['.'].require` (when `esm: true`) field of `package.json`.
174
+
The output file should be referenced in the `module` field and `exports['.'].import` (when `esm: true`) field of `package.json`.
181
175
182
-
By default, the code is compiled to support the last 2 versions of modern browsers. It also strips TypeScript and Flow annotations as well as compiles JSX. You can customize the environments to compile for by using a [browserslist config](https://github.com/browserslist/browserslist#config-file).
176
+
By default, the code is compiled to support the last 2 versions of modern browsers. It also strips TypeScript and Flow annotations as well as compiles JSX code. You can customize the environments to compile for by using a [browserslist config](https://github.com/browserslist/browserslist#config-file).
183
177
184
178
In addition, the following options are supported:
185
179
@@ -243,19 +237,19 @@ Sourcemaps are generated by default alongside the compiled files. You can disabl
243
237
Example:
244
238
245
239
```json
246
-
["commonjs", { "esm": true, "copyFlow": true }]
240
+
["commonjs", { "esm": true }]
247
241
```
248
242
249
-
#### `module`
243
+
#### `commonjs`
250
244
251
-
Enable compiling source files with Babel and use ES module system. This is essentially the same as the `commonjs` target and accepts the same options, but leaves the `import`/`export` statements in your code.
245
+
Enable compiling source files with Babel and use CommonJS module system. This is essentially the same as the `module` target and accepts the same options, but transforms the `import`/`export` statements in your code to `require`/`module.exports`.
252
246
253
-
This is useful for bundlers that understand ES modules and can tree-shake. The output file should be referenced in the `module` field and `exports['.'].import` (when `esm: true`) field of `package.json`.
247
+
This is useful for supporting usage of this module with `require` in Node versions older than 20 (it can still be used with `import` for Node.js 12+ if `module` target with `esm` is enabled). The output file should be referenced in the `main` field. If you need to use a [dual module setup](esm.md#dual-module-setup), it needs to be specified in `exports['.'].require` field of `package.json`.
The output file should be referenced in the `types` field or `exports['.'].types` field of `package.json`.
284
278
285
-
##### `esm`
286
-
287
-
Setting this option to `true` will output 2 sets of type definitions: one for the CommonJS build and one for the ES module build.
288
-
289
-
See the [ESM support](./esm.md) guide for more details.
290
-
291
279
#### `codegen`
292
280
293
281
Enable generating the [React Native Codegen](https://reactnative.dev/docs/the-new-architecture/what-is-codegen) scaffold code, which is used with the New React Native Architecture.
Copy file name to clipboardExpand all lines: docs/pages/esm.md
+99-21Lines changed: 99 additions & 21 deletions
Display the source diff
Display the rich diff
Original file line number
Diff line number
Diff line change
@@ -9,14 +9,15 @@ You can verify whether ESM support is enabled by checking the configuration for
9
9
"source": "src",
10
10
"output": "lib",
11
11
"targets": [
12
-
["commonjs", { "esm": true }],
13
12
["module", { "esm": true }],
14
13
"typescript"
15
14
]
16
15
}
17
16
```
18
17
19
-
The `"esm": true` option enables ESM-compatible output by adding the `.js` extension to the import statements in the generated files. For TypeScript, it also generates 2 sets of type definitions: one for the CommonJS build and one for the ES module build.
18
+
The `"esm": true` option enables ESM-compatible output by adding the `.js` extension to the import statements in the generated files. This is necessary if you want to be able to import the library on Node.js or in a bundler that supports ESM, with some caveats. See the [Guidelines](#guidelines) section for more information.
19
+
20
+
For TypeScript, it also generates 2 sets of type definitions if the [`commonjs`](build.md#commonjs) target is also enabled: one for the CommonJS build and one for the ES module build.
20
21
21
22
It's recommended to specify `"moduleResolution": "bundler"` and `"resolvePackageJsonImports": false` in your `tsconfig.json` file to match [Metro's behavior](https://reactnative.dev/blog/2023/06/21/package-exports-support#enabling-package-exports-beta):
22
23
@@ -34,35 +35,89 @@ Specifying `"moduleResolution": "bundler"` means that you don't need to use file
34
35
To make use of the output files, ensure that your `package.json` file contains the following fields:
The `main`, `module` and `types` fields are for legacy setups that don't support the `exports` field. See the [Manual configuration](build.md#manual-configuration) guide for more information about those fields.
47
+
The `main` field is for tools that don't support the `exports` field (e.g. [Metro](https://metrobundler.dev/)). The `exports` field is used by modern tools and bundlers to determine the correct entry point. Here, we specify 2 conditions:
55
48
56
-
The `exports` field is used by modern tools and bundlers to determine the correct entry point. Here, we specify 2 conditions:
49
+
-`types`: Used for the TypeScript definitions.
50
+
-`default`: Used for the actual JS code when the library is imported or required.
57
51
58
-
-`import`: Used when the library is imported with an `import` statement or a dynamic `import()`. It should point to the ESM build.
59
-
-`require`: Used when the library is required with a `require` call. It should point to the CommonJS build.
52
+
See the [Manual configuration](build.md#manual-configuration) guide for more information about those fields.
60
53
61
-
Each condition has a `types` field - necessary for TypeScript to provide the appropriate definitions for the module system. The type definitions have slightly different semantics for CommonJS and ESM, so it's important to specify them separately.
54
+
You can also specify additional conditions for different scenarios, such as `react-native`, `browser`, `production`, `development` etc. Note that support for these conditions depends on the tooling you're using.
62
55
63
-
The `default` field is the fallback entry point for both conditions. It's used for the actual JS code when the library is imported or required.
56
+
## Dual module setup
64
57
65
-
You can also specify additional conditions for different scenarios, such as `react-native`, `browser`, `production`, `development` etc. Note that support for these conditions depends on the tooling you're using.
58
+
The previously mentioned setup only works with tools that support ES modules. If you want to support tools that don't support ESM and use the CommonJS module system, you can set up a dual module setup.
59
+
60
+
A dual module setup means that you have 2 builds of your library: one for ESM and one for CommonJS. The ESM build is used by tools that support ES modules, while the CommonJS build is used by tools that don't support ES modules.
61
+
62
+
To set up a dual module setup, you can follow these steps:
63
+
64
+
1. Add the `commonjs` target to the `react-native-builder-bob` field in your `package.json` or `bob.config.js`:
65
+
66
+
```diff
67
+
"react-native-builder-bob": {
68
+
"source": "src",
69
+
"output": "lib",
70
+
"targets": [
71
+
["module", { "esm": true }],
72
+
+ ["commonjs", { "esm": true }]
73
+
"typescript",
74
+
]
75
+
}
76
+
```
77
+
78
+
2. Change the `main` field in your `package.json` to point to the CommonJS build:
79
+
80
+
```diff
81
+
- "main": "./lib/module/index.js",
82
+
+ "main": "./lib/commonjs/index.js",
83
+
```
84
+
85
+
3. Optionally add a `module` field in your `package.json` to point to the ESM build:
86
+
87
+
```diff
88
+
"main": "./lib/commonjs/index.js",
89
+
+ "module": "./lib/module/index.js",
90
+
```
91
+
92
+
The `module` field is a non-standard field that some tools use to determine the ESM entry point.
93
+
94
+
4. Change the `exports` field in your `package.json` to include 2 conditions:
-`import`: Used when the library is imported with an `import` statement or a dynamic `import()`. It will point to the ESM build.
116
+
-`require`: Used when the library is required with a `require` call. It will point to the CommonJS build.
117
+
118
+
Each condition has a `types` field - necessary for TypeScript to provide the appropriate definitions for the module system. The type definitions have slightly different semantics for CommonJS and ESM, so it's important to specify them separately.
119
+
120
+
The `default` field is the fallback entry point for both conditions. It's used for the actual JS code when the library is imported or required.
66
121
67
122
## Guidelines
68
123
@@ -79,9 +134,32 @@ There are still a few things to keep in mind if you want your library to be ESM-
79
134
const { foo } =require('my-library');
80
135
```
81
136
137
+
Alternatively, if you want to be able to use the library in Node.js with `import` syntax, you can use `require` to import code with platform-specific extensions in your library:
138
+
139
+
```js
140
+
// will import `foo.native.js`, `foo.ios.js`, `foo.js` etc.
141
+
const { foo } =require('./foo');
142
+
```
143
+
144
+
Make sure to have a file without any platform-specific extensions that will be loaded by Node.js.
145
+
146
+
Also note that if your module (e.g. `foo.js` in this case) contains ESM syntax, it will only work on Node.js 20 or newer.
147
+
82
148
- Avoid using `.cjs`, `.mjs`, `.cts` or `.mts` extensions. Metro always requires file extensions in import statements when using `.cjs` or `.mjs` which breaks platform-specific extension resolution.
83
149
- Avoid using `"moduleResolution": "node16"` or `"moduleResolution": "nodenext"` in your `tsconfig.json` file. They require file extensions in import statements which breaks platform-specific extension resolution.
84
-
- If you specify a `react-native` condition in `exports`, make sure that it comes before `import` or `require`. The conditions should be ordered from the most specific to the least specific:
150
+
- If you specify a `react-native` condition in `exports`, make sure that it comes before other conditions. The conditions should be ordered from the most specific to the least specific:
0 commit comments