Skip to content

Prevents unnecessary rerenders and GC pressure by hoisting constant objects out of JSX attributes and into the global scope, ex. for objects in a 'style' prop.

License

Notifications You must be signed in to change notification settings

joshwilsonvu/babel-plugin-hoist-constant-jsx-attributes

Repository files navigation

babel-plugin-hoist-constant-jsx-attributes

Version NPM Version License Build Status Supported Node Version

This plugin can reduce React rerenders and garbage collection pressure by pulling constant object attribute values (like style={{ color: 'red' }}) out of functions and into the highest possible scope. This means the objects will only get allocated once, and they will keep the same identity across renders.

Objects are only pulled out if they are plain old data and don't reference any variables, so more dynamic use cases will still work as written.

Example

In

const Component = () => <div style={{ color: 'red', fontSize: 14 }}>Text</div>;

Out

const _style = { color: 'red', fontSize: 14 };
const Component = () => <div style={_style}>Text</div>;

Install

# npm
npm i --save-dev babel-plugin-hoist-constant-jsx-attributes
# yarn
yarn add --dev babel-plugin-hoist-constant-jsx-attributes
{
  "plugins": [
    ["babel-plugin-hoist-constant-jsx-attributes", { /* options (see below) */ }]
  ]
}

Options

include

RegExp, or string to be matched with micromatch

Only hoist attribute values if the element name matches.

exclude

RegExp, or string to be matched with micromatch

Only hoist attributes values if the element name does not match.

includeAttributes

RegExp, or string to be matched with micromatch

Only hoist attribute values if the attribute name matches.

excludeAttributes

RegExp, or string to be matched with micromatch

Only hoist attributes values if the attribute name does not match.

lowerCaseOnly

boolean, defaults to false

Only hoist object attribute values on primitive elements like div and button.

alwaysHoist

boolean, defaults to false

By default, this plugin only hoists attribute values if the JSX element is contained in a function or method. Using this option is not recommended, since otherwise the problems this plugin solves don't occur. Setting this option to true will hoist even if the JSX element is at the top level.

freezeObjects

false, 'development', or 'always', defaults to false.

If set to 'development', check at runtime to see if process.env.NODE_ENV === 'development', and if so deeply freeze hoisted objects. If set to 'always', deeply freeze hoisted objects unconditionally.

Use this option for extra safety if you want to ensure that the attribute values are never mutated. If there is an attempt to mutate a hoisted attribute value, an exception will be thrown. Slightly increases the compiled code size.

Note

The React team considers this transformation unsafe to run by default, because it is possible to rely on object attribute values to have different identities every render. See this GitHub issue for more information.

However, the vast majority of cases will benefit from this transformation. The main reason they consider it unsafe is precisely because it can reduce the number of times a component rerenders, which is likely to be what you want. Unless you were to intentionally tinker with object referential equality, or mutate received props —and you would know if you were—this transformation will be safe.

Still, to be extra careful, you can set the lowerCaseOnly plugin option to true. You can also set the freezeObjects plugin option to 'development' or 'always' to receive an error if a component tries to mutate its props.

About

Prevents unnecessary rerenders and GC pressure by hoisting constant objects out of JSX attributes and into the global scope, ex. for objects in a 'style' prop.

Topics

Resources

License

Stars

Watchers

Forks

Releases

No releases published