GT2/Ejectable/node_modules/babel-preset-expo/index.js

128 lines
4.5 KiB
JavaScript

const lazyImportsBlacklist = require('./lazy-imports-blacklist');
module.exports = function(api, options = {}) {
const { web = {}, native = {} } = options;
const bundler = api.caller(getBundler);
const isWebpack = bundler === 'webpack';
let platform = api.caller(getPlatform);
// If the `platform` prop is not defined then this must be a custom config that isn't
// defining a platform in the babel-loader. Currently this may happen with Next.js + Expo web.
if (!platform && isWebpack) {
platform = 'web';
}
const platformOptions =
platform === 'web'
? { disableImportExportTransform: true, ...web }
: { disableImportExportTransform: false, ...native };
// Note that if `options.lazyImports` is not set (i.e., `null` or `undefined`),
// `metro-react-native-babel-preset` will handle it.
const lazyImportsOption = options && options.lazyImports;
return {
presets: [
[
// We use `require` here instead of directly using the package name because we want to
// specifically use the `metro-react-native-babel-preset` installed by this package (ex:
// `babel-preset-expo/node_modules/`). This way the preset will not change unintentionally.
// Reference: https://github.com/expo/expo/pull/4685#discussion_r307143920
require('metro-react-native-babel-preset'),
{
// Defaults to undefined, set to something truthy to disable `@babel/plugin-transform-react-jsx-self` and `@babel/plugin-transform-react-jsx-source`.
withDevTools: platformOptions.withDevTools,
// Defaults to undefined, set to `true` to disable `@babel/plugin-transform-flow-strip-types`
disableFlowStripTypesTransform: platformOptions.disableFlowStripTypesTransform,
// Defaults to undefined, set to `false` to disable `@babel/plugin-transform-runtime`
enableBabelRuntime: platformOptions.enableBabelRuntime,
// Defaults to `'default'`, can also use `'hermes-canary'`
unstable_transformProfile: platformOptions.unstable_transformProfile,
// Set true to disable `@babel/plugin-transform-react-jsx`
useTransformReactJsxExperimental: platformOptions.useTransformReactJsxExperimental,
disableImportExportTransform: platformOptions.disableImportExportTransform,
lazyImportExportTransform:
lazyImportsOption === true
? importModuleSpecifier => {
// Do not lazy-initialize packages that are local imports (similar to `lazy: true`
// behavior) or are in the blacklist.
return !(
importModuleSpecifier.includes('./') ||
lazyImportsBlacklist.has(importModuleSpecifier)
);
}
: // Pass the option directly to `metro-react-native-babel-preset`, which in turn
// passes it to `babel-plugin-transform-modules-commonjs`
lazyImportsOption,
},
],
],
plugins: [
getAliasPlugin(),
[require.resolve('@babel/plugin-proposal-decorators'), { legacy: true }],
platform === 'web' && [require.resolve('babel-plugin-react-native-web')],
isWebpack && platform !== 'web' && [require.resolve('./plugins/disable-ambiguous-requires')],
].filter(Boolean),
};
};
function getAliasPlugin() {
const aliases = {};
if (hasModule('@expo/vector-icons')) {
aliases['react-native-vector-icons'] = '@expo/vector-icons';
}
if (Object.keys(aliases).length) {
return [
require.resolve('babel-plugin-module-resolver'),
{
alias: aliases,
},
];
}
return null;
}
function hasModule(name) {
try {
return !!require.resolve(name);
} catch (error) {
if (error.code === 'MODULE_NOT_FOUND' && error.message.includes(name)) {
return false;
}
throw error;
}
}
function getPlatform(caller) {
return caller && caller.platform;
}
/**
* Get the name of the `bundler`.
*
* @param {*} caller
*/
function getBundler(caller) {
if (!caller) return null;
const { bundler, name } = caller;
if (!bundler) {
if (name === 'metro') {
// This is a hack to determine if metro is being used.
return 'metro';
} else if (name === 'next-babel-turbo-loader') {
// NextJS 11
return 'webpack';
} else if (name === 'babel-loader') {
// expo/webpack-config, gatsby, storybook, and next.js <10
return 'webpack';
}
}
// Perhaps we should add a check to log once when an unexpected bundler is being used.
return bundler || null;
}