babel-preset-expo 54.0.7-canary-20251031-b135dff → 54.1.0-canary-20251118-8f7ee64
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/build/common.js
CHANGED
|
@@ -92,7 +92,9 @@ function getIsFastRefreshEnabled(caller) {
|
|
|
92
92
|
assertExpoBabelCaller(caller);
|
|
93
93
|
if (!caller)
|
|
94
94
|
return false;
|
|
95
|
-
|
|
95
|
+
// NOTE(@kitten): `isHMREnabled` is always true in `@expo/metro-config`.
|
|
96
|
+
// However, we still use this option to ensure fast refresh is only enabled in supported runtimes (Metro + Expo)
|
|
97
|
+
return !!caller.isHMREnabled && !caller.isServer && !caller.isNodeModule && getIsDev(caller);
|
|
96
98
|
}
|
|
97
99
|
function getIsProd(caller) {
|
|
98
100
|
assertExpoBabelCaller(caller);
|
package/build/index.d.ts
CHANGED
|
@@ -26,6 +26,8 @@ type BabelPresetExpoPlatformOptions = {
|
|
|
26
26
|
unstable_transformProfile?: 'default' | 'hermes-stable' | 'hermes-canary';
|
|
27
27
|
/** Settings to pass to `babel-plugin-react-compiler`. Set as `false` to disable the plugin. */
|
|
28
28
|
'react-compiler'?: false | ReactCompilerOptions;
|
|
29
|
+
/** Only set to `false` to disable `react-refresh/babel` forcefully, defaults to `undefined` */
|
|
30
|
+
enableReactFastRefresh?: boolean;
|
|
29
31
|
/** Enable `typeof window` runtime checks. The default behavior is to minify `typeof window` on web clients to `"object"` and `"undefined"` on servers. */
|
|
30
32
|
minifyTypeofWindow?: boolean;
|
|
31
33
|
/**
|
package/build/index.js
CHANGED
|
@@ -10,6 +10,7 @@ const inline_env_vars_1 = require("./inline-env-vars");
|
|
|
10
10
|
const lazyImports_1 = require("./lazyImports");
|
|
11
11
|
const restricted_react_api_plugin_1 = require("./restricted-react-api-plugin");
|
|
12
12
|
const server_actions_plugin_1 = require("./server-actions-plugin");
|
|
13
|
+
const server_data_loaders_plugin_1 = require("./server-data-loaders-plugin");
|
|
13
14
|
const use_dom_directive_plugin_1 = require("./use-dom-directive-plugin");
|
|
14
15
|
function getOptions(options, platform) {
|
|
15
16
|
const tag = platform === 'web' ? 'web' : 'native';
|
|
@@ -162,6 +163,10 @@ function babelPresetExpo(api, options = {}) {
|
|
|
162
163
|
}
|
|
163
164
|
if ((0, common_1.hasModule)('expo-router')) {
|
|
164
165
|
extraPlugins.push(expo_router_plugin_1.expoRouterBabelPlugin);
|
|
166
|
+
// Strip loader() functions from client bundles
|
|
167
|
+
if (!isServerEnv) {
|
|
168
|
+
extraPlugins.push(server_data_loaders_plugin_1.serverDataLoadersPlugin);
|
|
169
|
+
}
|
|
165
170
|
}
|
|
166
171
|
extraPlugins.push(client_module_proxy_plugin_1.reactClientReferencesPlugin);
|
|
167
172
|
// Ensure these only run when the user opts-in to bundling for a react server to prevent unexpected behavior for
|
|
@@ -176,12 +181,13 @@ function babelPresetExpo(api, options = {}) {
|
|
|
176
181
|
}
|
|
177
182
|
// This plugin is fine to run whenever as the server-only imports were introduced as part of RSC and shouldn't be used in any client code.
|
|
178
183
|
extraPlugins.push(environment_restricted_imports_1.environmentRestrictedImportsPlugin);
|
|
179
|
-
if (
|
|
184
|
+
if (platformOptions.enableReactFastRefresh ||
|
|
185
|
+
(isFastRefreshEnabled && platformOptions.enableReactFastRefresh !== false)) {
|
|
180
186
|
extraPlugins.push([
|
|
181
187
|
require('react-refresh/babel'),
|
|
182
188
|
{
|
|
183
|
-
// We perform the env check to enable `isFastRefreshEnabled
|
|
184
|
-
skipEnvCheck: true,
|
|
189
|
+
// We perform the env check to enable `isFastRefreshEnabled`, unless the plugin is force-enabled
|
|
190
|
+
skipEnvCheck: platformOptions.enableReactFastRefresh !== true,
|
|
185
191
|
},
|
|
186
192
|
]);
|
|
187
193
|
}
|
|
@@ -0,0 +1,8 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Copyright © 2025 650 Industries.
|
|
3
|
+
*
|
|
4
|
+
* This source code is licensed under the MIT license found in the
|
|
5
|
+
* LICENSE file in the root directory of this source tree.
|
|
6
|
+
*/
|
|
7
|
+
import type { ConfigAPI, PluginObj } from '@babel/core';
|
|
8
|
+
export declare function serverDataLoadersPlugin(api: ConfigAPI & typeof import('@babel/core')): PluginObj;
|
|
@@ -0,0 +1,94 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.serverDataLoadersPlugin = serverDataLoadersPlugin;
|
|
4
|
+
const common_1 = require("./common");
|
|
5
|
+
const debug = require('debug')('expo:babel:server-data-loaders');
|
|
6
|
+
const LOADER_EXPORT_NAME = 'loader';
|
|
7
|
+
function serverDataLoadersPlugin(api) {
|
|
8
|
+
const { types: t } = api;
|
|
9
|
+
const routerAbsoluteRoot = api.caller(common_1.getExpoRouterAbsoluteAppRoot);
|
|
10
|
+
const isServer = api.caller(common_1.getIsServer);
|
|
11
|
+
return {
|
|
12
|
+
name: 'expo-server-data-loaders',
|
|
13
|
+
visitor: {
|
|
14
|
+
ExportNamedDeclaration(path, state) {
|
|
15
|
+
if (isServer) {
|
|
16
|
+
return;
|
|
17
|
+
}
|
|
18
|
+
// Early exit if file is not within the `app/` directory
|
|
19
|
+
if (!isInAppDirectory(state.file.opts.filename ?? '', routerAbsoluteRoot)) {
|
|
20
|
+
debug('Skipping file outside app directory:', state.file.opts.filename);
|
|
21
|
+
return;
|
|
22
|
+
}
|
|
23
|
+
debug(isServer ? 'Processing server bundle:' : 'Processing client bundle:', state.file.opts.filename);
|
|
24
|
+
const { declaration, specifiers } = path.node;
|
|
25
|
+
// Is this a type export like `export type Foo`?
|
|
26
|
+
const isTypeExport = path.node.exportKind === 'type';
|
|
27
|
+
// Does this export with `export { loader }`?
|
|
28
|
+
// NOTE(@hassankhan): We should add proper handling for specifiers too
|
|
29
|
+
const hasSpecifiers = specifiers.length > 0;
|
|
30
|
+
if (isTypeExport || hasSpecifiers) {
|
|
31
|
+
return;
|
|
32
|
+
}
|
|
33
|
+
// Handles `export function loader() {}`
|
|
34
|
+
if (t.isFunctionDeclaration(declaration)) {
|
|
35
|
+
const name = declaration.id?.name;
|
|
36
|
+
if (name && isLoaderIdentifier(name)) {
|
|
37
|
+
debug('Found and removed loader function declaration');
|
|
38
|
+
markForConstantFolding(state);
|
|
39
|
+
path.remove();
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
// Handles `export const loader = ...`
|
|
43
|
+
if (t.isVariableDeclaration(declaration)) {
|
|
44
|
+
let hasRemovedLoader = false;
|
|
45
|
+
declaration.declarations = declaration.declarations.filter((declarator) => {
|
|
46
|
+
const name = t.isIdentifier(declarator.id) ? declarator.id.name : null;
|
|
47
|
+
if (name && isLoaderIdentifier(name)) {
|
|
48
|
+
debug('Found and removed loader variable declaration');
|
|
49
|
+
hasRemovedLoader = true;
|
|
50
|
+
return false;
|
|
51
|
+
}
|
|
52
|
+
return true;
|
|
53
|
+
});
|
|
54
|
+
if (hasRemovedLoader) {
|
|
55
|
+
markForConstantFolding(state);
|
|
56
|
+
// If all declarations were removed, remove the export
|
|
57
|
+
if (declaration.declarations.length === 0) {
|
|
58
|
+
path.remove();
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
}
|
|
62
|
+
},
|
|
63
|
+
},
|
|
64
|
+
};
|
|
65
|
+
}
|
|
66
|
+
/**
|
|
67
|
+
* Checks if identifier name is `loader`
|
|
68
|
+
*/
|
|
69
|
+
function isLoaderIdentifier(name) {
|
|
70
|
+
return name === LOADER_EXPORT_NAME;
|
|
71
|
+
}
|
|
72
|
+
function assertExpoMetadata(metadata) {
|
|
73
|
+
if (metadata && typeof metadata === 'object') {
|
|
74
|
+
return;
|
|
75
|
+
}
|
|
76
|
+
throw new Error('Expected Babel state.file.metadata to be an object');
|
|
77
|
+
}
|
|
78
|
+
/**
|
|
79
|
+
* Check if file is within the `app/` directory
|
|
80
|
+
*/
|
|
81
|
+
function isInAppDirectory(filePath, routerRoot) {
|
|
82
|
+
const normalizedFilePath = (0, common_1.toPosixPath)(filePath);
|
|
83
|
+
const normalizedAppRoot = (0, common_1.toPosixPath)(routerRoot);
|
|
84
|
+
return normalizedFilePath.startsWith(normalizedAppRoot + '/');
|
|
85
|
+
}
|
|
86
|
+
/**
|
|
87
|
+
* Marks a file for Metro's constant folding. This will work for both development and production bundles.
|
|
88
|
+
*
|
|
89
|
+
* @see packages/@expo/metro-config/src/transform-worker/metro-transform-worker.ts#transformJS
|
|
90
|
+
*/
|
|
91
|
+
function markForConstantFolding(state) {
|
|
92
|
+
assertExpoMetadata(state.file.metadata);
|
|
93
|
+
state.file.metadata.performConstantFolding = true;
|
|
94
|
+
}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "babel-preset-expo",
|
|
3
|
-
"version": "54.0
|
|
3
|
+
"version": "54.1.0-canary-20251118-8f7ee64",
|
|
4
4
|
"description": "The Babel preset for Expo projects",
|
|
5
5
|
"main": "build/index.js",
|
|
6
6
|
"files": [
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"peerDependencies": {
|
|
44
44
|
"@babel/runtime": "^7.20.0",
|
|
45
45
|
"react-refresh": ">=0.14.0 <1.0.0",
|
|
46
|
-
"expo": "55.0.0-canary-
|
|
46
|
+
"expo": "55.0.0-canary-20251118-8f7ee64"
|
|
47
47
|
},
|
|
48
48
|
"peerDependenciesMeta": {
|
|
49
49
|
"@babel/runtime": {
|
|
@@ -69,7 +69,7 @@
|
|
|
69
69
|
"@babel/plugin-transform-parameters": "^7.24.7",
|
|
70
70
|
"@babel/preset-react": "^7.22.15",
|
|
71
71
|
"@babel/preset-typescript": "^7.23.0",
|
|
72
|
-
"@react-native/babel-preset": "0.
|
|
72
|
+
"@react-native/babel-preset": "0.83.0-nightly-20251104-502efe1cc",
|
|
73
73
|
"babel-plugin-react-compiler": "^1.0.0",
|
|
74
74
|
"babel-plugin-react-native-web": "~0.21.0",
|
|
75
75
|
"babel-plugin-transform-flow-enums": "^0.0.2",
|
|
@@ -81,7 +81,7 @@
|
|
|
81
81
|
"@babel/core": "^7.26.0",
|
|
82
82
|
"@types/babel__core": "^7.20.5",
|
|
83
83
|
"@expo/metro": "~54.1.0",
|
|
84
|
-
"expo-module-scripts": "5.0
|
|
84
|
+
"expo-module-scripts": "5.1.0-canary-20251118-8f7ee64",
|
|
85
85
|
"jest": "^29.2.1",
|
|
86
86
|
"react-refresh": "^0.14.2"
|
|
87
87
|
}
|