Skip to content

Commit 9ca6093

Browse files
committed
docs: improve docs regarding modules
1 parent 19f5a45 commit 9ca6093

File tree

4 files changed

+54
-39
lines changed

4 files changed

+54
-39
lines changed

docs/pages/build.md

+16-24
Original file line numberDiff line numberDiff line change
@@ -45,10 +45,10 @@ To configure your project manually, follow these steps:
4545
"source": "src",
4646
"output": "lib",
4747
"targets": [
48-
["commonjs", { "esm": true }],
4948
["module", { "esm": true }],
49+
["commonjs", { "esm": true }],
5050
"typescript",
51-
"codegen",
51+
"codegen"
5252
]
5353
}
5454
```
@@ -80,7 +80,6 @@ To configure your project manually, follow these steps:
8080
"source": "./src/index.tsx",
8181
"main": "./lib/commonjs/index.js",
8282
"module": "./lib/module/index.js",
83-
"types": "./lib/typescript/commonjs/src/index.d.ts",
8483
"exports": {
8584
".": {
8685
"import": {
@@ -91,7 +90,8 @@ To configure your project manually, follow these steps:
9190
"types": "./lib/typescript/commonjs/src/index.d.ts",
9291
"default": "./lib/commonjs/index.js"
9392
}
94-
}
93+
},
94+
"./package.json": "./package.json"
9595
},
9696
"files": [
9797
"lib",
@@ -103,15 +103,11 @@ To configure your project manually, follow these steps:
103103

104104
- `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.
105105
- `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.
108106
- `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.
107+
- `exports`: The entry points for tools that support the `exports` field in `package.json` - such as Node.js 12+, modern browsers and tools. See [the ESM support guide](./esm.md) for more details.
110108

111109
Make sure to change specify correct files according to the targets you have enabled.
112110

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).
114-
115111
5. Add the output directory to `.gitignore` and `.eslintignore`
116112

117113
```gitignore
@@ -173,13 +169,15 @@ Example:
173169

174170
Various targets to build for. The available targets are:
175171

176-
#### `commonjs`
172+
#### `module`
173+
174+
Enable compiling source files with Babel and use ES module system (`import`/`export`).
177175

178-
Enable compiling source files with Babel and use CommonJS module system.
176+
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.
179177

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`.
178+
The output file should be referenced in the `module` field and `exports['.'].import` (when `esm: true`) field of `package.json`.
181179

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).
180+
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).
183181

184182
In addition, the following options are supported:
185183

@@ -243,19 +241,19 @@ Sourcemaps are generated by default alongside the compiled files. You can disabl
243241
Example:
244242

245243
```json
246-
["commonjs", { "esm": true, "copyFlow": true }]
244+
["module", { "esm": true }]
247245
```
248246

