react: Server rendering is slower with npm react
I ran a few benchmarks on the server (modifying https://github.com/paulshen/react-bench to not use jsdom). The results were surprising, as the browserified react.js was about 30% faster than the npm version, even with NODE_ENV=production.
The performance ranking (test run time) was react.min.js < react.js < NODE_ENV=production node react < node react.
I suspect process.env is not a regular js object but perhaps a getter and thus carries a penalty when you test for "production" !== process.env.NODE_ENV everywhere.
Also the minified version might still perform best of all, as at least some time ago V8 used function source length (including comments) as a heuristic for function complexity / compilation time and thus affecting chances for optimization in some cases, but the effect might be negligible.
About this issue
- Original URL
- State: closed
- Created 10 years ago
- Reactions: 10
- Comments: 59 (24 by maintainers)
Commits related to this issue
- When packaging, copy the code and inline `__DEV__` Fixes #812. Previously, this code module.exports = moo(); function moo() { return __DEV__; } would be transformed to module.exports ... — committed to sophiebits/react by sophiebits 10 years ago
- uglify server build this gets rid of some runtime checks against the process.env property, which slows down node A LOT, see https://github.com/facebook/react/issues/812 — committed to mrtnbroder/universal-react-webpack-boilerplate by mrtnbroder 8 years ago
@mhart Technically you can fix the problem in your own code by doing
process.env = JSON.parse(JSON.stringify(process.env)), converting it from a live object that callsgetenvdown a plain JS object. You’ll get the same performance benefits, with the only downside that any code that was relying on live edits to the env (does anyone really do that?) will fail.Referencing https://github.com/facebook/fbjs/pull/86 which will fix this now that UglifyJS can properly eliminate dev code (even if it references a
varthat never changes) with its newreduce_varsoption, which is a default.See https://github.com/facebook/fbjs/pull/86#issuecomment-285204734 for more context.
Lately I have been simply using a wrapped module
Works great. You could consider switching npm package to some such scheme if there are no downsides.
@STRML thanks! However, I’ve seen a warning that
babel/registeris not suitable for libraries. I’ve only usedbabel/registeron files in my app. I’m curious if people use it on node modules commonly in production.If you’re already using babel on your server-side code (say, via
babel-nodeorrequire('babel-register')), you can add the inline env transformer to get around this problem.Call me all crazy, just had a left field idea. Could the transformer that builds the npm module create 2 complete copies of react? one for dev and one for production?
In the the normal version of react
var React = require('react')could you there look at theNODE_ENVand swap which module is returned? This way on server you only get the performance hit once;I’m using webpack and
new webpack.DefinePlugin({'process.env.NODE_ENV': '"production"'})was enough to solve it for me. Is there no such thing in browserify?