Skip to content

Commit 18126b9

Browse files
committed
refactor: drop commonjs build from default setup
1 parent 9ca6093 commit 18126b9

File tree

5 files changed

+94
-63
lines changed

5 files changed

+94
-63
lines changed

docs/pages/build.md

Lines changed: 4 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,6 @@ To configure your project manually, follow these steps:
4646
"output": "lib",
4747
"targets": [
4848
["module", { "esm": true }],
49-
["commonjs", { "esm": true }],
5049
"typescript",
5150
"codegen"
5251
]
@@ -78,18 +77,11 @@ To configure your project manually, follow these steps:
7877

7978
```json
8079
"source": "./src/index.tsx",
81-
"main": "./lib/commonjs/index.js",
82-
"module": "./lib/module/index.js",
80+
"main": "./lib/module/index.js",
8381
"exports": {
8482
".": {
85-
"import": {
86-
"types": "./lib/typescript/module/src/index.d.ts",
87-
"default": "./lib/module/index.js"
88-
},
89-
"require": {
90-
"types": "./lib/typescript/commonjs/src/index.d.ts",
91-
"default": "./lib/commonjs/index.js"
92-
}
83+
"types": "./lib/typescript/src/index.d.ts",
84+
"default": "./lib/module/index.js"
9385
},
9486
"./package.json": "./package.json"
9587
},
@@ -248,7 +240,7 @@ Example:
248240

249241
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`.
250242

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

253245
Example:
254246

docs/pages/esm.md

Lines changed: 83 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ You can verify whether ESM support is enabled by checking the configuration for
1010
"output": "lib",
1111
"targets": [
1212
["module", { "esm": true }],
13-
["commonjs", { "esm": true }],
1413
"typescript"
1514
]
1615
}
@@ -36,41 +35,95 @@ Specifying `"moduleResolution": "bundler"` means that you don't need to use file
3635
To make use of the output files, ensure that your `package.json` file contains the following fields:
3736

3837
```json
39-
"main": "./lib/commonjs/index.js",
40-
"module": "./lib/module/index.js",
38+
"main": "./lib/module/index.js",
4139
"exports": {
4240
".": {
43-
"import": {
44-
"types": "./lib/typescript/module/src/index.d.ts",
45-
"default": "./lib/module/index.js"
46-
},
47-
"require": {
48-
"types": "./lib/typescript/commonjs/src/index.d.ts",
49-
"default": "./lib/commonjs/index.js"
50-
}
41+
"types": "./lib/typescript/src/index.d.ts",
42+
"default": "./lib/module/index.js"
5143
},
5244
"./package.json": "./package.json"
5345
},
5446
```
5547

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.
48+
The `main` field is for tools that don't support the `exports` field (e.g. [Metro](https://metrobundler.dev/)).
5749

5850
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')`).
5951

6052
Here, we specify 2 conditions:
6153

62-
- `import`: Used when the library is imported with an `import` statement or a dynamic `import()`. It should point to the ESM build.
63-
- `require`: Used when the library is required with a `require` call. It should point to the CommonJS build.
64-
65-
Each condition has 2 fields:
66-
6754
- `types`: Used for the TypeScript definitions.
6855
- `default`: Used for the actual JS code when the library is imported or required.
6956

7057
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.
7158

7259
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)).
7360

61+
## Dual module setup
62+
63+
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.
64+
65+
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.
66+
67+
To set up a dual module setup, you can follow these steps:
68+
69+
1. Add the `commonjs` target to the `react-native-builder-bob` field in your `package.json` or `bob.config.js`:
70+
71+
```diff
72+
"react-native-builder-bob": {
73+
"source": "src",
74+
"output": "lib",
75+
"targets": [
76+
["module", { "esm": true }],
77+
+ ["commonjs", { "esm": true }]
78+
"typescript",
79+
]
80+
}
81+
```
82+
83+
2. Change the `main` field in your `package.json` to point to the CommonJS build:
84+
85+
```diff
86+
- "main": "./lib/module/index.js",
87+
+ "main": "./lib/commonjs/index.js",
88+
```
89+
90+
3. Optionally add a `module` field in your `package.json` to point to the ESM build:
91+
92+
```diff
93+
"main": "./lib/commonjs/index.js",
94+
+ "module": "./lib/module/index.js",
95+
```
96+
97+
The `module` field is a non-standard field that some tools use to determine the ESM entry point.
98+
99+
4. Change the `exports` field in your `package.json` to include 2 conditions:
100+
101+
```diff
102+
"exports": {
103+
".": {
104+
- "types": "./lib/typescript/src/index.d.ts",
105+
- "default": "./lib/module/index.js"
106+
+ "import": {
107+
+ "types": "./lib/typescript/module/src/index.d.ts",
108+
+ "default": "./lib/module/index.js"
109+
+ },
110+
+ "require": {
111+
+ "types": "./lib/typescript/commonjs/src/index.d.ts",
112+
+ "default": "./lib/commonjs/index.js"
113+
+ }
114+
}
115+
},
116+
```
117+
118+
Here, we specify 2 conditions:
119+
120+
- `import`: Used when the library is imported with an `import` statement or a dynamic `import()`. It will point to the ESM build.
121+
- `require`: Used when the library is required with a `require` call. It will point to the CommonJS build.
122+
123+
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.
124+
125+
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.
126+
74127
## Guidelines
75128

