Skip to content

Commit

Permalink
feat: add esm build option for typescript (#603)
Browse files Browse the repository at this point in the history
This wraps up the ESM support to add support for TypeScript as well. For
TypeScript to work correctly, it's necessary to have 2 builds (for ESM
and CommonJS). With this, we generate one build and then copy the
folder, then add a `package.json` with `type` property for the module
system.
  • Loading branch information
satya164 authored Aug 1, 2024
1 parent f0a7a2f commit fd43167
Show file tree
Hide file tree
Showing 7 changed files with 258 additions and 91 deletions.
21 changes: 16 additions & 5 deletions docs/pages/build.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@ yarn add --dev react-native-builder-bob
"targets": [
["commonjs", { "esm": true }],
["module", { "esm": true }],
"typescript",
["typescript", { "esm": true }]
]
}
```
Expand Down Expand Up @@ -76,12 +76,17 @@ yarn add --dev react-native-builder-bob
"source": "./src/index.tsx",
"main": "./lib/commonjs/index.js",
"module": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
"types": "./lib/typescript/commonjs/src/index.d.ts",
"exports": {
".": {
"types": "./typescript/src/index.d.ts",
"import": "./module/index.js",
"require": "./commonjs/index.js"
"import": {
"types": "./lib/typescript/module/src/index.d.ts",
"default": "./lib/module/index.js"
},
"require": {
"types": "./lib/typescript/commonjs/src/index.d.ts",
"default": "./lib/commonjs/index.js"
}
}
},
"files": [
Expand Down Expand Up @@ -224,6 +229,12 @@ Example:

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

##### `esm`

Setting this option to `true` will output 2 sets of type definitions: one for the CommonJS build and one for the ES module build.

See the [ESM support](./esm.md) guide for more details.

## Commands

The `bob` CLI exposes the following commands:
Expand Down
18 changes: 12 additions & 6 deletions docs/pages/esm.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,12 @@ You can verify whether ESM support is enabled by checking the configuration for
"targets": [
["commonjs", { "esm": true }],
["module", { "esm": true }],
"typescript",
["typescript", { "esm": true }]
]
}
```

The `"esm": true` option enables ESM-compatible output by adding the `.js` extension to the import statements in the generated files.
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.

It's recommended to specify `"moduleResolution": "Bundler"` in your `tsconfig.json` file as well:

Expand All @@ -43,10 +43,16 @@ There are still a few things to keep in mind if you want your library to be ESM-
```json
"exports": {
".": {
"types": "./lib/typescript/src/index.d.ts",
"react-native": "./lib/modules/index.native.js",
"import": "./lib/modules/index.js",
"require": "./lib/commonjs/index.js"
"import": {
"types": "./lib/typescript/module/src/index.d.ts",
"react-native": "./lib/modules/index.native.js",
"default": "./lib/module/index.js"
},
"require": {
"types": "./lib/typescript/commonjs/src/index.d.ts",
"react-native": "./lib/commonjs/index.native.js",
"default": "./lib/commonjs/index.js"
}
}
}
```
2 changes: 1 addition & 1 deletion packages/create-react-native-library/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ import generateExampleApp, {
import { spawn } from './utils/spawn';
import { version } from '../package.json';

const FALLBACK_BOB_VERSION = '0.28.0';
const FALLBACK_BOB_VERSION = '0.29.0';

const BINARIES = [
/(gradlew|\.(jar|keystore|png|jpg|gif))$/,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
"source": "./src/index.tsx",
"main": "./lib/commonjs/index.js",
"module": "./lib/module/index.js",
"types": "./lib/typescript/src/index.d.ts",
"exports": {
".": {
"types": "./lib/typescript/src/index.d.ts",
"import": "./lib/module/index.js",
"require": "./lib/commonjs/index.js"
"import": {
"types": "./lib/typescript/module/src/index.d.ts",
"default": "./lib/module/index.js"
},
"require": {
"types": "./lib/typescript/commonjs/src/index.d.ts",
"default": "./lib/commonjs/index.js"
}
}
},
"files": [
Expand Down Expand Up @@ -178,7 +182,8 @@
[
"typescript",
{
"project": "tsconfig.build.json"
"project": "tsconfig.build.json",
"esm": true
}
]
]
Expand Down
64 changes: 41 additions & 23 deletions packages/react-native-builder-bob/src/index.ts
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,29 @@ yargs
entries.main = entries.source;
}

const types: {
[key in 'require' | 'import']?: string;
} = {};

if (targets.includes('typescript')) {
entries.types = `./${path.join(
types.require = `./${path.join(
output,
'typescript',
'commonjs',
source,
'index.d.ts'
)}`;

types.import = `./${path.join(
output,
'typescript',
'module',
source,
'index.d.ts'
)}`;

entries.types = types.require;

if (!(await fs.pathExists(path.join(root, 'tsconfig.json')))) {
const { tsconfig } = await prompts({
type: 'confirm',
Expand Down Expand Up @@ -258,9 +273,14 @@ yargs

const exports = {
'.': {
...(entries.types ? { types: entries.types } : null),
...(entries.module ? { import: entries.module } : null),
...(entries.main ? { require: entries.main } : null),
import: {
...(types.import ? { types: types.import } : null),
...(entries.module ? { default: entries.module } : null),
},
require: {
...(types.require ? { types: types.require } : null),
...(entries.main ? { default: entries.main } : null),
},
},
};

Expand Down Expand Up @@ -318,25 +338,23 @@ yargs
pkg.scripts.prepare = prepare;
}

if (
pkg.files &&
JSON.stringify(pkg.files.slice().sort()) !==
JSON.stringify(files.slice().sort())
) {
const { update } = await prompts({
type: 'confirm',
name: 'update',
message: `Your package.json already has a 'files' field.\n Do you want to update it?`,
initial: true,
});
if (pkg.files) {
const pkgFiles = pkg.files;

if (update) {
pkg.files = [
...files,
...pkg.files.filter(
(file: string) => !files.includes(file.replace(/\/$/g, ''))
),
];
if (files?.some((file) => !pkgFiles.includes(file))) {
const { update } = await prompts({
type: 'confirm',
name: 'update',
message: `Your package.json already has a 'files' field.\n Do you want to update it?`,
initial: true,
});

if (update) {
pkg.files = [
...files,
...pkg.files.filter((file: string) => !files.includes(file)),
];
}
}
} else {
pkg.files = files;
Expand All @@ -350,7 +368,7 @@ yargs
return [t, { copyFlow: true }];
}

if (t === 'commonjs' || t === 'module') {
if (t === 'commonjs' || t === 'module' || t === 'typescript') {
return [t, { esm }];
}

Expand Down
Loading

0 comments on commit fd43167

Please sign in to comment.