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(metro-config)!: enable experimentalImportSupport by default #30005

Draft
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

EvanBacon
Copy link
Contributor

@EvanBacon EvanBacon commented Jun 25, 2024

Why

In SDK 52 and greater, we should try to enable experimentalImportSupport by default. This feature converts import/export syntax to use Metro runtime equivalents in a secondary Babel pass. This aligns with how Metro is used internally at Meta, and fixes some broken behavior in the Metro transform pipeline.

When experimentalImportSupport is disabled, the babel plugins @babel/plugin-transform-modules-commonjs and @babel/plugin-proposal-export-default-from are used to emulate the behavior but with @babel/runtime equivalents. This leads to substantially more imports and breaks the "use strict" directive injection since all modules are viewed as commonjs.

When this flag is enabled lazyImports is silently ignored. Which raises some other questions. It appears we currently discard the internal list of lazy imports by React Native. I'd imagine the RN list is there to emulate a subset of inlineRequires behavior. When bundling a React Native iOS app however, it doesn't appear that any of the modules in the RN list are ever invoked. This seems like an artifact of when React Native migrated from using Haste-style imports View to standard imports like ./View.

For us, the only notable change is that imports on expo, expo-asset, and expo-task-manager will no longer default to being lazily initialized. expo and expo-assets should never have been in this list since they both contain root side-effects that must be imported at an exact time. Not sure if anything breaks by moving expo-task-manager, can't imagine how it might.

Syntax changes

  • Redeclaring commonjs globals in the top scope such as module (like we do in expo-maps) will not work anymore.

Test Plan

  • Updated expo-dev-launcher.
  • Updated tests.
  • This feature has been out in the wild for a long time so it's pretty well used.

@expo-bot expo-bot added the bot: suggestions ExpoBot has some suggestions label Jun 25, 2024
@expo-bot
Copy link
Collaborator

expo-bot commented Jun 25, 2024

The Pull Request introduced fingerprint changes against the base commit: db6f679

Fingerprint diff
[
  {
    "type": "dir",
    "filePath": "../../packages/expo-dev-launcher",
    "reasons": [
      "expoAutolinkingIos",
      "expoAutolinkingAndroid"
    ],
    "hash": "bec35d3b4a8ed9bf794c217b4e7b6dea2d0019bb"
  }
]

Generated by PR labeler 🤖

@expo-bot
Copy link
Collaborator

Hi there! 👋 I'm a bot whose goal is to ensure your contributions meet our guidelines.

I've found some issues in your pull request that should be addressed (click on them for more details) 👇

⚠️ Suggestion: Missing changelog entries


Your changes should be noted in the changelog. Read Updating Changelogs guide and consider adding an appropriate entry to the following changelogs:


Generated by ExpoBot 🤖 against 75831ae

EvanBacon added a commit that referenced this pull request Jun 27, 2024
…0010)

# Why

- We are currently hiding this issue but it becomes clear when we
support ESM better #30005

---------

Co-authored-by: Expo Bot <[email protected]>
github-merge-queue bot pushed a commit to software-mansion/react-native-reanimated that referenced this pull request Jun 28, 2024
<!-- Thanks for submitting a pull request! We appreciate you spending
the time to work on these changes. Please follow the template so that
the reviewers can easily understand what the code changes affect. -->

## Summary

React Native Babel preset uses a loose plugin to convert imports to
commonjs, we're investigating switching to a more standard approach in
Expo CLI here expo/expo#30005 which aligns with
how Metro is used at Meta.
 
When running on the kitchen sink, I found that there was an invalid
expression in reanimated where it exports null and then destructures
null. This error didn't occur previously because the commonjs plugin
deferred access to the null object until later.

**Before**

```js
var _Math = _$$_REQUIRE(_dependencyMap[0]);

// Later ...

_Math.add
```

This coincidentally didn't throw because the deferred code is never
accessed.

**After**

```js
var add = _$$_REQUIRE(_dependencyMap[0]).add;
```

This throws because the `null` is accessed when the module is loaded.

## Test plan

Bundle a Metro web project with experimentalImportSupport enabled:

```js
config.transformer.getTransformOptions = async () => ({
  transform: {
    experimentalImportSupport: true,
    inlineRequires: false,
  },
});
```

Then run `npx serve dist` -> Error was there but not anymore.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet

2 participants