├── .babelrc
├── .eslintignore
├── .eslintrc
├── .gitignore
├── .npmignore
├── .travis.yml
├── README.md
├── app
├── .babelrc
├── index.html
├── js
│ ├── components
│ │ └── Input.js
│ ├── containers
│ │ └── App.js
│ ├── index.js
│ ├── reducers
│ │ ├── Elements.js
│ │ └── index.js
│ └── store
│ │ └── configureStore.js
├── package.json
├── static
│ └── bundle.js
└── webpack.config.js
├── index.js
├── lib
└── index.js
├── package.json
└── src
└── index.js
/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015","stage-0"]
3 | }
4 |
--------------------------------------------------------------------------------
/.eslintignore:
--------------------------------------------------------------------------------
1 | ./test/*.js
2 |
--------------------------------------------------------------------------------
/.eslintrc:
--------------------------------------------------------------------------------
1 | {
2 | "rules": {
3 | "quotes": [
4 | 2,
5 | "single"
6 | ],
7 | "linebreak-style": [
8 | 2,
9 | "unix"
10 | ],
11 | "semi": [
12 | 2,
13 | "always"
14 | ],
15 | "consistent-return": 0,
16 | "no-else-return": 0,
17 | "no-console": 0,
18 | "max-len": [1, 160],
19 | "quote-props": [1, "consistent-as-needed"],
20 | "no-cond-assign": [2, "except-parens"],
21 | "radix": 0,
22 | "func-names": 0,
23 | "padded-blocks": 0,
24 | "computed-property-spacing": [2, "always"],
25 | "space-infix-ops": 0,
26 | "no-unused-vars": [1, {"vars": "local", "args": "none"}],
27 | "space-before-function-paren": 2,
28 | "space-in-parens": [2, "always"],
29 | "key-spacing": [2, { "align": "colon", "beforeColon": false, "afterColon": true }],
30 | "brace-style": [2, "allman", { "allowSingleLine": true }]
31 | },
32 | "env": {
33 | "es6": true,
34 | "browser": true,
35 | "node": true
36 | },
37 | "extends": "airbnb/base",
38 | "globals": {
39 | "describe": true,
40 | "it": true,
41 | "beforeEach": true
42 | },
43 | "plugins": [
44 | "react"
45 | ]
46 | }
47 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | node_modules
2 | /lib
3 |
--------------------------------------------------------------------------------
/.npmignore:
--------------------------------------------------------------------------------
1 | .babelrc
2 | .eslintignore
3 | .eslintrc
4 | .gitignore
5 | .travis.yml
6 | npm-debug.log
7 | test/
8 | app/
9 | src/
10 |
--------------------------------------------------------------------------------
/.travis.yml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/AvraamMavridis/redux-perf-middleware/dda01fb1482317d14f3761738f9f52c3bbaab551/.travis.yml
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # redux-perf-middleware
2 |
3 | [](https://badge.fury.io/js/redux-perf-middleware) []()
4 | []()
5 |
6 |
7 | Measure the time that the actions need to change the state
8 |
9 | ### Install
10 | [](https://nodei.co/npm/redux-perf-middleware/)
11 |
12 | ### Usage
13 |
14 | ```javascript
15 | import perflogger from 'redux-perf-middleware';
16 |
17 | const createStoreWithMiddleware = applyMiddleware( perflogger )(createStore);
18 | const store = createStoreWithMiddleware(reducer);
19 | ```
20 |
21 | This project adheres to [Semantic Versioning](http://semver.org/).
22 |
23 |
24 |
25 | ### Example
26 |
27 | **Dumb Reducer**
28 |
29 | ```javascript
30 | function slow(){
31 | let sum;
32 | for(let i = 0; i< 10000; i++){
33 | for(let j = 0; j< 10000; j++)
34 | {
35 | sum = i+j;
36 | }
37 | }
38 | return sum;
39 | }
40 |
41 |
42 | export const Elements = function ( state = {}, action ) {
43 |
44 | switch ( action.type )
45 | {
46 | case 'SLOW':
47 | return slow();
48 |
49 | default:
50 | return state;
51 | }
52 | };
53 | ```
54 |
55 | **Dumb Component**
56 |
57 | ```javascript
58 | import React, { Component } from 'react';
59 | import { connect } from 'react-redux';
60 |
61 | class Input extends Component {
62 | /**
63 | * Renders the markup for the topbar
64 | */
65 | render() {
66 | const { dispatch } = this.props;
67 | return (
68 | dispatch({ type: 'SLOW' })} />
69 | );
70 | }
71 | };
72 |
73 | const selector = function( { default: elements } ){
74 | return elements;
75 | }
76 |
77 | export default connect(selector)( Input );
78 | ```
79 |
80 | On every keydown **Redux** will dispatch the action with type SLOW, and in the console the middleware will log something like:
81 |
82 | 
83 |
84 | Or check the [sample app](https://github.com/AvraamMavridis/redux-perf-middleware/tree/master/app)
85 |
86 | ## Contributing
87 | Feel free to open issues, make suggestions or send PRs.
88 | This project adheres to the Contributor Covenant [code of conduct](http://contributor-covenant.org/). By participating, you are expected to uphold this code.
89 |
90 | ## Contact
91 |
92 | Twitter: [@avraamakis](https://twitter.com/avraamakis)
93 |
94 | ### License
95 | MIT
96 |
--------------------------------------------------------------------------------
/app/.babelrc:
--------------------------------------------------------------------------------
1 | {
2 | "presets": ["es2015","react","stage-0"]
3 | }
4 |
--------------------------------------------------------------------------------
/app/index.html:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
--------------------------------------------------------------------------------
/app/js/components/Input.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Simple Input Component
3 | *
4 | * @author Avraam Mavridis
5 | *
6 | */
7 | import React, { Component } from 'react';
8 | import { connect } from 'react-redux';
9 |
10 | class Input extends Component {
11 | /**
12 | * Renders the markup for the topbar
13 | */
14 | render() {
15 | const { dispatch } = this.props;
16 | return (
17 | dispatch({ type: 'SLOW' })} />
18 | );
19 | }
20 | };
21 |
22 | const selector = function( { default: elements } ){
23 | return elements;
24 | }
25 |
26 | export default connect(selector)( Input );
27 |
--------------------------------------------------------------------------------
/app/js/containers/App.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Main Component, Container
3 | *
4 | * @author Avraam Mavridis
5 | *
6 | */
7 | 'use strict';
8 |
9 | /** External Dependecies */
10 | import React from 'react';
11 | import { Provider } from 'react-redux';
12 | import { connect } from 'react-redux';
13 | import configureStore from '../store/configureStore';
14 | import Input from '../components/Input';
15 | const store = configureStore();
16 |
17 | export class App extends React.Component
18 | {
19 | render() {
20 | return (
21 |
22 |
23 |
24 | );
25 | }
26 | }
27 |
--------------------------------------------------------------------------------
/app/js/index.js:
--------------------------------------------------------------------------------
1 | import React from 'react';
2 | import ReactDOM from 'react-dom';
3 | import { App } from './containers/App';
4 |
5 | ReactDOM.render( , document.getElementById( 'main' ) );
6 |
--------------------------------------------------------------------------------
/app/js/reducers/Elements.js:
--------------------------------------------------------------------------------
1 | function slow(){
2 | let sum;
3 | for(let i = 0; i< 10000; i++){
4 | for(let j = 0; j< 10000; j++)
5 | {
6 | sum = i+j;
7 | }
8 | }
9 | return sum;
10 | }
11 |
12 |
13 | export const Elements = function ( state = {}, action ) {
14 |
15 | switch ( action.type )
16 | {
17 | case 'SLOW':
18 | return slow();
19 |
20 | default:
21 | return state;
22 | }
23 | };
24 |
--------------------------------------------------------------------------------
/app/js/reducers/index.js:
--------------------------------------------------------------------------------
1 | import { Elements } from './Elements';
2 | import { combineReducers } from 'redux';
3 |
4 | export default combineReducers( {
5 | elements: Elements
6 | } );
7 |
--------------------------------------------------------------------------------
/app/js/store/configureStore.js:
--------------------------------------------------------------------------------
1 | import { createStore, applyMiddleware, combineReducers, compose } from 'redux';
2 | import * as reducers from '../reducers/index';
3 | import perflogger from 'redux-perf-middleware';
4 |
5 | let createStoreWithMiddleware = applyMiddleware( perflogger )( createStore );
6 |
7 | const rootReducer = combineReducers( reducers );
8 |
9 | export default function configureStore( initialState = {} ) {
10 | return createStoreWithMiddleware( rootReducer, initialState );
11 | }
12 |
--------------------------------------------------------------------------------
/app/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "app",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "index.js",
6 | "scripts": {
7 | "start": "webpack-dev-server --config webpack.config.js",
8 | "build-dev": "webpack -p",
9 | "test": "mocha --compilers js:babel-core/register --recursive",
10 | "test:watch": "npm test -- --watch"
11 | },
12 | "author": "Avraam Mavridis (http://avraammavridis.github.io/)",
13 | "license": "ISC",
14 | "devDependencies": {
15 | "babel-core": "^6.4.0",
16 | "babel-loader": "^6.2.1",
17 | "babel-preset-es2015": "^6.3.13",
18 | "babel-preset-stage-0": "^6.3.13",
19 | "eslint": "^1.10.3",
20 | "eslint-config-airbnb": "^3.1.0",
21 | "eslint-plugin-react": "^3.15.0",
22 | "open-browser-webpack-plugin": "0.0.2",
23 | "react": "^0.14.6",
24 | "react-dom": "^0.14.6",
25 | "react-hot-loader": "^1.3.0",
26 | "react-redux": "^4.0.6",
27 | "redux": "^3.0.5",
28 | "redux-perf-middleware": "0.0.3",
29 | "webpack": "^1.12.11",
30 | "webpack-dev-server": "^1.14.1"
31 | },
32 | "dependencies": {
33 | "babel-preset-react": "^6.3.13"
34 | }
35 | }
36 |
--------------------------------------------------------------------------------
/app/webpack.config.js:
--------------------------------------------------------------------------------
1 | var webpack = require('webpack');
2 | const OpenBrowserPlugin = require( 'open-browser-webpack-plugin' );
3 |
4 | var devFlagPlugin = new webpack.DefinePlugin({
5 | __DEV__: JSON.stringify(JSON.parse(process.env.DEBUG || 'false'))
6 | });
7 |
8 | module.exports = {
9 | entry: [
10 | 'webpack-dev-server/client?http://localhost:8080',
11 | 'webpack/hot/only-dev-server',
12 | './js/index.js'
13 | ],
14 | output: {
15 | path: __dirname + '/static/',
16 | publicPath: '/static/',
17 | filename: 'bundle.js',
18 | hot: true
19 | },
20 | plugins: [
21 | new webpack.HotModuleReplacementPlugin(),
22 | new OpenBrowserPlugin( { url: 'http://localhost:8080' } )
23 | ],
24 | module: {
25 | loaders: [
26 | { test: /\.js$/, loaders: ['react-hot', 'babel'], exclude: /node_modules/ },
27 | ]
28 | },
29 | resolve: {
30 | extensions: ['', '.js', '.json']
31 | }
32 | };
33 |
--------------------------------------------------------------------------------
/index.js:
--------------------------------------------------------------------------------
1 | module.exports = require( './lib' );
2 |
--------------------------------------------------------------------------------
/lib/index.js:
--------------------------------------------------------------------------------
1 | 'use strict';
2 |
3 | Object.defineProperty(exports, "__esModule", {
4 | value: true
5 | });
6 | /**
7 | * Redux performance logger
8 | *
9 | * @author Avraam Mavridis
10 | *
11 | */
12 | var perflogger = exports.perflogger = function perflogger(store) {
13 | return function (next) {
14 | return function (action) {
15 | console.log('dispatching', action);
16 | console.log('%c Dispatching ', 'background: #222; color: #bada55', action);
17 | var start = performance.now();
18 | var result = next(action);
19 | var end = performance.now();
20 | console.log('%c Action with type "' + action.type + '" took ' + (end - start).toFixed(2) + ' milliseconds.', 'background: #bada55; color: #222');
21 | return result;
22 | };
23 | };
24 | };
25 |
26 | exports.default = perflogger;
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "redux-perf-middleware",
3 | "version": "1.2.2",
4 | "description": "Measure the time that actions needs to change the state",
5 | "main": "index.js",
6 | "scripts": {
7 | "test": "npm run compile && mocha --compilers js:babel-register --require babel-polyfill",
8 | "compile": "babel --presets es2015,stage-0 --require babel-polyfill -d lib/ src/",
9 | "prepublish": "npm run compile",
10 | "watch": "npm-scripts-watcher"
11 | },
12 | "watch": {
13 | "src/**/*.js": [
14 | "compile"
15 | ]
16 | },
17 | "repository": {
18 | "type": "git",
19 | "url": "git+https://github.com/AvraamMavridis/redux-perf-middleware.git"
20 | },
21 | "keywords": [
22 | "redux",
23 | "logger",
24 | "redux-logger",
25 | "redux",
26 | "middleware",
27 | "redux-perf-logger",
28 | "redux-perf-middleware",
29 | "redux-performance",
30 | "performance"
31 | ],
32 | "author": "Avraam Mavridis (http://avraammavridis.github.io/)",
33 | "license": "MIT",
34 | "devDependencies": {
35 | "babel-cli": "^6.11.4",
36 | "babel-core": "^6.11.4",
37 | "babel-plugin-transform-decorators": "^6.8.0",
38 | "babel-plugin-transform-decorators-legacy": "^1.3.4",
39 | "babel-polyfill": "^6.9.1",
40 | "babel-preset-es2015": "^6.9.0",
41 | "babel-preset-react": "^6.11.1",
42 | "babel-preset-stage-0": "^6.5.0",
43 | "babel-register": "^6.11.6",
44 | "chai": "^3.5.0",
45 | "eslint": "^1.10.3",
46 | "eslint-config-airbnb": "^2.0.0",
47 | "eslint-config-google": "^0.3.0",
48 | "eslint-plugin-react": "^3.11.2",
49 | "mocha": "^3.0.0",
50 | "promise": "^7.1.1",
51 | "sinon": "^1.17.5",
52 | "sinon-chai": "^2.8.0"
53 | },
54 | "bugs": {
55 | "url": "https://github.com/AvraamMavridis/redux-perf-middleware/issues"
56 | },
57 | "homepage": "https://github.com/AvraamMavridis/redux-perf-middleware#readme",
58 | "dependencies": {
59 | "present": "^1.0.0"
60 | }
61 | }
62 |
--------------------------------------------------------------------------------
/src/index.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Redux performance logger
3 | *
4 | * @author Avraam Mavridis
5 | *
6 | */
7 |
8 | const present = require('present')
9 |
10 | export const perflogger = store => next => action => {
11 | console.log( '%c Dispatching ', 'background: #222; color: #bada55', action );
12 | const start = present();
13 | const result = next( action );
14 | const end = present();
15 | console.log( `%c Action with type "${action.type}" took ${( end-start ).toFixed( 2 )} milliseconds.`, 'background: #bada55; color: #222' );
16 | return result;
17 | };
18 |
19 | export default perflogger;
20 |
--------------------------------------------------------------------------------