Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(cli): transform based on engine #24672

Merged
merged 7 commits into from
Sep 29, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
2 changes: 2 additions & 0 deletions packages/@expo/cli/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### 🎉 New features

- Automatically optimize transformations based on Hermes usage. ([#24672](https://github.com/expo/expo/pull/24672) by [@EvanBacon](https://github.com/EvanBacon))

### 🐛 Bug fixes

- Ensure a unique static path is generated for each group during static extraction ([#24218](https://github.com/expo/expo/pull/24218) by [@marklawlor](https://github.com/marklawlor))
Expand Down
2 changes: 1 addition & 1 deletion packages/@expo/cli/e2e/__tests__/start-test.ts
Original file line number Diff line number Diff line change
Expand Up @@ -172,7 +172,7 @@ describe('server', () => {

// URLs
expect(manifest.launchAsset.url).toBe(
'http://127.0.0.1:8081/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false'
'http://127.0.0.1:8081/node_modules/expo/AppEntry.bundle?platform=ios&dev=true&hot=false&transform.engine=hermes'
);
expect(manifest.extra.expoGo.debuggerHost).toBe('127.0.0.1:8081');
expect(manifest.extra.expoGo.mainModuleName).toBe('node_modules/expo/AppEntry');
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,7 @@ type StaticRenderOptions = {
minify?: boolean;
platform?: string;
environment?: 'node';
engine?: 'hermes';
};

const moveStaticRenderFunction = memoize(async (projectRoot: string, requiredModuleId: string) => {
Expand Down Expand Up @@ -100,7 +101,13 @@ export async function createMetroEndpointAsync(
projectRoot: string,
devServerUrl: string,
absoluteFilePath: string,
{ dev = false, platform = 'web', minify = false, environment }: StaticRenderOptions = {}
{
dev = false,
platform = 'web',
minify = false,
environment,
engine = 'hermes',
}: StaticRenderOptions = {}
): Promise<string> {
const root = getMetroServerRoot(projectRoot);
const safeOtherFile = await ensureFileInRootDirectory(projectRoot, absoluteFilePath);
Expand All @@ -112,6 +119,9 @@ export async function createMetroEndpointAsync(
if (environment) {
url += `&resolver.environment=${environment}&transform.environment=${environment}`;
}
if (engine) {
url += `&transform.engine=${engine}`;
}
return url;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@ import { resolveGoogleServicesFile, resolveManifestAssets } from './resolveAsset
import { resolveAbsoluteEntryPoint } from './resolveEntryPoint';
import { parsePlatformHeader, RuntimePlatform } from './resolvePlatform';
import { ServerHeaders, ServerNext, ServerRequest, ServerResponse } from './server.types';
import { isEnableHermesManaged } from '../../../export/exportHermes';
import * as Log from '../../../log';
import { env } from '../../../utils/env';
import { stripExtension } from '../../../utils/url';
Expand Down Expand Up @@ -84,6 +85,7 @@ export function createBundleUrlPath({
serializerOutput,
serializerIncludeMaps,
lazy,
engine,
}: {
platform: string;
mainModuleName: string;
Expand All @@ -93,6 +95,7 @@ export function createBundleUrlPath({
serializerOutput?: 'static';
serializerIncludeMaps?: boolean;
lazy?: boolean;
engine?: 'hermes';
}): string {
const queryParams = new URLSearchParams({
platform: encodeURIComponent(platform),
Expand All @@ -108,6 +111,11 @@ export function createBundleUrlPath({
if (minify) {
queryParams.append('minify', String(minify));
}

if (engine) {
queryParams.append('transform.engine', engine);
}

if (environment) {
queryParams.append('resolver.environment', environment);
queryParams.append('transform.environment', environment);
Expand Down Expand Up @@ -191,6 +199,8 @@ export abstract class ManifestMiddleware<
// Read from headers
const mainModuleName = this.resolveMainModuleName(projectConfig, platform);

const isHermesEnabled = isEnableHermesManaged(projectConfig.exp, platform);

// Create the manifest and set fields within it
const expoGoConfig = this.getExpoGoConfig({
mainModuleName,
Expand All @@ -203,6 +213,7 @@ export abstract class ManifestMiddleware<
platform,
mainModuleName,
hostname,
engine: isHermesEnabled ? 'hermes' : undefined,
});

// Resolve all assets and set them on the manifest as URLs
Expand Down Expand Up @@ -253,17 +264,20 @@ export abstract class ManifestMiddleware<
platform,
mainModuleName,
hostname,
engine,
}: {
platform: string;
hostname?: string | null;
mainModuleName: string;
engine?: 'hermes';
}): string {
const path = createBundleUrlPath({
mode: this.options.mode ?? 'development',
minify: this.options.minify,
platform,
mainModuleName,
lazy: shouldEnableAsyncImports(this.projectRoot),
engine,
});

return (
Expand All @@ -275,12 +289,14 @@ export abstract class ManifestMiddleware<
);
}

public _getBundleUrlPath({
private _getBundleUrlPath({
platform,
mainModuleName,
engine,
}: {
platform: string;
mainModuleName: string;
engine?: 'hermes';
}): string {
const queryParams = new URLSearchParams({
platform: encodeURIComponent(platform),
Expand All @@ -291,7 +307,9 @@ export abstract class ManifestMiddleware<
if (shouldEnableAsyncImports(this.projectRoot)) {
queryParams.append('lazy', String(true));
}

if (engine) {
queryParams.append('transform.engine', String(engine));
}
if (this.options.minify) {
queryParams.append('minify', String(this.options.minify));
}
Expand Down Expand Up @@ -362,6 +380,8 @@ export abstract class ManifestMiddleware<
return this._getBundleUrlPath({
platform,
mainModuleName,
// Hermes doesn't support more modern JS features than most, if not all, modern browser.
engine: 'hermes',
});
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ describe('checkBrowserRequestAsync', () => {
// NOTE(EvanBacon): Browsers won't pass the `expo-platform` header so we need to
// provide the `platform=web` query parameter in order for the multi-platform dev server
// to return the correct bundle.
'/index.bundle?platform=web&dev=true&hot=false',
'/index.bundle?platform=web&dev=true&hot=false&transform.engine=hermes',
],
});
expect(res.setHeader).toBeCalledWith('Content-Type', 'text/html');
Expand Down
2 changes: 2 additions & 0 deletions packages/@expo/metro-config/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

### 🎉 New features

- Automatically optimize transformations based on Hermes usage. ([#24672](https://github.com/expo/expo/pull/24672) by [@EvanBacon](https://github.com/EvanBacon))

### 🐛 Bug fixes

### 💡 Others
Expand Down
7 changes: 5 additions & 2 deletions packages/@expo/metro-config/build/babel-transformer.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Large diffs are not rendered by default.

3 changes: 3 additions & 0 deletions packages/@expo/metro-config/src/babel-transformer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,9 @@ const transform: BabelTransformer['transform'] = ({
// Empower the babel preset to know the env it's bundling for.
// Metro automatically updates the cache to account for the custom transform options.
isServer: options.customTransformOptions?.environment === 'node',
// Pass the engine to babel so we can automatically transpile for the correct
// target environment.
engine: options.customTransformOptions?.engine,
},
ast: true,

Expand Down
2 changes: 2 additions & 0 deletions packages/babel-preset-expo/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,8 @@

### 🎉 New features

- Automatically optimize transformations based on Hermes usage. ([#24672](https://github.com/expo/expo/pull/24672) by [@EvanBacon](https://github.com/EvanBacon))

### 🐛 Bug fixes

### 💡 Others
Expand Down
2 changes: 1 addition & 1 deletion packages/babel-preset-expo/build/index.d.ts

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

10 changes: 8 additions & 2 deletions packages/babel-preset-expo/build/index.js

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,59 @@ exports[`metro uses the platform's react-native import 1`] = `
var _reactNative=require("react-native");"
`;

exports[`metro+hermes aliases @expo/vector-icons 1`] = `
"
require("@expo/vector-icons");
require("@expo/vector-icons");
imposter.require('react-native-vector-icons');
imposter.import('react-native-vector-icons');"
`;

exports[`metro+hermes composes with babel-plugin-module-resolver 1`] = `
"
require("react-native");
require("@expo/vector-icons");"
`;

exports[`metro+hermes supports automatic JSX runtime 1`] = `
"Object.defineProperty(exports,"__esModule",{value:true});exports.default=App;
var _reactNative=require("react-native");var _jsxRuntime=require("react/jsx-runtime");
function App(){
return(0,_jsxRuntime.jsx)(_reactNative.View,{children:(0,_jsxRuntime.jsx)(_reactNative.Text,{children:"Hello World"})});
}"
`;

exports[`metro+hermes supports classic JSX runtime 1`] = `
"Object.defineProperty(exports,"__esModule",{value:true});exports.default=App;
var _reactNative=require("react-native");
function App(){
return React.createElement(_reactNative.View,null,React.createElement(_reactNative.Text,null,"Hello World"));
}"
`;

exports[`metro+hermes supports disabling reanimated 1`] = `
"
function someWorklet(greeting){
'worklet';
console.log("Hey I'm running on the UI thread");
}"
`;

exports[`metro+hermes supports reanimated worklets 1`] = `
"var _worklet_2797951844470_init_data={code:"function someWorklet(greeting) {\\n console.log(\\"Hey I'm running on the UI thread\\");\\n}",location:"[mock]/worklet.js",sourceMap:"{\\"version\\":3,\\"mappings\\":\\"AAAA;EAAAA;AACA\\",\\"names\\":[\\"console\\"],\\"sources\\":[\\"[mock]/worklet.js\\"]}"};var
someWorklet=function(){var _e=[new global.Error(),1,-27];var _f=function(greeting){

console.log("Hey I'm running on the UI thread");
};_f._closure={};_f.__initData=_worklet_2797951844470_init_data;_f.__workletHash=2797951844470;_f.__stackDetails=_e;_f.__version="3.3.0";return _f;}();"
`;

exports[`metro+hermes transpiles non-standard exports 1`] = `"Object.defineProperty(exports,"__esModule",{value:true});exports.default=void 0;var _default=_interopRequireWildcard(require("./Animated"));exports.default=_default;function _getRequireWildcardCache(nodeInterop){if(typeof WeakMap!=="function")return null;var cacheBabelInterop=new WeakMap();var cacheNodeInterop=new WeakMap();return(_getRequireWildcardCache=function(nodeInterop){return nodeInterop?cacheNodeInterop:cacheBabelInterop;})(nodeInterop);}function _interopRequireWildcard(obj,nodeInterop){if(!nodeInterop&&obj&&obj.__esModule){return obj;}if(obj===null||typeof obj!=="object"&&typeof obj!=="function"){return{default:obj};}var cache=_getRequireWildcardCache(nodeInterop);if(cache&&cache.has(obj)){return cache.get(obj);}var newObj={};var hasPropertyDescriptor=Object.defineProperty&&Object.getOwnPropertyDescriptor;for(var key in obj){if(key!=="default"&&Object.prototype.hasOwnProperty.call(obj,key)){var desc=hasPropertyDescriptor?Object.getOwnPropertyDescriptor(obj,key):null;if(desc&&(desc.get||desc.set)){Object.defineProperty(newObj,key,desc);}else{newObj[key]=obj[key];}}}newObj.default=obj;if(cache){cache.set(obj,newObj);}return newObj;}"`;

exports[`metro+hermes uses the platform's react-native import 1`] = `
"
var _reactNative=require("react-native");"
`;

exports[`webpack aliases @expo/vector-icons 1`] = `
"
import"@expo/vector-icons";
Expand Down