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

[0.56][RELEASE] Bundler cuts off some used babel helpers in release build (decorators issue) #20150

Closed
3 tasks done
farwayer opened this issue Jul 11, 2018 · 45 comments
Closed
3 tasks done
Labels
Impact: Regression Describes a behavior that used to work on a prior release, but stopped working recently. JavaScript Platform: Linux Building on Linux. Resolution: Locked This issue was locked by the bot. Tech: Bundler 📦 This issue is related to the bundler (Metro, Haul, etc) used.

Comments

@farwayer
Copy link
Contributor

farwayer commented Jul 11, 2018

Environment

  React Native Environment Info:
    System:
      OS: Linux 4.17 Arch Linux rolling
      CPU: x64 Intel(R) Core(TM) i7-3770K CPU @ 3.50GHz
      Memory: 1.06 GB / 7.47 GB
      Shell: 5.5.1 - /bin/zsh
    Binaries:
      Node: 10.6.0 - /usr/bin/node
      Yarn: 1.7.0 - /usr/bin/yarn
      npm: 6.1.0 - /usr/bin/npm
      Watchman: 4.9.0 - /usr/bin/watchman
    SDKs:
      Android SDK:
        Build Tools: 23.0.1, 23.0.3, 25.0.2, 26.0.1, 26.0.2, 27.0.0, 27.0.3
        API Levels: 22, 23, 24, 25, 26, 27
    npmPackages:
      react: ^16.4.1 => 16.4.1 
      react-native: ^0.56.0 => 0.56.0 
    npmGlobalPackages:
      react-native-cli: 2.0.1
      react-native-git-upgrade: 0.2.7

Description

Bundler cuts off some used babel helpers in release build. Look like by mistake while optimization.
For example initializerDefineProperty and applyDecoratedDescriptor needed by @babel/proposal-decorators.

2018-07-10-144351_393x122_scrot

Reproducible Demo

{
  "presets": ["react-native"],
  "plugins": [
    ["@babel/proposal-decorators", {"legacy": true}]
  ]
}
"devDependencies": {
  "@babel/plugin-proposal-decorators": "7.0.0-beta.47"
}
function test() {}

class Test {
  @test val;
}
undefined is not a function (evaluating 'babelHelpers.applyDecoratedDescriptor(_class.prototype, "val", [test], {
    enumerable: true,
    initializer: null
  })')

Workaround 1 (can have side effects)

Be care because this workaround can bring some errors with external libs.

For RN 0.56:

yarn add --dev @babel/plugin-transform-runtime@7.0.0-beta.47

.babelrc

{
  "presets": ["react-native"],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"legacy": true}],
    ["@babel/plugin-transform-runtime", {
      "polyfill": false,
      "regenerator": false
    }]
  ]
}

For RN 0.57:

yarn add --dev @babel/plugin-transform-runtime@7.0.0

.babelrc

{
  "presets": ["module:metro-react-native-babel-preset"],
  "plugins": [
    ["@babel/plugin-proposal-decorators", {"legacy": true}],
    ["@babel/plugin-transform-runtime", {
      "polyfill": false,
      "regenerator": false
    }]
  ]
}

Workaround 2

