Skip to content

Optimizing Compiler: Inline ReactElements #3228

Closed
@sebmarkbage

Description

@sebmarkbage

Starting with React 0.14 we will be able to inline ReactElements:

<div className="foo">{bar}<Baz key="baz" /></div>

as objects:

{ type: 'div', props: { className: 'foo', children:
  [ bar, { type: Baz, props: { }, key: 'baz', ref: null } ]
}, key: null, ref: null }

This improves performance over the existing React.createElement call by inlining the result of it.

defaultProps

If a component might have default props they need to be resolved by the transpiler's runtime:

{ type: 'div', props: { className: 'foo', children:
  [ bar, { type: Baz, props: $resolveDefaults(Baz.defaultProps, { }), key: 'baz', ref: null } ]
}, key: null, ref: null }

Exception: ref="string"

Unfortunately we still haven't figured out what the final semantics for refs. The current semantics relies on getting the current React owner. Therefore, we cannot apply this optimization if the ref attribute might be a string.

render() {
  // Neither of these...
  return <div ref="str" />;
  // ...are safe to inline...
  return <div ref={possibleStringValue} />;
  // ...because they might contain a ref.
  return <div {...objectThatMightContainARef} />;
}

Non-JSX

This can work on React.createElement or functions created by React.createFactory if the first argument is an inline object literal. Otherwise it is not safe since the object might be reused and mutated.

Only in Production Mode

This optimization should only be applied in production mode. Currently React.createElement fires various warnings for propTypes and key warnings if the __DEV__ flag is set to true or "production" !== process.env.NODE_ENV. This optimization would skip the warnings which would be very very bad in development mode.

The difficult part of this is figuring out a way that this will work in everyone's environment because not everyone has the ability to use different transpilers for development and production mode.

One solution might be to use a ternary and rely on minifiers to strip out the extra code:

"production" === process.env.NODE_ENV ?
  { type: 'div', props: { ... }, key: null, ref: null } :
  React.createElement('div', ...)

This will a pain for source maps though.

Another solution would be to have different flags in the transpilers themselves but we'd have to make sure that people actually use them correctly. They will otherwise have problems due to not firing warnings, or think that React is slow because they screwed up their config.

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions