Skip to content

Commit 29c668d

Browse files
committed
feat: make the esm option configurable
1 parent e2d7072 commit 29c668d

File tree

7 files changed

+84
-23
lines changed

7 files changed

+84
-23
lines changed

docs/pages/build.md

Lines changed: 2 additions & 2 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",
46-
"module",
45+
["commonjs", { "esm" : true }],
46+
["module", { "esm" : true }],
4747
"typescript",
4848
]
4949
}

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

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -164,8 +164,17 @@
164164
"source": "src",
165165
"output": "lib",
166166
"targets": [
167-
"commonjs",
168-
"module",
167+
[
168+
"commonjs",
169+
{
170+
"esm": true,
171+
}
172+
],
173+
["module",
174+
{
175+
"esm": true,
176+
}
177+
],
169178
[
170179
"typescript",
171180
{

packages/react-native-builder-bob/babel-preset.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
const browserslist = require('browserslist');
44

5+
/**
6+
* Babel preset for React Native Builder Bob
7+
* @param {'commonjs' | 'preserve'} options.modules - Whether to compile modules to CommonJS or preserve them
8+
* @param {Boolean} options.esm - Whether to output ES module compatible code, e.g. by adding extension to import/export statements
9+
*/
510
module.exports = function (api, options, cwd) {
611
const cjs = options.modules === 'commonjs';
712

@@ -42,7 +47,7 @@ module.exports = function (api, options, cwd) {
4247
[
4348
require.resolve('./lib/babel'),
4449
{
45-
extension: cjs ? 'cjs' : 'mjs',
50+
extension: options.esm ? (cjs ? 'cjs' : 'mjs') : undefined,
4651
},
4752
],
4853
],

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

Lines changed: 17 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,22 @@ yargs
151151
[key in 'source' | 'main' | 'module' | 'types']?: string;
152152
} = {
153153
source: `./${path.join(source, entryFile)}`,
154-
main: `./${
155-
target
156-
? path.join(output, target, 'index.cjs')
157-
: path.join(source, entryFile)
158-
}`,
159154
};
160155

156+
let esm = false;
157+
161158
if (targets.includes('module')) {
159+
esm = true;
160+
161+
if (targets.includes('commonjs')) {
162+
entries.main = `./${path.join(output, 'commonjs', 'index.cjs')}`;
163+
}
164+
162165
entries.module = `./${path.join(output, 'module', 'index.mjs')}`;
166+
} else if (targets.includes('commonjs')) {
167+
entries.main = `./${path.join(output, 'commonjs', 'index.js')}`;
168+
} else {
169+
entries.main = entries.source;
163170
}
164171

165172
if (targets.includes('typescript')) {
@@ -240,7 +247,7 @@ yargs
240247
}
241248
}
242249

243-
if (Object.values(entries).some((entry) => entry.endsWith('.mjs'))) {
250+
if (esm) {
244251
let replace = false;
245252

246253
const exports = {
@@ -337,6 +344,10 @@ yargs
337344
return [t, { copyFlow: true }];
338345
}
339346

347+
if (t === 'commonjs' || t === 'module') {
348+
return [t, { esm }];
349+
}
350+
340351
return t;
341352
}),
342353
};

packages/react-native-builder-bob/src/targets/commonjs.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { Input } from '../types';
66

77
type Options = Input & {
88
options?: {
9+
esm?: boolean;
910
babelrc?: boolean | null;
1011
configFile?: string | false | null;
1112
sourceMaps?: boolean;

packages/react-native-builder-bob/src/targets/module.ts

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@ import type { Input } from '../types';
66

77
type Options = Input & {
88
options?: {
9+
esm?: boolean;
910
babelrc?: boolean | null;
1011
configFile?: string | false | null;
1112
sourceMaps?: boolean;
@@ -34,7 +35,7 @@ export default async function build({
3435
source,
3536
output,
3637
exclude,
37-
modules: false,
38+
modules: 'preserve',
3839
report,
3940
});
4041
}

packages/react-native-builder-bob/src/utils/compile.ts

Lines changed: 45 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -6,18 +6,20 @@ import glob from 'glob';
66
import type { Input } from '../types';
77

88
type Options = Input & {
9+
esm?: boolean;
910
babelrc?: boolean | null;
1011
configFile?: string | false | null;
1112
sourceMaps?: boolean;
1213
copyFlow?: boolean;
13-
modules: 'commonjs' | false;
14+
modules: 'commonjs' | 'preserve';
1415
exclude: string;
1516
};
1617

1718
export default async function compile({
1819
root,
1920
source,
2021
output,
22+
esm = false,
2123
babelrc = false,
2224
configFile = false,
2325
exclude,
@@ -63,7 +65,11 @@ export default async function compile({
6365
}
6466
}
6567

66-
const outputExtension = modules === 'commonjs' ? '.cjs' : '.mjs';
68+
const outputExtension = esm
69+
? modules === 'commonjs'
70+
? '.cjs'
71+
: '.mjs'
72+
: '.js';
6773

6874
await Promise.all(
6975
files.map(async (filepath) => {
@@ -91,7 +97,9 @@ export default async function compile({
9197
...(babelrc || configFile
9298
? null
9399
: {
94-
presets: [[require.resolve('../../babel-preset'), { modules }]],
100+
presets: [
101+
[require.resolve('../../babel-preset'), { modules, esm }],
102+
],
95103
}),
96104
});
97105

@@ -144,14 +152,40 @@ export default async function compile({
144152

145153
const fields =
146154
modules === 'commonjs'
147-
? [
148-
{ name: 'main', value: pkg.main },
149-
{ name: "exports['.'].require", value: pkg.exports?.['.']?.require },
150-
]
151-
: [
152-
{ name: 'module', value: pkg.module },
153-
{ name: "exports['.'].import", value: pkg.exports?.['.']?.import },
154-
];
155+
? [{ name: 'main', value: pkg.main }]
156+
: [{ name: 'module', value: pkg.module }];
157+
158+
if (esm) {
159+
if (modules === 'commonjs') {
160+
fields.push({
161+
name: "exports['.'].require",
162+
value: pkg.exports?.['.']?.require,
163+
});
164+
} else {
165+
fields.push({
166+
name: "exports['.'].import",
167+
value: pkg.exports?.['.']?.import,
168+
});
169+
}
170+
} else {
171+
if (modules === 'commonjs' && pkg.exports?.['.']?.require) {
172+
report.warn(
173+
`The ${kleur.blue('esm')} option is disabled, but the ${kleur.blue(
174+
"exports['.'].require"
175+
)} field is set in ${kleur.blue(
176+
'package.json'
177+
)}. This is likely a mistake.`
178+
);
179+
} else if (modules === 'preserve' && pkg.exports?.['.']?.import) {
180+
report.warn(
181+
`The ${kleur.blue('esm')} option is disabled, but the ${kleur.blue(
182+
"exports['.'].import"
183+
)} field is set in ${kleur.blue(
184+
'package.json'
185+
)}. This is likely a mistake.`
186+
);
187+
}
188+
}
155189

156190
if (fields.some((field) => field.value)) {
157191
await Promise.all(

0 commit comments

Comments
 (0)