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

transform-runtime regression, not requiring _objectSpread helper #10261

Closed
fabiomcosta opened this issue Jul 24, 2019 · 12 comments · May be fixed by #10325
Closed

transform-runtime regression, not requiring _objectSpread helper #10261

fabiomcosta opened this issue Jul 24, 2019 · 12 comments · May be fixed by #10325
Labels
Has PR i: bug outdated A closed issue/PR that is archived due to age. Recommended to make a new issue

Comments

@fabiomcosta
Copy link
Contributor

fabiomcosta commented Jul 24, 2019

Bug Report

Current Behavior
The objectSpread is not being transformed by runtime-transform into a require to the respective helper. See REPL link.
I've also setup a project to make it easy to show this issue, the instructions are on the README file, see https://github.com/fabiomcosta/babel_transform_runtime_helpers_bug
On that project you'll notice that @babel/core v7.0.0 used to behave properly, and the regression started happening on v7.0.1.
Note that I'm mentioning transform-runtime because that's the plugin that actually activates this transform, but the issue seems to be inside @babel/core (see the repro project).

Input Code
REPL

If the issue hasn't been fixed yet, you'll see that _objectSpread didn't become a require from its respective helper:

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _defineProperty2 = _interopRequireDefault(require("@babel/runtime/helpers/defineProperty"));

function ownKeys(object, enumerableOnly) { var keys = Object.keys(object); if (Object.getOwnPropertySymbols) { var symbols = Object.getOwnPropertySymbols(object); if (enumerableOnly) symbols = symbols.filter(function (sym) { return Object.getOwnPropertyDescriptor(object, sym).enumerable; }); keys.push.apply(keys, symbols); } return keys; }

function _objectSpread(target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i] != null ? arguments[i] : {}; if (i % 2) { ownKeys(source, true).forEach(function (key) { (0, _defineProperty2["default"])(target, key, source[key]); }); } else if (Object.getOwnPropertyDescriptors) { Object.defineProperties(target, Object.getOwnPropertyDescriptors(source)); } else { ownKeys(source).forEach(function (key) { Object.defineProperty(target, key, Object.getOwnPropertyDescriptor(source, key)); }); } } return target; }

var x = _objectSpread({}, {});

Expected behavior/code
The expected behavior for that is what used to happen on v7.0.0, the following code:

const x = { ...{} };

Should transpile to:

"use strict";

var _interopRequireDefault = require("@babel/runtime/helpers/interopRequireDefault");

var _objectSpread2 = _interopRequireDefault(require("@babel/runtime/helpers/objectSpread2"));

var x = (0, _objectSpread2.default)({}, {});

Environment

  • Babel version(s): 7.0.1 and up
  • Node/npm version: I used Node 10, but I'm not sure this matter that much for this report
  • OS: OSX 10.14.5
  • Monorepo: unrelated
  • How you are using Babel: cli
@babel-bot
Copy link
Collaborator

Hey @fabiomcosta! We really appreciate you taking the time to report an issue. The collaborators on this project attempt to help as many people as possible, but we're a limited number of volunteers, so it's possible this won't be addressed swiftly.

If you need any help, or just have general Babel or JavaScript questions, we have a vibrant Slack community that typically always has someone willing to help. You can sign-up here for an invite.

@JLHwung
Copy link
Contributor

JLHwung commented Jul 24, 2019

You could specify a helper version on plugin-transform

