Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 11 additions & 1 deletion packages/react-native-builder-bob/babel-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,17 @@ const getConfig = (defaultConfig, { root, pkg }) => {
},
{
include: path.join(root, src),
presets: [require.resolve('./babel-preset')],
presets: [
[
require.resolve('./babel-preset'),
{
// Let the app's preset handle the commonjs transform
// Otherwise this causes issues with `@react-native/babel-plugin-codegen`
// Codegen generates `export` statements in wrong places causing syntax error
supportsStaticESM: true,
},
],
],
},
],
};
Expand Down
9 changes: 7 additions & 2 deletions packages/react-native-builder-bob/babel-preset.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,16 @@ const browserslist = require('browserslist');

/**
* Babel preset for React Native Builder Bob
*
* @param {Boolean} options.supportsStaticESM - Whether to preserve ESM imports/exports, defaults to `false`
* @param {Boolean} options.rewriteImportExtensions - Whether to rewrite import extensions to '.js', defaults to `false`
* @param {'automatic' | 'classic'} options.jsxRuntime - Which JSX runtime to use, defaults to 'automatic'
*/
module.exports = function (api, options, cwd) {
const opt = (name) =>
api.caller((caller) => (caller != null ? caller[name] : undefined));
options[name] !== undefined
? options[name]
: api.caller((caller) => (caller != null ? caller[name] : undefined));

const supportsStaticESM = opt('supportsStaticESM');
const rewriteImportExtensions = opt('rewriteImportExtensions');
Expand Down Expand Up @@ -47,7 +53,6 @@ module.exports = function (api, options, cwd) {
require.resolve('@babel/preset-flow'),
],
plugins: [
require.resolve('@react-native/babel-plugin-codegen'),
require.resolve('@babel/plugin-transform-strict-mode'),
[
require.resolve('./lib/babel'),
Expand Down
1 change: 0 additions & 1 deletion packages/react-native-builder-bob/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -51,7 +51,6 @@
"@babel/preset-flow": "^7.24.7",
"@babel/preset-react": "^7.24.7",
"@babel/preset-typescript": "^7.24.7",
"@react-native/babel-plugin-codegen": "^0.76.3",
"babel-plugin-module-resolver": "^5.0.2",
"browserslist": "^4.20.4",
"cosmiconfig": "^9.0.0",
Expand Down
21 changes: 15 additions & 6 deletions packages/react-native-builder-bob/src/babel.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import type {
ExportAllDeclaration,
ExportNamedDeclaration,
} from '@babel/types';
import isFabricComponentFile from './utils/isFabricComponentFile';

type Options = {
/**
Expand Down Expand Up @@ -38,17 +39,18 @@ const isDirectory = (filename: string): boolean => {
return exists;
};

const isModule = (
const checkExts = (
filename: string,
extension: string,
platforms: string[]
platforms: string[],
callback: (ext: string) => boolean
): boolean => {
const exts = ['js', 'ts', 'jsx', 'tsx', extension];

return exts.some(
(ext) =>
isFile(`${filename}.${ext}`) &&
platforms.every((platform) => !isFile(`${filename}.${platform}.${ext}`))
callback(`${filename}.${ext}`) &&
platforms.every((platform) => !callback(`${filename}.${platform}.${ext}`))
);
};

Expand Down Expand Up @@ -112,22 +114,29 @@ export default function (
node.source.value
);

// Skip if file is a fabric view
if (
checkExts(filename, extension, platforms, (f) => isFabricComponentFile(f))
) {
return;
}

// Replace .ts extension with .js if file with extension is explicitly imported
if (isFile(filename)) {
node.source.value = node.source.value.replace(/\.tsx?$/, `.${extension}`);
return;
}

// Add extension if .ts file or file with extension exists
if (isModule(filename, extension, platforms)) {
if (checkExts(filename, extension, platforms, isFile)) {
node.source.value += `.${extension}`;
return;
}

// Expand folder imports to index and add extension
if (
isDirectory(filename) &&
isModule(path.join(filename, 'index'), extension, platforms)
checkExts(path.join(filename, 'index'), extension, platforms, isFile)
) {
node.source.value = node.source.value.replace(
/\/?$/,
Expand Down
8 changes: 8 additions & 0 deletions packages/react-native-builder-bob/src/utils/compile.ts
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import kleur from 'kleur';
import * as babel from '@babel/core';
import glob from 'glob';
import type { Input } from '../types';
import isFabricComponentFile from './isFabricComponentFile';

type Options = Input & {
esm?: boolean;
Expand Down Expand Up @@ -95,6 +96,13 @@ export default async function compile({
return;
}

if (isFabricComponentFile(filepath)) {
// React Native wants to handle compiling the file for fabric components
// So we just copy it over as is
fs.copy(filepath, path.join(output, path.relative(source, filepath)));
return;
}

const content = await fs.readFile(filepath, 'utf-8');
const result = await babel.transformAsync(content, {
caller: {
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
export default function isFabricComponentFile(filepath: string): boolean {
return /(?:^|[\\/])(?:Native\w+|(\w+)NativeComponent)\.[jt]sx?$/.test(
filepath
);
}
Loading
Loading