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

Use babel runtime instead of relying on global babelHelpers and regenerator #198

Closed
wants to merge 2 commits into from

Conversation

janicduplessis
Copy link
Contributor

Summary

The RN transformer currently relies on the enviroment providing babelHelpers and regeneratorRuntime as globals by using 'babel-external-helpers'. This wasn't really a problem before since helpers were stable and we could maintain our copy easily but it seems like there are more now with babel 7 and it makes sense to include only those used by the app.

This is exactly what @babel/transform-runtime does. It will alias all helpers and calls to regeneratorRuntime to files in the @babel/runtime package.

This will solve issues like this facebook/react-native#20150 caused by missing babelHelpers. This solution also avoids bloating babelHelpers to fix OSS issues like the one linked before.

Test plan

  • Updated tests so they all pass.
  • Tested that it actually works by applying the changes locally in an RN app.
  • Added a test for async functions, to make sure regenerator is aliased properly and doesn't depend on the global.
  • Made sure require-test.js still fails if the require implementation contains babel helpers (by adding an empty class in the file).

@facebook-github-bot facebook-github-bot added the CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed. label Jul 12, 2018
@janicduplessis
Copy link
Contributor Author

janicduplessis commented Jul 12, 2018

Not sure how we should go about including the @babel/runtime dependency, it could be added here or in RN, I think RN makes more sense since that is where the babelHelpers / regeneratorRuntime are defined atm.

If this makes sense I will make a PR on RN that adds @babel/runtime and removes babelHelpers and the regenerator global.

@codecov-io
Copy link

codecov-io commented Jul 12, 2018

Codecov Report

Merging #198 into master will decrease coverage by <.01%.
The diff coverage is 100%.

Impacted file tree graph

@@            Coverage Diff             @@
##           master     #198      +/-   ##
==========================================
- Coverage   84.24%   84.24%   -0.01%     
==========================================
  Files         134      134              
  Lines        4406     4405       -1     
  Branches      691      691              
==========================================
- Hits         3712     3711       -1     
  Misses        614      614              
  Partials       80       80
Impacted Files Coverage Δ
...etro-react-native-babel-preset/src/configs/main.js 100% <ø> (ø) ⬆️
packages/metro/src/reactNativeTransformer.js 70.9% <100%> (-0.52%) ⬇️

Continue to review full report at Codecov.

Legend - Click here to learn more
Δ = absolute <relative> (impact), ø = not affected, ? = missing data
Powered by Codecov. Last update 3e5833b...8ed955a. Read the comment docs.