76129
There are still a few things to keep in mind if you want your library to be ESM-compatible:
@@ -99,7 +152,19 @@ There are still a few things to keep in mind if you want your library to be ESM-
99152

100153
- 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.
101154
- 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.
102-
- 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:
155+
- 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:
156+
157+
```json
158+
"exports": {
159+
".": {
160+
"types": "./lib/typescript/src/index.d.ts",
161+
"react-native": "./lib/modules/index.native.js",
162+
"default": "./lib/module/index.js"
163+
}
164+
}
165+
```
166+
167+
Or for a dual module setup:
103168

104169
```json
105170
"exports": {

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

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -3,18 +3,11 @@
33
"version": "0.1.0",
44
"description": "<%- project.description %>",
55
"source": "./src/index.tsx",
6-
"main": "./lib/commonjs/index.js",
7-
"module": "./lib/module/index.js",
6+
"main": "./lib/module/index.js",
87
"exports": {
98
".": {
10-
"import": {
11-
"types": "./lib/typescript/module/src/index.d.ts",
12-
"default": "./lib/module/index.js"
13-
},
14-
"require": {
15-
"types": "./lib/typescript/commonjs/src/index.d.ts",
16-
"default": "./lib/commonjs/index.js"
17-
}
9+
"types": "./lib/typescript/src/index.d.ts",
10+
"default": "./lib/module/index.js"
1811
},
1912
"./package.json": "./package.json"
2013
},
@@ -210,12 +203,6 @@
210203
"esm": true
211204
}
212205
],
213-
[
214-
"commonjs",
215-
{
216-
"esm": true
217-
}
218-
],
219206
[
220207
"typescript",
221208
{

packages/react-native-builder-bob/src/__tests__/__snapshots__/init.test.ts.snap

Lines changed: 3 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -9,20 +9,13 @@ exports[`initializes the configuration 1`] = `
99
},
1010
"exports": {
1111
".": {
12-
"import": {
13-
"types": "./lib/typescript/module/src/index.d.ts",
14-
"default": "./lib/module/index.js"
15-
},
16-
"require": {
17-
"types": "./lib/typescript/commonjs/src/index.d.ts",
18-
"default": "./lib/commonjs/index.js"
19-
}
12+
"types": "./lib/typescript/src/index.d.ts",
13+
"default": "./lib/module/index.js"
2014
},
2115
"./package.json": "./package.json"
2216
},
2317
"source": "./src/index.ts",
24-
"main": "./lib/commonjs/index.js",
25-
"module": "./lib/module/index.js",
18+
"main": "./lib/module/index.js",
2619
"scripts": {
2720
"prepare": "bob build"
2821
},
@@ -43,12 +36,6 @@ exports[`initializes the configuration 1`] = `
4336
"esm": true
4437
}
4538
],
46-
[
47-
"commonjs",
48-
{
49-
"esm": true
50-
}
51-
],
5239
"typescript"
5340
]
5441
},

packages/react-native-builder-bob/src/init.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -104,7 +104,7 @@ export async function init() {
104104
{
105105
title: 'commonjs - for legacy setups (Node.js < 20)',
106106
value: 'commonjs',
107-
selected: true,
107+
selected: false,
108108
},
109109
{
110110
title: 'typescript - declaration files for typechecking',

0 commit comments

Comments
 (0)