{
  plugins: [["transform-runtime", {
    "version": "7.5.0"
  }],
}

When it is not specified, babel will assume you are using @babel/helpers 7.0.0-beta.0. Some polyfills are not available at 7.0.0-beta.0, so babel would not try to replace inserted polyfill to a helper import. It is mean to preserve backward compatibility to old versions of @babel/helpers.

_objectSpread2 helper is available since 7.5.0, if you have upgraded @babel/helpers to 7.5.0, please specify the version field.

@nicolo-ribaudo I don't think it is smooth for those who keep @babel/core (implicitly upgraded @babel/helpers) up-to-dated. Could we detect the @babel/helpers version if version is not specified?

@sgomes
Copy link

sgomes commented Aug 5, 2019

This seems to be the actual root cause behind our recent increase in bundle size. When we upgraded to 7.5.5, the helpers were updated too (through a new transform-runtime version).

By keeping the configuration as it was, the ownKeys and objectSpread helpers (which seem to have had new versions released) started being bundled into the output file multiple times, rather than imported, as before, which even with minification and compression afterwards still resulted in a significantly larger bundle (around 3.8KB, in the case of one of our main chunks).

Adding the version explicitly, as @JLHwung recommended above, does appear to fix the issue, with the file size going back down and the import being used again.

If at all possible, I'd love if you could add autodetection as @JLHwung suggested, as in our case a simple upgrade produced a fairly complex issue to debug.

sgomes added a commit to Automattic/wp-calypso that referenced this issue Aug 8, 2019
With version 7.5.x of Babel, the object spread helper was updated to fix
some issues.

When we upgraded Babel to 7.5.5, it started trying to use the new helper
to perform object spreads. This would have been fine, since the relevant
package (transform-runtime) was part of the upgrade, but Babel
sadly assumes that its version is older, instead of auto-detecting.

This change explicitly indicates which version of the transform-runtime
we're using, fixing the issue. It unfortunately adds extra maintenance
overhead to Babel upgrades, but the Babel authors are considering adding
the aforemention auto-detection, at which point we could remove the
explicit definition.

See babel/babel#10261
pull bot pushed a commit to patilswapnilv/wp-calypso that referenced this issue Aug 12, 2019
* Prevent duplicate Babel object spread helpers.

With version 7.5.x of Babel, the object spread helper was updated to fix
some issues.

When we upgraded Babel to 7.5.5, it started trying to use the new helper
to perform object spreads. This would have been fine, since the relevant
package (transform-runtime) was part of the upgrade, but Babel
sadly assumes that its version is older, instead of auto-detecting.

This change explicitly indicates which version of the transform-runtime
we're using, fixing the issue. It unfortunately adds extra maintenance
overhead to Babel upgrades, but the Babel authors are considering adding
the aforemention auto-detection, at which point we could remove the
explicit definition.

See babel/babel#10261

* Add note to changelog.

* Add issue comment to Babel config too.
getdave pushed a commit to Automattic/wp-calypso that referenced this issue Aug 13, 2019
* Prevent duplicate Babel object spread helpers.

With version 7.5.x of Babel, the object spread helper was updated to fix
some issues.

When we upgraded Babel to 7.5.5, it started trying to use the new helper
to perform object spreads. This would have been fine, since the relevant
package (transform-runtime) was part of the upgrade, but Babel
sadly assumes that its version is older, instead of auto-detecting.

This change explicitly indicates which version of the transform-runtime
we're using, fixing the issue. It unfortunately adds extra maintenance
overhead to Babel upgrades, but the Babel authors are considering adding
the aforemention auto-detection, at which point we could remove the
explicit definition.

See babel/babel#10261

* Add note to changelog.

* Add issue comment to Babel config too.
getdave pushed a commit to Automattic/wp-calypso that referenced this issue Aug 13, 2019
* Prevent duplicate Babel object spread helpers.

With version 7.5.x of Babel, the object spread helper was updated to fix
some issues.

When we upgraded Babel to 7.5.5, it started trying to use the new helper
to perform object spreads. This would have been fine, since the relevant
package (transform-runtime) was part of the upgrade, but Babel
sadly assumes that its version is older, instead of auto-detecting.

This change explicitly indicates which version of the transform-runtime
we're using, fixing the issue. It unfortunately adds extra maintenance
overhead to Babel upgrades, but the Babel authors are considering adding
the aforemention auto-detection, at which point we could remove the
explicit definition.

See babel/babel#10261

* Add note to changelog.

* Add issue comment to Babel config too.
@csvn
Copy link

csvn commented Aug 13, 2019

@JLHwung Thanks a lot for your suggestion, it fixed my issue too. Though I can't see it documented on https://babeljs.io/docs/en/babel-plugin-transform-runtime#options. Is this intended?

As @sgomes said, I also found it hard to find the cause for why the inline helpers appeared. Is there somewhere where this is explained? And I don't really understand why the backwards compatibility is needed. I only have @babel/runtime specified in my package.json, which is in turn requiring the helpers, which I just upgraded to 7.5.5 (which produced the issue described here).

@JLHwung
Copy link
Contributor

JLHwung commented Aug 13, 2019

We are working on #10325 so that when version is not specified, we can produce a more helpful warning and offer guide to specify version.

why the inline helpers appeared

The helpers are inlined because transform-runtime doesn't know if they are included in babel/helpers. In this case, it will assume you are using babel/helpers 7.0.0-beta.0, which means every helper introduced later than 7.0.0-beta.0 will be inlined instead of require. Specifying a version field helps transform-runtime to generate imports of helpers.

why the backwards compatibility is needed

From what I have mentioned above, you can see that this mechanism ensures that transform-runtime 7.5.0 can work with babel/helpers 7.0.0-beta.0, but for developers keep babel/core up-to-dated with transform-runtime, the bundle size will be get larger. That's why we are working towards to a better solution.

@JLHwung JLHwung added the Has PR label Aug 13, 2019
@DavidWells
Copy link

I'm seeing the same issue @sgomes describes

The ownKeys and _objectSpread functions are being added to my bundle multiple times ownKeys$a, ownKeys$b etc. This added about 6kb to the total output.

image

Noticed this when updating from babel 7.2.2 to 7.5.4

I updated versions to fix this issue #10179

Thanks for your awesome work on babel by the way. You folks rock

@DavidWells
Copy link

DavidWells commented Aug 14, 2019

Confirmed pinning version to 7.5.5 and using @babel/plugin-transform-runtime shrank the bundle back to the original size.

DavidWells/analytics@3594c35#diff-26e31d5a6dff458a0b7db69a92db2308R15

Thanks @sgomes for the fix 😃

🚀 https://bundlephobia.com/result?p=analytics@0.1.19

@csvn
Copy link

csvn commented Aug 14, 2019

@JLHwung Thanks for you answers, that makes it clearer.

@sgomes
Copy link

sgomes commented Aug 14, 2019

Thanks @sgomes for the fix 😃

Oh, that's not my fix at all! That was @JLHwung helpfully debugging the issue for @fabiomcosta 🙂

instructure-gerrit pushed a commit to instructure/instructure-ui that referenced this issue Sep 9, 2019
because of babel/babel#10261 if you don't 
speficiy a version of @babel/helpers to use, it will default to 
7.0.0-beta.0 which doesn't have _objectSpread

TEST PLAN:
* Before checking this out, 
* run babel to transpile a file that uses
  object spread syntax, like `const foo = {...bar}`
* you should see inline _objectSpread helpers like what is currently
  on npm. see for example:
https://unpkg.com/browse/@instructure/ui-a11y@6.10.0/es/Dialog/index.js
  (See how that has a _objectSpread inlined in it?)

* with this checked out, 
* run yarn build
* Look at: packages/ui-a11y/es/Dialog/index.js
* it should not have an inline _objectSpread function, but should
  Instead have a line like
  import _objectSpread2 from "@babel/runtime/helpers/esm/objectSpread2"
  


Change-Id: I1a65ae85789848ad0702e43aafdc5580210942eb
Reviewed-on: https://gerrit.instructure.com/208612
Tested-by: Jenkins
Reviewed-by: Clay Diffrient <cdiffrient@instructure.com>
QA-Review: Daniel Sasaki <dsasaki@instructure.com>
QA-Review: Steve Jensen <sejensen@instructure.com>
Product-Review: Steve Jensen <sejensen@instructure.com>
Visual-Regression-Test: Steve Jensen <sejensen@instructure.com>
@jahed
Copy link

jahed commented Nov 5, 2019

This also affects the new useSpread option for JSX transforms introduced in 7.7.0.

For anyone still wondering what the fix is, use version which is currently undocumented:

['@babel/plugin-transform-runtime', {
  version: require('@babel/helpers/package.json').version
}]

@dcleao
Copy link

dcleao commented Dec 10, 2019

I've checked that specifying the "version" property solves the issue, when calling Babel directly to process each file.

However, it doesn't affect a build generated with Webpack and babel-loader...
I'm out of ideas :-(

Update 1: Specifically, this is happening for external modules, coming from node_modules. Local project code is requiring the helper.

Update 2: Solved. It's the same root issue, but it was already present in dependencies which were not being transpiled locally...

@nicolo-ribaudo
Copy link
Member

This is now documented at https://babeljs.io/docs/en/babel-plugin-transform-runtime#version

@github-actions github-actions bot added the outdated A closed issue/PR that is archived due to age. Recommended to make a new issue label May 3, 2021
@github-actions github-actions bot locked as resolved and limited conversation to collaborators May 3, 2021
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Has PR i: bug outdated A closed issue/PR that is archived due to age. Recommended to make a new issue
Projects
None yet
Development

Successfully merging a pull request may close this issue.

9 participants