Skip to content

Commit bd44597

Browse files
committed
docs: add guidelines for ESM support
1 parent a7c9ae0 commit bd44597

File tree

3 files changed

+59
-5
lines changed

3 files changed

+59
-5
lines changed

docs/pages/_meta.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,5 +2,6 @@
22
"index": "Introduction",
33
"create": "Scaffold a library",
44
"build": "Build a library",
5+
"esm": "ESM support",
56
"faq": "FAQ"
67
}

docs/pages/build.md

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,8 +42,8 @@ yarn add --dev react-native-builder-bob
4242
"source": "src",
4343
"output": "lib",
4444
"targets": [
45-
["commonjs", { "esm" : true }],
46-
["module", { "esm" : true }],
45+
["commonjs", { "esm": true }],
46+
["module", { "esm": true }],
4747
"typescript",
4848
]
4949
}
@@ -166,9 +166,7 @@ In addition, the following options are supported:
166166

167167
Setting this option to `true` will output ES modules compatible code for Node.js 12+, modern browsers and other tools that support `package.json`'s `exports` field.
168168

169-
This mainly adds file extensions to the imports and exports. Note that file extensions are not added when importing a file that may have platform-specific extensions (e.g. `.android.ts`) to avoid breaking tools.
170-
171-
If you use TypeScript, also make sure to set `"moduleResolution": "Bundler"` in your `tsconfig.json` file.
169+
See the [ESM support](./esm.md) guide for more details.
172170

173171
##### `configFile`
174172

docs/pages/esm.md

Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
# ESM support
2+
3+
Libraries created with [`create-react-native-library`](./create.md) are pre-configured to work with ESM (ECMAScript Modules) out of the box.
4+
5+
You can verify whether ESM support is enabled by checking the configuration for [`react-native-builder-bob`](./build.md) in the `package.json` file of the library:
6+
7+
```json
8+
"react-native-builder-bob": {
9+
"source": "src",
10+
"output": "lib",
11+
"targets": [
12+
["commonjs", { "esm" : true }],
13+
["module", { "esm" : true }],
14+
"typescript",
15+
]
16+
}
17+
```
18+
19+
The `"esm": true` option enables ESM-compatible output. Here's what it does:
20+
21+
- It adds the `.js` extension to the import statements in the generated files.
22+
- It creates a `package.json` file in the output directory with the content: `{ "type": "module" }`
23+
24+
In addition, it's necessary to specify `"moduleResolution": "Bundler"` in your `tsconfig.json` file:
25+
26+
```json
27+
{
28+
"compilerOptions": {
29+
"moduleResolution": "Bundler"
30+
}
31+
}
32+
```
33+
34+
This means that you don't need to specify the file extension in the import statements. They'll be automatically added when possible during the build process.
35+
36+
## Guidelines
37+
38+
There are still a few things to keep in mind if you want your library to be ESM-compatible:
39+
40+
- Avoid using default exports in your library. Named exports are recommended. Default exports produce a CommonJS module with a `default` property, which will work differently than the ESM build and can cause issues.
41+
- If the library uses platform-specific extensions (e.g., `.ios.js` or `.android.js`), the ESM output will not be compatible with Node.js. It's necessary to omit file extensions from the imports to make platform-specific extensions work, however, Node.js requires file extensions to be present. Bundlers such as Webpack (with [`resolve.fullySpecified: false`](https://webpack.js.org/configuration/module/#resolvefullyspecified)) or Metro can handle this. It's still possible to `require` the CommonJS build directly in Node.js.
42+
- 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.
43+
- 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.
44+
- 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:
45+
46+
```json
47+
"exports": {
48+
".": {
49+
"types": "./lib/typescript/src/index.d.ts",
50+
"react-native": "./lib/modules/index.native.js",
51+
"import": "./lib/modules/index.js",
52+
"require": "./lib/commonjs/index.js"
53+
}
54+
}
55+
```

0 commit comments

Comments
 (0)