{"action":"created","issue":{"url":"https://api.github.com/repos/6to5/6to5/issues/653","labels_url":"https://api.github.com/repos/6to5/6to5/issues/653/labels{/name}","comments_url":"https://api.github.com/repos/6to5/6to5/issues/653/comments","events_url":"https://api.github.com/repos/6to5/6to5/issues/653/events","html_url":"https://github.com/6to5/6to5/issues/653","id":56161709,"number":653,"title":"React/Flow/Type optimisations","user":{"login":"sebmck","id":853712,"avatar_url":"https://avatars.githubusercontent.com/u/853712?v=3","gravatar_id":"","url":"https://api.github.com/users/sebmck","html_url":"https://github.com/sebmck","followers_url":"https://api.github.com/users/sebmck/followers","following_url":"https://api.github.com/users/sebmck/following{/other_user}","gists_url":"https://api.github.com/users/sebmck/gists{/gist_id}","starred_url":"https://api.github.com/users/sebmck/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/sebmck/subscriptions","organizations_url":"https://api.github.com/users/sebmck/orgs","repos_url":"https://api.github.com/users/sebmck/repos","events_url":"https://api.github.com/users/sebmck/events{/privacy}","received_events_url":"https://api.github.com/users/sebmck/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/6to5/6to5/labels/discussion","name":"discussion","color":"bfe5bf"}],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":17,"created_at":"2015-02-01T12:15:16Z","updated_at":"2015-02-02T21:35:30Z","closed_at":null,"body":"As per #568 I've been thinking of areas where static analysis and JavaScript transformation can really shine and one area in particular that I've thought of is the optimisation of React components. There's a lot of areas for possible optimisations, especially with the use of flow types and React `propTypes`.\r\n\r\nFor example consider the following:\r\n\r\n```javascript\r\nvar Foo = React.createClass({\r\n  propTypes: {\r\n    items: React.PropTypes.array\r\n  },\r\n\r\n  render() {\r\n    return <div>{this.props.items.map(function (item) {\r\n      return <p>{item.title}</p>;\r\n    })}</div>;\r\n  }\r\n});\r\n```\r\n\r\nThis would normally be compiled to:\r\n\r\n```javascript\r\nvar Foo = React.createClass({\r\n  displayName: \"Foo\",\r\n\r\n  propTypes: {\r\n    items: React.PropTypes.array\r\n  },\r\n\r\n  render: function render() {\r\n    return React.createElement(\r\n      \"div\",\r\n      null,\r\n      this.props.items.map(function (item) {\r\n        return React.createElement(\"p\", null, item.title);\r\n      })\r\n    );\r\n  }\r\n});\r\n```\r\n\r\nHowever with the optimisations I'm proposing it would instead compile to:\r\n\r\n```javascript\r\nvar Foo = React.createClass({\r\n  displayName: \"Foo\",\r\n  \r\n  propTypes: {\r\n    items: React.PropTypes.array\r\n  },\r\n\r\n  render: function render() {\r\n    return React.createElement(\r\n      \"div\",\r\n      null,\r\n      (function (items) {\r\n        var children = [];\r\n        for (var i = 0; i < items.length; i++) {\r\n          var item = items[i];\r\n          children.push(React.createElement(\"p\", null, item.title));\r\n        }\r\n        return children;\r\n      })(this.props.items)\r\n    );\r\n  }\r\n});\r\n```\r\n\r\nIt may even be possible to drop the IIFE depending on the order of evaluation. There's a lot of patterns that could be handled to ensure that the code is as fast as possible. Other array methods such as `filter`, `some`, `every` etc could also be handled.\r\n\r\nI think this would be extremely beneficial especially in hot methods such as `render`. You could even extend this to inlining methods so:\r\n\r\n```javascript\r\nvar Button = React.createClass({\r\n  title() {\r\n    return (\r\n      <div className=\"detail\">\r\n        <h2 className=\"detail__title\">{this.props.options.title}</h2>\r\n      </div>\r\n    );\r\n  },\r\n\r\n  render() {\r\n    return (\r\n      <div className=\"dialog__inner\">\r\n        {this.title()}\r\n      </div>\r\n    );\r\n  }\r\n});\r\n```\r\n\r\nwould just become:\r\n\r\n```javascript\r\nvar Button = React.createClass({\r\n  displayName: \"Button\",\r\n  \r\n  render: function render() {\r\n    return React.createElement(\r\n      \"div\",\r\n      { className: \"dialog__inner\" },\r\n      React.createElement(\r\n        \"div\",\r\n        { className: \"detail\" },\r\n        React.createElement(\r\n          \"h2\",\r\n          { className: \"detail__title\" },\r\n          this.props.options.title\r\n        )\r\n      )\r\n    );\r\n  }\r\n});\r\n```\r\n\r\nReference tracking would also need to be implemented to handle the following:\r\n\r\n```javascript\r\nvar props = this.props; // register that `props` is `this.props`\r\nprops.foo;\r\n\r\nvar foo = this.props.foo; // register that `foo` is `this.props.foo`\r\nvar foo2 = foo; // register that `foo2` is `this.props.foo`\r\nfoo = bar; // `foo` has been dereferenced\r\n```\r\n\r\n/cc @RReverser @amasad @fkling @fabiomcosta @leebyron\r\n\r\nThere's a lot that can be done and I'd be interested to hear your feedback on whether something like this is valuable and specific problem areas that could be optimised with static analysis."},"comment":{"url":"https://api.github.com/repos/6to5/6to5/issues/comments/72542790","html_url":"https://github.com/6to5/6to5/issues/653#issuecomment-72542790","issue_url":"https://api.github.com/repos/6to5/6to5/issues/653","id":72542790,"user":{"login":"phpnode","id":363611,"avatar_url":"https://avatars.githubusercontent.com/u/363611?v=3","gravatar_id":"","url":"https://api.github.com/users/phpnode","html_url":"https://github.com/phpnode","followers_url":"https://api.github.com/users/phpnode/followers","following_url":"https://api.github.com/users/phpnode/following{/other_user}","gists_url":"https://api.github.com/users/phpnode/gists{/gist_id}","starred_url":"https://api.github.com/users/phpnode/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/phpnode/subscriptions","organizations_url":"https://api.github.com/users/phpnode/orgs","repos_url":"https://api.github.com/users/phpnode/repos","events_url":"https://api.github.com/users/phpnode/events{/privacy}","received_events_url":"https://api.github.com/users/phpnode/received_events","type":"User","site_admin":false},"created_at":"2015-02-02T21:35:30Z","updated_at":"2015-02-02T21:35:30Z","body":"It seems like if you want to do this kind of optimization (rewriting `.map` to a loop etc), catering specifically to React would be a mistake. Flow types are the obvious way to approach this, it's a real shame that flow isn't a JS library itself - to do this safely 6to5 needs a way to reliably infer types. If type information was available in the AST it'd be a lot easier to plugin many different types of optimisation, e.g. tail calls etc."}}