Move app initialization to some other file (I'm using src/ dir for source) and update root index.js file.
N.B. require main app code instead of import because require executed after.

For RN 0.56:

yarn add @babel/runtime@7.0.0-beta.47

Root index.js

import applyDecoratedDescriptor from '@babel/runtime/helpers/es6/applyDecoratedDescriptor'
import initializerDefineProperty from '@babel/runtime/helpers/es6/initializerDefineProperty'

Object.assign(babelHelpers, {
  applyDecoratedDescriptor,
  initializerDefineProperty,
});

require('./src');

For RN 0.57:

yarn add @babel/runtime@7.0.0

Root index.js

import applyDecoratedDescriptor from '@babel/runtime/helpers/esm/applyDecoratedDescriptor'
import initializerDefineProperty from '@babel/runtime/helpers/esm/initializerDefineProperty'

Object.assign(babelHelpers, {
  applyDecoratedDescriptor,
  initializerDefineProperty,
});

require('./src');
@thientnc-ibl
Copy link

@farwayer
Where can this code be placed?

import initializerDefineProperty from '@babel/runtime/helpers/es6/initializerDefineProperty'
Object.assign(babelHelpers, {applyDecoratedDescriptor, initializerDefineProperty});
require('./src');```

@farwayer
Copy link
Contributor Author

@thientnc-ibl This is root index.js file. Put your app code in some other file and require() it at the end of root index.

@thientnc-ibl
Copy link

The RELEASE build is OK now, bravo... We should write this work around to React native 0.56 doc

@janicduplessis
Copy link
Contributor

RN includes its own version of babel-helpers but it does not include the applyDecoratedDescriptor. Facebook probably doesn't use decorators so this went unnoticed. I'll see if we can include it to get this fixed, in the meantime the workaround is valid.

@folofse
Copy link

folofse commented Jul 19, 2018

I was stuck with this problem in my release build until I manually recreated the android bundle. I thought the bundle was recreated automaticly on release. But I had to run the terminal code after each change: 'react-native bundle --platform android --dev false --entry-file index.android.js --bundle-output android/app/src/main/assets/index.android.bundle --assets-dest android/app/src/main/res/'

@hvaoc
Copy link

hvaoc commented Jul 19, 2018

Faced the same error with React Native 0.56, used combination of resolutions proposed including the Workaround 2 by @farwayer above.

Steps that I followed:

  1. Clean up dependencies
rm -rf node_modules
yarn
yarn upgrade react-native@0.56.0
  1. @farwayer suggested workaround 2

Check the version of babel components used with React Native by checking the yarn.lock or package-lock.json and match @babel/runtime with the same version. React native 0.56 is using babel 7.0.0-beta.47.

yarn add @babel/runtime@7.0.0-beta.47

index.js

import {AppRegistry} from 'react-native'


// RN 0.56 Release version crashes
// import App from './src/App'
// AppRegistry.registerComponent('MyApp', () => App)

// Workaround: RN 0.56 Release version crashes
// Sources:
//      https://github.com/facebook/react-native/issues/19827
//      https://github.com/facebook/react-native/issues/20150

import applyDecoratedDescriptor from '@babel/runtime/helpers/es6/applyDecoratedDescriptor'
import initializerDefineProperty from '@babel/runtime/helpers/es6/initializerDefineProperty'

Object.assign(babelHelpers, {applyDecoratedDescriptor, initializerDefineProperty})

// Your main app code is in /src/index.js
AppRegistry.registerComponent('MyApp', () => require('./src').default)

Tested iOS / Android - Debug and Release version on Simulators and Devices. - All of them are working fine.

Note: I am also using decorators for MobX and custom .babelrc

package.json

{
  "name": "MyApp",
  "version": "0.0.1",
  "dependencies": {
    "@babel/plugin-proposal-decorators": "7.0.0-beta.47",
    "@babel/runtime": "7.0.0-beta.47",
    "mobx": "^5.0.3",
    "mobx-react": "^5.2.3",
    "react": "16.4.1",
    "react-native": "0.56.0"
  },
  "devDependencies": {
    "babel-jest": "23.4.0",
    "babel-preset-react-native": "^5",
    "flow-bin": "^0.76.0",
    "jest": "^23.4.1",
    "jsc-android": "^224109.0.0",
    "react-native-cli": "^2.0.1",
    "react-test-renderer": "16.4.1"
  },
  "jest": {
    "preset": "react-native"
  }
}

.babelrc

{
  "presets": [
    "react-native"
  ],
  "plugins": [
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ]
  ]
}

@scriptum
Copy link

With decorators plugin jest is broken too:

  ● Test suite failed to run

    TypeError: babelHelpers.applyDecoratedDescriptor is not a function

@mehulmpt
Copy link

Your solution works flawlessly @farwayer. My react-native-vector-icons package was broken with the approach I was trying earlier and this one works fine with it too! +1

@csotiriou
Copy link

This error also exists in React Native 0.57 rc3.

@164738777
Copy link

This error also exists in React Native 0.57 rc3.
+1

@lxcid
Copy link

lxcid commented Sep 1, 2018

In metro-react-native-babel-preset, it is stated that @babel/plugin-transform-flow-strip-types need to be before @babel/plugin-proposal-class-properties.

the flow strip types plugin must go BEFORE class properties! there'll be a test case that fails if you don't.

https://github.com/facebook/metro/blob/579b12974d13c7f02b2c58540ce8fddcb6a3e423/packages/metro-react-native-babel-preset/src/configs/main.js#L19-L21

This kinda explain why flow is affecting the babel output as describe around the issue…

If you provide your own plugins, it get applied first before presets, as described in Plugin Ordering section at https://babeljs.io/docs/en/plugins/#plugin-ordering

So, if you need decorators, you will have to place @babel/plugin-proposal-decorators above @babel/plugin-proposal-class-properties in plugins, which get executed first, thus not applying the @babel/plugin-transform-flow-strip-types, See https://babeljs.io/docs/en/next/babel-plugin-proposal-decorators.html

The fix for me is to add @babel/plugin-transform-flow-strip-types before the 2 other plugins…

{
  "plugins": [
    [
      "@babel/plugin-transform-flow-strip-types"
    ],
    [
      "@babel/plugin-proposal-decorators",
      {
        "legacy": true
      }
    ],
    [
      "@babel/plugin-proposal-class-properties",
      {
        "loose": true
      }
    ]
  ],
}

@rborn
Copy link

rborn commented Sep 5, 2018

For me none of the above solutions/workarounds work.
I also tried to upgrade to 0.57 but no luck.

@rborn
Copy link

rborn commented Sep 6, 2018

SOLVED 🎉, thanks to @Amnesthesia @jrnk ❤️ oblador/react-native-vector-icons#801 (comment)

Tested both ios/android debug/release (didn't upload to stores though but delivered with TestFairy so it should be just fine)

@farwayer farwayer changed the title [0.56][RELEASE] Bundler cuts off some used babel helpers in release build by mistake [0.56][RELEASE] Bundler cuts off some used babel helpers in release build (decorators issue) Sep 18, 2018
@chussum
Copy link

chussum commented Sep 19, 2018

Thank you guys!! You guys were save me! :) 👍
Thanks!! (__)

facebook-github-bot pushed a commit to facebook/metro that referenced this issue 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 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: #198

Reviewed By: mjesun

Differential Revision: D8833903

Pulled By: rafeca

fbshipit-source-id: 7081f769f288ab358ba89ae8ee72a513bb12e225
facebook-github-bot pushed a commit that referenced this issue 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
@rknell

This comment has been minimized.

@janicduplessis
Copy link
Contributor

@rknell Sorry you are feeling this way. This took a long time to fix since it isn't a hacky patch and required major changes in the way RN handles babel helpers so we don't rely on manually adding them anymore.

A patch to move from global babelHelpers to @babel/runtime landed a few days ago, with a follow up to remove the globals completely from RN that should land soon.

Thanks for you patience on this one.

@bzeeman

This comment has been minimized.

grabbou pushed a commit that referenced this issue 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
@shinriyo
Copy link

shinriyo commented Oct 7, 2018

Did you resolve?

2018-10-07 16:35:58.532 [error][tid:com.facebook.react.JavaScript] undefined is not a function (near '...babelHelpers.applyDecoratedDescriptor...')

@csotiriou
Copy link

To be honest, I had to hardcode versions beta.47 of the relevant babel packages in order to get it to work. Upgrading to 7.1.2 didn't help.

@pppluto
Copy link

pppluto commented Nov 2, 2018

for me I need "@babel/core": "^7.0.0" for android

@Fsarmento
Copy link

This issue seams to be solved in 0.57.4 (60b05ca).

We can go back to:

import { AppRegistry } from 'react-native';
import App from './App';

AppRegistry.registerComponent('myApp', () => App);

@Sushant-Sardeshpande
Copy link

Sushant-Sardeshpande commented Mar 6, 2019

Getting the same on updating from 0.55 to 0.58.6
Did not get this on the first package install but the next time I did it, getting it ever since

Edit: For me, just a --reset-cache for packager solved it, been working with a copy using 0.55 as well, not sure if that created an issue the second time around....

@AdamGerthel
Copy link

AdamGerthel commented Mar 26, 2019

I've tried to understand the workarounds here and if they're still needed or not. I'm running RN using Expo v32.0, and I'm heavily invested in decorators (due to MobX), and I'm getting this error when trying to run the production version.

What do I do? I'm not using AppRegistry and I never have before either. Is that a requirement to fix this? How do I use @babel/runtime?

Update: Finally got it up and running again. Not entirely sure what fixed it in the end, but I upgraded from Babel 6 -> 7 and this is what my babel.config.js looks like:

module.exports = function(api) {
  api.cache(true)

  return {
    presets: ['babel-preset-expo'],
    plugins: [
      ['@babel/plugin-transform-react-jsx-source'],
      ['@babel/plugin-proposal-decorators', { legacy: true }]
    ]
  }
}

I also cleared Expo cache multiple times (expo r -c)

aleclarson pushed a commit to aleclarson/metro that referenced this issue 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 issue 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
@facebook facebook locked as resolved and limited conversation to collaborators Sep 18, 2019
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Sep 18, 2019
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Impact: Regression Describes a behavior that used to work on a prior release, but stopped working recently. JavaScript Platform: Linux Building on Linux. Resolution: Locked This issue was locked by the bot. Tech: Bundler 📦 This issue is related to the bundler (Metro, Haul, etc) used.
Projects
None yet
Development

No branches or pull requests