CSS in JS React vs Stylesheet

JavaScript performance comparison

Revision 2 of this test case created by

Preparation code

<!-- React -->
<script src="http://fb.me/react-0.12.1.min.js"></script>
<!-- Undercore -->
<script src="http://underscorejs.org/underscore-min.js"></script>

<div id="inlineMountNode"></div>
<div id="stylesheetMountNode"></div>
      
<script>
Benchmark.prototype.setup = function() {
  var STYLESHEET = (function() {
      // Create the <style> tag
      var style = document.createElement("style");
      // WebKit hack :(
      style.appendChild(document.createTextNode(""));
      // Add the <style> element to the page
      document.head.appendChild(style);
      return style.sheet;
  })();
  function addStyleRule(props, selector) {
      // we insert an empty rule just to create a new CSSStyleRule object
      // the second param is the index to insert at
      // using the length property we effectively "append" the rule to the end of the sheet
      var ruleIndex = STYLESHEET.insertRule(selector + " {}", STYLESHEET.cssRules.length)
  
      // the index is the position the rule was inserted at, so we can now get a handle on it
      var rule = STYLESHEET.cssRules.item(ruleIndex);
  
      // now we have it, modify it's styles!
      // applied to the document immediately
      _.each(props, function (v, k) {
          rule.style[k] = v;
      });
  }
  
  var styleData = {
      '.row': {
          backgroundColor: "rgb(226, 237, 255)",
          borderCollapse: "separate",
          color: "rgb(51, 51, 51)",
          display: "block",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "14px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "19px",
          lineHeight: "17px",
          overflowX: "hidden",
          overflowY: "hidden",
          paddingBottom: "1px",
          paddingLeft: "50px",
          paddingRight: "15px",
          paddingTop: "1px",
          whiteSpace: "pre-wrap",
          width: "796px",
          wordWrap: "break-word"
      },
      '.date': {
          borderCollapse: "separate",
          color: "rgb(170, 170, 170)",
          display: "inline-block",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "11px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "17px",
          lineHeight: "17px",
          marginLeft: "-50px",
          marginRight: "5px",
          marginTop: "2px",
          textAlign: "center",
          verticalAlign: "top",
          whiteSpace: "pre-wrap",
          width: "45px",
          wordWrap: "break-word"
      },
      '.title': {
          borderCollapse: "separate",
          color: "rgb(170, 170, 170)",
          display: "inline",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "11px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "auto",
          lineHeight: "17px",
          textAlign: "center",
          whiteSpace: "pre-wrap",
          width: "auto",
          wordWrap: "break-word"
      },
      '.g': {
          borderCollapse: "separate",
          color: "rgb(51, 51, 51)",
          display: "block",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "14px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "17px",
          left: "-999px",
          lineHeight: "17px",
          position: "absolute",
          top: "-999px",
          whiteSpace: "pre-wrap",
          width: "3.90625px",
          wordWrap: "break-word"
      },
      '.message': {
          borderCollapse: "separate",
          color: "rgb(51, 51, 51)",
          display: "inline",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "14px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "auto",
          lineHeight: "17px",
          whiteSpace: "pre-wrap",
          width: "auto",
          wordWrap: "break-word"
      },
      '.authorWrap': {
          borderCollapse: "separate",
          color: "rgb(51, 51, 51)",
          display: "inline",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "14px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "auto",
          lineHeight: "17px",
          whiteSpace: "pre-wrap",
          width: "auto",
          wordWrap: "break-word"
      },
      '.mode_symbol': {
          borderCollapse: "separate",
          color: "rgb(186, 23, 25)",
          display: "none",
          fontFamily: "Inconsolata, 'Ubuntu Mono', Menlo, Consolas, Courier, monospace",
          fontSize: "15px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "auto",
          lineHeight: "17px",
          marginBottom: "0px",
          marginBeft: "0px",
          marginBight: "3px",
          marginBop: "0px",
          whiteSpace: "pre-wrap",
          width: "auto",
          wordWrap: "break-word"
      },
      '.mode_pill': {
          borderCollapse: "separate",
          color: "rgb(186, 23, 25)",
          display: "inline",
          fontFamily: "Inconsolata, 'Ubuntu Mono', Menlo, Consolas, Courier, monospace",
          fontSize: "15px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "bold",
          height: "auto",
          lineHeight: "17px",
          marginBottom: "0px",
          marginBeft: "0px",
          marginBight: "3px",
          marginBop: "0px",
          whiteSpace: "pre-wrap",
          width: "auto",
          wordWrap: "break-word"
      },
      '.bufferLink': {
          borderCollapse: "separate",
          color: "rgb(34, 34, 34)",
          cursor: "auto",
          display: "inline",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "14px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "bold",
          height: "auto",
          lineHeight: "17px",
          textDecoration: "none",
          whiteSpace: "nowrap",
          width: "auto",
          wordWrap: "break-word"
      },
      '.content': {
          borderCollapse: "separate",
          color: "rgb(51, 51, 51)",
          display: "inline",
          fontFamily: "'Helvetica Neue', Helvetica, Arial, sans-serif",
          fontSize: "14px",
          fontStyle: "normal",
          fontVariant: "normal",
          fontWeight: "normal",
          height: "auto",
          lineHeight: "17px",
          whiteSpace: "pre-wrap",
          width: "auto",
          wordWrap: "break-word"
      }
  };
  
  _.each(styleData, addStyleRule);
  var LogLines = React.createClass({
      styled: function (className, elProps) {
          elProps = elProps || {};
          if (this.props.inline) {
              elProps.style = styleData['.' + className];
          } else {
              elProps.className = className;
          }
          return elProps;
      },
      render: function () {
          var lines = {};
          _.each(_.range(1000), function (i) {
              var div = React.DOM.div(this.styled('row'),
                  React.DOM.span(this.styled('date'),
                      React.DOM.span(this.styled('title'), '17:06')
                  ),
                  React.DOM.span(this.styled('g'), '\u00A0'),
                  React.DOM.span(this.styled('message'),
                      React.DOM.span(this.styled('authorWrap'),
                          React.DOM.span(this.styled('g'), '<'),
                          React.DOM.span(this.styled('mode_symbol'), '@'),
                          React.DOM.span(this.styled('mode_pill'), '•'),
                          React.DOM.a(this.styled('bufferLink', {
                              'href': "#"
                          }), 'foo'),
                          React.DOM.span(this.styled('g'), '>'),
                          '\u00A0'
                      ),
                      React.DOM.span(this.styled('content'), 'bar')
                  )
              );
              lines['line-' + i] = div;
          }, this);
          return React.DOM.div(null, lines);
      }
  });
  var logs = React.createFactory(LogLines);

};
</script>

Preparation code output

<!-- React --> <!-- Undercore --> <div id="inlineMountNode"></div> <div id="stylesheetMountNode"></div>

Test runner

Warning! For accurate results, please disable Firebug before running the tests. (Why?)

Java applet disabled.

Testing in CCBot 2.0.0 / Other 0.0.0
Test Ops/sec
Inline
React.render(logs({inline: true}), document.getElementById('inlineMountNode'));
pending…
Stylesheet

React.render(logs({inline: false}), document.getElementById('stylesheetMountNode'));
pending…

Compare results of other browsers

Revisions

You can edit these tests or add even more tests to this page by appending /edit to the URL.

0 Comments