@@ -15,7 +15,6 @@
"dependencies": {
"@babel/core": "7.0.0-beta.48",
"@babel/generator": "7.0.0-beta.48",
"@babel/helper-remap-async-to-generator": "7.0.0-beta.48",
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I was checking deps and those were not used in the metro package.

@@ -28,7 +27,6 @@ type ModuleES6 = {__esModule?: boolean, default?: {}};

const cacheKeyParts = [
fs.readFileSync(__filename),
require('babel-plugin-external-helpers/package.json').version,
Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we still keep the babel version as part of that cache key?

@rafeca
Copy link
Contributor

rafeca commented Jul 13, 2018

Thanks for doing this! This looks like the right approach, much more robust 👍 I think it's better to have this in metro tbh.

I guess that you're going to remove https://github.com/facebook/react-native/blob/master/rn-get-polyfills.js#L21 once this change gets propagated to RN?

I'm going to import this PR to our internal systems to check that it does not break anything or it does not cause any build size regression

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@rafeca has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@janicduplessis
Copy link
Contributor Author

janicduplessis commented Jul 13, 2018

@rafeca Yes we’ll be able to remove that as well as the global regenerator we add in InitializeCore (https://github.com/facebook/react-native/blob/master/Libraries/Core/InitializeCore.js#L90).

@newyankeecodeshop
Copy link
Contributor

This looks great! Will this make it possible for RN apps which target a modern JavaScriptCore (e.g. iOS 10.3+) to use a custom babel config that does not even need the regenerator runtime? (because generator functions are natively supported?)

@janicduplessis
Copy link
Contributor Author

It will help since RN won’t always bundle regeneratorRuntime, it will only be added if babel needs it (this means it won’t add it when targeting modern JSC with a custom babel config).

@janicduplessis
Copy link
Contributor Author

@rafeca Did you have a chance to look at this?

@janicduplessis janicduplessis force-pushed the babel-runtime branch 2 times, most recently from d717970 to 3ae32a5 Compare August 3, 2018 04:36
@newyankeecodeshop
Copy link
Contributor

Any movement on this? It looks like a great addition to decouple babel dependencies from React Native itself.

@ItsNoHax
Copy link

Will this fix the whole regeneratorRuntime missing issue?

@loganfsmyth
Copy link

loganfsmyth commented Sep 3, 2018

@janicduplessis Babel maintainer here. This would be great overall, since I think external-helpers isn't that useful now that @babel/runtime is trimmed down.

I'll also say that the 7.0.0 external-helpers transform also accepts the same whitelist option that babel.buildExternalHelpers does, https://github.com/babel/babel/blob/master/packages/babel-plugin-external-helpers/src/index.js#L10, so if there are issues with getting this landed in the short term, a quick fix would be to take the list of helpers that RN builds and pass it to the transform. That way it will fall back to injecting the helpers into each individual file, instead of inserting references to helpers that don't exist.

I'd expect this to become more and more of a problem since we'll likely add new helpers over 7.x's lifetime and we assume that, if you inject a reference, you're saying that you actually have that helper available.

@simonwang6666
Copy link

Any movement of this?

@rafeca
Copy link
Contributor

rafeca commented Sep 8, 2018

Hey folks, when I tried to import this PR it caused a few errors in our internal builds, I'm going to try again next week (probably tweaking it a bit) and see if I can squeeze it in 😃

@janicduplessis
Copy link
Contributor Author

@rafeca Cool, I just rebased on master to fix conflicts.

Copy link
Contributor

@facebook-github-bot facebook-github-bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

rafeca has imported this pull request. If you are a Facebook employee, you can view this diff on Phabricator.

@simonwang6666
Copy link

@rafeca Will this cherry-picked in next release?

@janicduplessis
Copy link
Contributor Author

@wangshangming This has not been merged to master yet, when it does we'll know when it will make it in a release.

@rafeca
Copy link
Contributor

rafeca commented Sep 14, 2018

I'm still dealing with some internal issues in order to be able to merge this PR, but making slow but steady progress.

To give some context, these are the two main issues found:

  • The current [babelHelpers](https://github.com/facebook/react-native/blob/master/Libraries/polyfills/babelHelpers.js) that we use are from babel-7.0.0-beta.47. Between that beta and latest stable differ slightly in behaviour, making some of our tests fail.
  • Because @babel/runtime adds a bunch of requires instead of calling the static methods, tests that use jest.autoMock() stop working since they also mock the runtime. Unfortunately we still have lots of old tests with that so I'm dealing with them.

Lastly, once I get everything working I'll do some performance measurement to check that the startup times of RN apps does not regress (adding new require calls adds a small overhead, and this together with inline requires could cause perf regressions).

I'll keep you informed

@LinusU
Copy link
Contributor

LinusU commented Sep 17, 2018

[...] adding new require calls [...]

This might not be relevant at all, but just so you know, you can pass useESModules: true to @babel/plugin-transform-runtime in order to use import instead of require. That could potentially be optimized better...

facebook-github-bot pushed a commit to facebook/react-native that referenced this pull request Sep 21, 2018
…erator (#198)

Summary:
**Summary**

The RN transformer currently relies on the enviroment providing babelHelpers and regeneratorRuntime as globals by using 'babel-external-helpers'. This wasn't really a problem before since helpers were stable and we could maintain our copy easily but it seems like there are more now with babel 7 and it makes sense to include only those used by the app.

This is exactly what babel/transform-runtime does. It will alias all helpers and calls to regeneratorRuntime to files in the babel/runtime package.

This will solve issues like this #20150 caused by missing babelHelpers. This solution also avoids bloating babelHelpers to fix OSS issues like the one linked before.

**Test plan**

- Updated tests so they all pass.
- Tested that it actually works by applying the changes locally in an RN app.
- Added a test for async functions, to make sure regenerator is aliased properly and doesn't depend on the global.
- Made sure require-test.js still fails if the require implementation contains babel helpers (by adding an empty class in the file).
Pull Request resolved: facebook/metro#198

Reviewed By: mjesun

Differential Revision: D8833903

Pulled By: rafeca

fbshipit-source-id: 7081f769f288ab358ba89ae8ee72a513bb12e225
grabbou pushed a commit to facebook/react-native that referenced this pull request Oct 2, 2018
…erator (#198)

Summary:
**Summary**

The RN transformer currently relies on the enviroment providing babelHelpers and regeneratorRuntime as globals by using 'babel-external-helpers'. This wasn't really a problem before since helpers were stable and we could maintain our copy easily but it seems like there are more now with babel 7 and it makes sense to include only those used by the app.

This is exactly what babel/transform-runtime does. It will alias all helpers and calls to regeneratorRuntime to files in the babel/runtime package.

This will solve issues like this #20150 caused by missing babelHelpers. This solution also avoids bloating babelHelpers to fix OSS issues like the one linked before.

**Test plan**

- Updated tests so they all pass.
- Tested that it actually works by applying the changes locally in an RN app.
- Added a test for async functions, to make sure regenerator is aliased properly and doesn't depend on the global.
- Made sure require-test.js still fails if the require implementation contains babel helpers (by adding an empty class in the file).
Pull Request resolved: facebook/metro#198

Reviewed By: mjesun

Differential Revision: D8833903

Pulled By: rafeca

fbshipit-source-id: 7081f769f288ab358ba89ae8ee72a513bb12e225
aleclarson pushed a commit to aleclarson/metro that referenced this pull request Mar 26, 2019
…erator (facebook#198)

Summary:
**Summary**

The RN transformer currently relies on the enviroment providing babelHelpers and regeneratorRuntime as globals by using 'babel-external-helpers'. This wasn't really a problem before since helpers were stable and we could maintain our copy easily but it seems like there are more now with babel 7 and it makes sense to include only those used by the app.

This is exactly what babel/transform-runtime does. It will alias all helpers and calls to regeneratorRuntime to files in the babel/runtime package.

This will solve issues like this facebook/react-native#20150 caused by missing babelHelpers. This solution also avoids bloating babelHelpers to fix OSS issues like the one linked before.

**Test plan**

- Updated tests so they all pass.
- Tested that it actually works by applying the changes locally in an RN app.
- Added a test for async functions, to make sure regenerator is aliased properly and doesn't depend on the global.
- Made sure require-test.js still fails if the require implementation contains babel helpers (by adding an empty class in the file).
Pull Request resolved: facebook#198

Reviewed By: mjesun

Differential Revision: D8833903

Pulled By: rafeca

fbshipit-source-id: 7081f769f288ab358ba89ae8ee72a513bb12e225
t-nanava pushed a commit to microsoft/react-native-macos that referenced this pull request Jun 17, 2019
…erator (#198)

Summary:
**Summary**

The RN transformer currently relies on the enviroment providing babelHelpers and regeneratorRuntime as globals by using 'babel-external-helpers'. This wasn't really a problem before since helpers were stable and we could maintain our copy easily but it seems like there are more now with babel 7 and it makes sense to include only those used by the app.

This is exactly what babel/transform-runtime does. It will alias all helpers and calls to regeneratorRuntime to files in the babel/runtime package.

This will solve issues like this facebook#20150 caused by missing babelHelpers. This solution also avoids bloating babelHelpers to fix OSS issues like the one linked before.

**Test plan**

- Updated tests so they all pass.
- Tested that it actually works by applying the changes locally in an RN app.
- Added a test for async functions, to make sure regenerator is aliased properly and doesn't depend on the global.
- Made sure require-test.js still fails if the require implementation contains babel helpers (by adding an empty class in the file).
Pull Request resolved: facebook/metro#198

Reviewed By: mjesun

Differential Revision: D8833903

Pulled By: rafeca

fbshipit-source-id: 7081f769f288ab358ba89ae8ee72a513bb12e225
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
CLA Signed This label is managed by the Facebook bot. Authors need to sign the CLA before a PR can be reviewed.
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants