├── .gitignore ├── LICENSE ├── README.md ├── html └── index.html ├── js └── main.js ├── package.json └── webpack.config.js /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | .idea 3 | node_modules 4 | 5 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Axel Rauschmayer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ![Benchmark gif](http://i.imgur.com/ufZeDFd.gif) 2 | 3 | # Run 4 | 5 | * Build once: `npm run webpack` 6 | * Run dev server: `npm start` 7 | * Web page: http://localhost:8080/ 8 | * Open the console 9 | * Run `window.benchmark()` 10 | 11 | 12 | Built using https://github.com/rauschma/react-starter-project 13 | -------------------------------------------------------------------------------- /html/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 |

Open the console, then:

9 | window.benchmark(10) 10 | 11 |
12 |
13 |
14 | 15 | 16 | 17 | 18 | -------------------------------------------------------------------------------- /js/main.js: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import {render} from 'react-dom'; 3 | 4 | const Dot = (props) => 5 | .; 6 | 7 | class DotComponent extends React.Component { 8 | render() { 9 | return .; 10 | } 11 | } 12 | 13 | class Main extends React.Component { 14 | render() { 15 | var dots = Array(500).fill(0).map(x => { 16 | if(this.props.kind == 'stateless-functional-direct-call') { 17 | return Dot(); 18 | } else if(this.props.kind == 'stateless-functional-mounted') { 19 | return React.createElement(Dot, {}, {}); 20 | } else if(this.props.kind == 'stateful') { 21 | return React.createElement(DotComponent, {}, {}); 22 | } 23 | }) 24 | return React.createElement('div', {}, ...dots); 25 | } 26 | } 27 | 28 | let prevBenchmarkTime, benchmarkCount, statefulTotalTime, statelessFunctionalMountedTotalTime, statelessFunctionalDirectCallTotalTime; 29 | benchmarkCount = 0; 30 | statefulTotalTime = 0; 31 | statelessFunctionalMountedTotalTime = 0; 32 | statelessFunctionalDirectCallTotalTime = 0; 33 | 34 | const run = () => { 35 | ['stateful', 'stateless-functional-mounted', 'stateless-functional-direct-call'].forEach(kind => { 36 | const prevTime = performance.now(); 37 | 38 | var items = []; 39 | var i, len; 40 | for (i = 0, len = 20; i < len; i++) { 41 | items.push(i); 42 | } 43 | items.forEach(i => { 44 | render(( 45 |
46 | ), document.getElementById(kind)); 47 | }); 48 | 49 | const time = Math.round(performance.now() - prevTime); 50 | 51 | if(kind == 'stateless-functional-direct-call') { 52 | statelessFunctionalDirectCallTotalTime = statelessFunctionalDirectCallTotalTime + time 53 | } else if(kind == 'stateless-functional-mounted') { 54 | statelessFunctionalMountedTotalTime = statelessFunctionalMountedTotalTime + time 55 | } else if(kind == 'stateful') { 56 | statefulTotalTime = statefulTotalTime + time 57 | } 58 | 59 | const perf = (Math.round((1-time/prevBenchmarkTime)*100) || ' ') 60 | prevBenchmarkTime = time; 61 | }) 62 | prevBenchmarkTime = undefined 63 | benchmarkCount = benchmarkCount + 1 64 | console.log('.') 65 | return 66 | } 67 | 68 | window.benchmark = (count=10) => { 69 | console.log(`Running %c${count} %ctimes ...`, 'font-weight: bold', 'font-weight: normal'); 70 | Array(count).fill(0).forEach(x => run()) 71 | console.log(`Stateful took ${statefulTotalTime}ms`); 72 | console.log(`Stateless Functional Mounted took ${statelessFunctionalMountedTotalTime}ms %c${Math.round((1-statelessFunctionalMountedTotalTime/statefulTotalTime)*100)}% %c`, 'color:green', 'color:black'); 73 | console.log(`Stateless Functional Direct Call took ${statelessFunctionalDirectCallTotalTime}ms %c${Math.round((1-statelessFunctionalDirectCallTotalTime/statefulTotalTime)*100)}% %c`, 'color:green', 'color:black'); 74 | console.log(`%c🎉`, 'font-size: 100px') 75 | } 76 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "react-starter-project", 3 | "version": "1.0.0", 4 | "description": "", 5 | "scripts": { 6 | "webpack": "webpack", 7 | "start": "webpack-dev-server --hot --inline" 8 | }, 9 | "author": "Axel Rauschmayer", 10 | "license": "MIT", 11 | "devDependencies": { 12 | "babel-core": "^6.1.21", 13 | "babel-preset-es2015": "^6.1.18", 14 | "babel-preset-react": "^6.1.18", 15 | "babel-loader": "^6.1.0", 16 | 17 | "webpack": "^1.12.6", 18 | "copy-webpack-plugin": "^0.2.0", 19 | "webpack-dev-server": "^1.12.1", 20 | "react-hot-loader": "^1.3.0" 21 | }, 22 | "dependencies": { 23 | "react": "^0.14.2", 24 | "react-dom": "^0.14.2" 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /webpack.config.js: -------------------------------------------------------------------------------- 1 | /* global __dirname */ 2 | 3 | var path = require('path'); 4 | 5 | var webpack = require('webpack'); 6 | var CopyWebpackPlugin = require('copy-webpack-plugin'); 7 | 8 | var dir_js = path.resolve(__dirname, 'js'); 9 | var dir_html = path.resolve(__dirname, 'html'); 10 | var dir_build = path.resolve(__dirname, 'build'); 11 | 12 | module.exports = { 13 | entry: path.resolve(dir_js, 'main.js'), 14 | output: { 15 | path: dir_build, 16 | filename: 'bundle.js' 17 | }, 18 | devServer: { 19 | contentBase: dir_build, 20 | }, 21 | module: { 22 | loaders: [ 23 | { 24 | loader: 'react-hot', 25 | test: dir_js, 26 | }, 27 | { 28 | loader: 'babel-loader', 29 | test: dir_js, 30 | query: { 31 | presets: ['es2015', 'react'], 32 | }, 33 | } 34 | ] 35 | }, 36 | plugins: [ 37 | // Simply copies the files over 38 | new CopyWebpackPlugin([ 39 | { from: dir_html } // to: output.path 40 | ]), 41 | // Avoid publishing files when compilation fails 42 | new webpack.NoErrorsPlugin() 43 | ], 44 | stats: { 45 | // Nice colored output 46 | colors: true 47 | }, 48 | // Create Sourcemaps for the bundle 49 | devtool: 'source-map', 50 | }; 51 | --------------------------------------------------------------------------------