249-
#### `module`
247+
#### `commonjs`
250248

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.
249+
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`.
252250

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`.
251+
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), and some tools such a [Jest](https://jestjs.io). The output file should be referenced in the `main` field. If you have a dual module setup with both ESM and CommonJS builds, it needs to be specified in `exports['.'].require` field of `package.json`.
254252

255253
Example:
256254

257255
```json
258-
["module", { "esm": true, "sourceMaps": false }]
256+
["commonjs", { "sourceMaps": false, "copyFlow": true }]
259257
```
260258

261259
#### `typescript`
@@ -282,12 +280,6 @@ Example:
282280

283281
The output file should be referenced in the `types` field or `exports['.'].types` field of `package.json`.
284282

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-
291283
#### `codegen`
292284

293285
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.

docs/pages/esm.md

+28-9
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,16 @@ You can verify whether ESM support is enabled by checking the configuration for
99
"source": "src",
1010
"output": "lib",
1111
"targets": [
12-
["commonjs", { "esm": true }],
1312
["module", { "esm": true }],
13+
["commonjs", { "esm": true }],
1414
"typescript"
1515
]
1616
}
1717
```
1818

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.
19+
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.
20+
21+
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.
2022

2123
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):
2224

@@ -36,7 +38,6 @@ To make use of the output files, ensure that your `package.json` file contains t
3638
```json
3739
"main": "./lib/commonjs/index.js",
3840
"module": "./lib/module/index.js",
39-
"types": "./lib/typescript/commonjs/src/index.d.ts",
4041
"exports": {
4142
".": {
4243
"import": {
@@ -47,23 +48,29 @@ To make use of the output files, ensure that your `package.json` file contains t
4748
"types": "./lib/typescript/commonjs/src/index.d.ts",
4849
"default": "./lib/commonjs/index.js"
4950
}
50-
}
51+
},
52+
"./package.json": "./package.json"
5153
},
5254
```
5355

54-
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.
56+
The `main` field is for tools that don't support the `exports` field (e.g. [Metro](https://metrobundler.dev/)). The `module` field is a non-standard field that some tools use to determine the ESM entry point.
5557

56-
The `exports` field is used by modern tools and bundlers to determine the correct entry point. Here, we specify 2 conditions:
58+
The `exports` field is used by Node.js 12+, modern browsers and tools to determine the correct entry point. The entrypoint is specified in the `.` key and will be used when the library is imported or required directly (e.g. `import 'my-library'` or `require('my-library')`).
59+
60+
Here, we specify 2 conditions:
5761

5862
- `import`: Used when the library is imported with an `import` statement or a dynamic `import()`. It should point to the ESM build.
5963
- `require`: Used when the library is required with a `require` call. It should point to the CommonJS build.
6064

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.
65+
Each condition has 2 fields:
6266

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.
67+
- `types`: Used for the TypeScript definitions.
68+
- `default`: Used for the actual JS code when the library is imported or required.
6469

6570
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.
6671

72+
The `./package.json` field is used to point to the library's `package.json` file. It's necessary for tools that may need to read the `package.json` file directly (e.g. [React Native Codegen](https://reactnative.dev/docs/the-new-architecture/what-is-codegen)).
73+
6774
## Guidelines
6875

6976
There are still a few things to keep in mind if you want your library to be ESM-compatible:
@@ -79,6 +86,17 @@ There are still a few things to keep in mind if you want your library to be ESM-
7986
const { foo } = require('my-library');
8087
```
8188

89+
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:
90+
91+
```js
92+
// will import `foo.native.js`, `foo.ios.js`, `foo.js` etc.
93+
const { foo } = require('./foo');
94+
```
95+
96+
Make sure to have a file without any platform-specific extensions that will be loaded by Node.js.
97+
98+
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.
99+
82100
- 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.
83101
- 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.
84102
- 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:
@@ -96,6 +114,7 @@ There are still a few things to keep in mind if you want your library to be ESM-
96114
"react-native": "./lib/commonjs/index.native.js",
97115
"default": "./lib/commonjs/index.js"
98116
}
99-
}
117+
},
118+
"./package.json": "./package.json"
100119
}
101120
```

docs/pages/faq.md

+7-4
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,8 @@ If you have a reason to not ship Codegen generated scaffold code with your libra
135135
```diff
136136
"codegenConfig": {
137137
// …
138-
+ "includesGeneratedCode": false
138+
- "includesGeneratedCode": true
139+
+ "includesGeneratedCode": false
139140
}
140141
```
141142

@@ -146,16 +147,18 @@ If you have a reason to not ship Codegen generated scaffold code with your libra
146147
"output": "lib",
147148
"targets": [
148149
// …
149-
- "codegen"
150+
- "codegen"
150151
]
151152
```
152153

153154
3. If you have an `exports` field in your `package.json`, ensure that it contains `./package.json`:
154155

155156
```diff
156157
"exports": {
157-
// …
158-
+ "./package.json": "./package.json"
158+
".": {
159+
// …
160+
},
161+
+ "./package.json": "./package.json"
159162
},
160163
```
161164

packages/create-react-native-library/templates/common/$package.json

+3-2
Original file line numberDiff line numberDiff line change
@@ -205,12 +205,13 @@
205205
"codegen",
206206
<% } -%>
207207
[
208-
"commonjs",
208+
"module",
209209
{
210210
"esm": true
211211
}
212212
],
213-
["module",
213+
[
214+
"commonjs",
214215
{
215216
"esm": true
216217
}

0 commit comments

Comments
 (0)