Skip to content

New JSX runtime use adds spread overhead #2773

@bz2

Description

@bz2

Using new JSX runtime compilation through babel added in preact 10.5.x adds spread operations and overhead in cases the old createElement-like interface did not have.

For instance, one chunk in a project I'm working on went from 30.9 KiB minified to 34.6 KiB. It looks like the actual fix(es) will need to happen at the babel level, but might be worth documenting a sane path for now with preact?

Steps

Clone https://github.com/bz2/example-babel-jsx-spread for a minimal reproduction.

For a component like this:

function App({style}) {
  return <h1 {...{style}}>Title</h1>;
}

Using a pragma and importing h results in babel with @babel/preset-env generating the following code:

function App(_ref) {
  var style = _ref.style;
  return h("h1", {
    style: style
  }, "Title");
}

Whereas using '@babel/plugin-transform-react-jsx', {runtime: 'automatic', importSource: 'preact'}] produces:

function App(_ref) {
  var style = _ref.style;
  return jsxRuntime_module_o("h1", _objectSpread(_objectSpread({}, {
    style: style
  }), {}, {
    children: "Title"
  }));
}

Note this case of explicit spreading a literal is particularly bad because spread is actually known to not be needed at compile time.

The switch to using spread was added in babel/babel#10572 and this is also gets made worse by babel/babel#10261 (has a solution, but is non-obvious as a problem) which resulted in a local copy of _objectSpread and its helpers in every file.

In preset-modules babel/preset-modules#4 was used to use Object.assign instead, but I don't see how to get that to work for the remerged bugfixes: true option of preset-env.

Expected Behavior

Using the new JSX runtime should result in faster, and also not larger code.

Actual Behavior

Using the new JSX runtime generates larger, slower code.

Solution

Probably a bit more smarts upstream in the babel-helper-builder-react-jsx-experimental and some new docs in preact showing the right combination of babel options for the best results?

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions