{"id":13393024,"url":"https://github.com/ohager/nanoflux","last_synced_at":"2025-04-28T14:49:09.656Z","repository":{"id":57307957,"uuid":"42107132","full_name":"ohager/nanoflux","owner":"ohager","description":"A very lightweight and dependency-free Flux implementation","archived":false,"fork":false,"pushed_at":"2021-07-07T14:50:23.000Z","size":760,"stargazers_count":57,"open_issues_count":1,"forks_count":3,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-04-14T11:45:51.000Z","etag":null,"topics":["application-state","flux","flux-architecture"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ohager.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2015-09-08T11:03:10.000Z","updated_at":"2023-11-17T17:57:04.000Z","dependencies_parsed_at":"2022-08-31T04:22:57.978Z","dependency_job_id":null,"html_url":"https://github.com/ohager/nanoflux","commit_stats":null,"previous_names":[],"tags_count":10,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohager%2Fnanoflux","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohager%2Fnanoflux/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohager%2Fnanoflux/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ohager%2Fnanoflux/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ohager","download_url":"https://codeload.github.com/ohager/nanoflux/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":250790123,"owners_count":21487752,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["application-state","flux","flux-architecture"],"created_at":"2024-07-30T17:00:41.272Z","updated_at":"2025-04-28T14:49:09.619Z","avatar_url":"https://github.com/ohager.png","language":"JavaScript","funding_links":[],"categories":["Uncategorized"],"sub_categories":["Uncategorized"],"readme":"[![Build Status](https://travis-ci.org/ohager/nanoflux.svg?branch=master)](https://travis-ci.org/ohager/nanoflux)\r\n[![npm version](https://img.shields.io/npm/v/nanoflux.svg?style=flat-square)](https://www.npmjs.com/package/nanoflux)\r\n[![npm downloads](https://img.shields.io/npm/dm/nanoflux.svg?maxAge=2592000)](https://www.npmjs.com/package/nanoflux)\r\n\r\n# nanoflux\r\n\r\n[__PROJECT SITE__](http://ohager.github.io/nanoflux/)\r\n\r\n__nanoflux__ is a *very* lightweight (about 3.5 KiB minified, and 1.25 KiB gzipped) dependency-free Flux implementation.\r\n\r\nThe idea of this implementation is to support a very small, but full Flux implementation (separated Action, Dispatcher, and Store), \r\nand also a \"fluxy\" version, with Action and Dispatcher merged in one unit. \r\n\r\nFurthermore, __nanoflux__ uses a pure functional approach as a performant solution.\r\n\r\n# Features\r\n\r\n- Extremely tiny implementation\r\n- No dependencies at all\r\n- Support for full Flux using full stack of ActionProvider/Creator, Dispatcher, and Stores\r\n- Support for a simplified 'fluxy' concept, where Dispatcher is also ActionProvider\r\n- Interoperable/Chainable Stores\r\n- Multiple Dispatchers\r\n- Built in ActionCreator\r\n- Quite fast\r\n- CommonJS, RequireJS ready\r\n- Middleware support (*new, since 1.1.0*)\r\n\r\n\u003e Hint: Have a look at [nanoflux-fusion](https://github.com/ohager/nanoflux-fusion), which is an extension for\r\n*nanoflux* providing a even more comfortable API inspired by [redux](http://redux.js.org/)\r\n\r\n\r\n# Comparison to Facebook's Implementation\r\n\r\nFrom an architectural point of view, the main difference is that [Facebook's Flux implementation](https://github.com/facebook/flux) provides \r\none central dispatcher, while __nanoflux__ supports also multiple dispatchers (if needed). Given that flexibility, it is possible to link multiple stores \r\nand multiple dispatchers, but IMHO this would only be a preferable scenario for really large applications. Additionally, it is also possible \r\n(as a built in feature) to link stores easily, so they can notify each other on changes (chaining).\r\n\r\nFor more comfort, __nanoflux__ supports a 'fluxy' way, which means, that a dispatcher provides actions directly without the need of a dedicated *ActionProvider*. \r\nThis can be quite handy in less complex applications and reduces much of boilerplate code. Of course, __nanoflux__  supports the original concept with separated *ActionProvider*. \r\n\r\nThe verbosity may be one of the 'weakest' aspects of Facebook's Flux: this is due to the fact, that Facebook provides the Dispatcher only. \r\nA *Store* and/or an *ActionProvider* is not part of their library, and therefore Facebook's Flux implementation is very lightweight, too. \r\nAnd even a bit smaller than __nanoflux__. The developer gains more liberty on implementation decisions, but for the costs of more work. \r\nFor example, it is left to the developer how stores and actions may interoperate, p.e. common approaches base on event emitters. \r\n\r\nIn this point __nanoflux__ offers slightly less flexibility with its convention based the dispatcher-store-binding, but is more comfortable.\r\n\r\nSince version 1.1.0 __nanoflux__ provides a middleware, which allows something like a payload data transformation pipeline, or dispatch inspection for logging, or debugging tools.\r\n\r\n# Size\r\n__nanoflux__ is a really tiny implementation, although it offers *much* more comfort than the reference implementation from Facebook.\r\n\r\n1. fb.flux.min.js       ca. 2 KiB \r\n2. nanoflux.min.js      ca. 3.5 KiB \r\n3. reflux.min.js        ca. 18 KiB \r\n4. delorean.min.js      ca 20 KiB\r\n5. alt.min.js           ca 23 KiB\r\n\r\n# Performance\r\n\r\n__nanoflux__  use synchronous function calls, that makes __nanoflux__ quite fast. Synchronous cycles guarantee consistent dispatch cycles.\r\n\r\nHere are some results of benchmarks for entire *action-dispatch-notify*-cycles:\r\n\r\n1. fbflux-perf: 163983.67 op/s (0.00 op/s) - 100.00%\r\n2. nanoflux-fluxy-perf: 157380.00 op/s (-6603.67 op/s) - 95.97%\r\n3. nanoflux-fullflux-perf: 151334.33 op/s (-12649.34 op/s) - 92.29%\r\n4. reflux-perf: 61861.33 op/s (-102122.34 op/s) - 37.72%\r\n5. alt-perf: 27704.33 op/s (-136279.34 op/s) - 16.89%\r\n6. delorean-perf: 9350.33 op/s (-154633.34 op/s) - 5.70%\r\n\r\nThe benchmark code is available under `./perf`.\r\n\r\nCurrently, all measuring is done server side using `nodejs` (listed results run on Dell XPS15 i7). \r\nI think it is slightly slower than Facebooks implementation, as __nanoflux__ uses a comfortable auto-binding, \r\nwithout verbose switch-case-statements like the Facebook version. Nevertheless, it should be fast enough :)\r\n\r\n# Example\r\n\r\nThe following example demonstrates the 'full' Flux approach, using ActionProvider, Dispatcher, and Store\r\n\r\n```javascript\r\n\r\n\tvar NanoFlux = require('nanoflux'); // UMD with browserify!\r\n\r\n    var setup = function() {\r\n    \r\n        // Creating a store 'myStore' with functions triggered by dispatched actions\r\n        // The convention for action handlers name is: on\u003cActionName\u003e\r\n        NanoFlux.createStore('myStore', {\r\n    \r\n            // the handlers signature bases on the users convention\r\n            onAction1: function (test) {\r\n                console.log(\"Store.onAction1: \" + test);\r\n                // this will call the subscribed callbacks\r\n                this.notify({data: test});\r\n            },\r\n    \r\n            onAction2: function (test) {\r\n                console.log(\"Store.onAction2: \" + test);\r\n                this.notify({data: test});\r\n            },\r\n    \r\n            onAction3: function (test) {\r\n                console.log(\"Store.onAction3: \" + test);\r\n                this.notify({data: test});\r\n            }\r\n        });\r\n\r\n\t\t// Creating the Dispatcher\r\n\t\t// You may also use the implicit default dispatcher: \r\n\t\t// var dispatcher = NanoFlux.getDispatcher();\r\n        var dispatcher = NanoFlux.createDispatcher('myDispatcher');\r\n        \r\n        // The full flux concept foresees a separation of actions and dispatcher\r\n        // Here we create actions using the built in action creator\r\n        NanoFlux.createActions('myActions', dispatcher, {\r\n            action1 : function(data){\r\n                console.log(\"Action 1\");\r\n                // this way, the dispatcher establishes dynamically the action binding, calling stores onAction1().\r\n                this.dispatch('action1', data);\r\n            },\r\n    \r\n            action2 : function(data){\r\n                console.log(\"Action 2\");\r\n                this.dispatch('action2', data);\r\n            }\r\n        });    \r\n    };\r\n```\r\n    \r\n    \r\n```javascript\r\n    \r\n    setup();\r\n    function Component(){\r\n    \r\n        // callback called by Store.notify\r\n        this.onNotify = function(data){\r\n            console.log(\"Component notified: \" + JSON.stringify(data));\r\n        };\r\n    \r\n        this.exec = function(){\r\n    \r\n                \r\n            var dispatcher = NanoFlux.getDispatcher('myDispatcher');\r\n            var store = NanoFlux.getStore('myStore');\r\n            var actions = NanoFlux.getActions('myActions'); \r\n            \r\n            // Now, connecting Store and Dispatcher\r\n            dispatcher.connectTo(store);\r\n            \r\n            // establishes the link between store's notification mechanism and this component.\r\n            // use the returned object to unsubscribe, if needed!\r\n            var subscription = store.subscribe(this, this.onNotify);\r\n    \r\n\t\t\t// executing the actions    \r\n            actions.action1(\"test 1\");\r\n            actions.action2(\"test 2\");\r\n        };\r\n    }   \r\n```\r\n\r\n\r\n## Middleware Example\r\n\r\nApplying middleware is as simple as licking ice cream on the beach:\r\n\r\n```javascript\r\nfunction Logger(){\r\n    var log = [];\r\n\r\n    return function(handlerName, args){\r\n        log.push({\r\n            handler: handlerName,\r\n            payload : args\r\n            }\r\n        )\r\n    }\r\n}\r\n\r\n// somewhere in your app --- using the fluxy approach for sake of simplicity\r\n// ...\r\nvar dispatcher = NanoFlux.createDispatcher(null, [\"action1\", \"action2\"]);\r\nNanoFlux.use(new Logger(), dispatcher);\r\n\r\ndispatcher.action1({foo:\"fromAction1\"});\r\n/* Log is:  [{handler: \"onAction1\", payload: [{foo:\"fromAction1\"}]}] */\r\n\r\ndispatcher.action2({foo:\"fromAction2\"});\r\n/* Final Log is:\r\n    [\r\n        {handler: \"onAction1\", payload: [{foo:\"fromAction1\"}]}\r\n        {handler: \"onAction2\", payload: [{foo:\"fromAction2\"}]}\r\n    ]\r\n*/\r\n\r\n```\r\n\r\n# Getting nanoflux\r\n\r\nYou may pick the library directly from ``./dist``, use ``npm install nanoflux``, or use ``bower install nanoflux``\r\n\r\n# Build your own\r\n\r\n1. Get sources: ``npm install nanoflux`` (or fork/clone this repo)\r\n2. Install dependencies: ``npm install``\r\n3. Build:\r\n  - ``gulp`` to build the minified and non-minified bundle in ``.\\dist``\r\n\r\nPronto!\r\n\r\n## Automated Testing\r\n\r\nThe gulp build chain runs tests only for the browserified __nanoflux__ module. \r\n\r\nAll tests can be run using `jasmine-node` or `npm run test`. \r\n\r\n\r\n# Available Node Tasks\r\n\r\nUse `npm run \u003ctask\u003e` to execute additional task. Available tasks are:\r\n \r\n- test : Runs all tests\r\n- benchmark : Runs a performance benchmark for different Flux Implementations. \r\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fohager%2Fnanoflux","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fohager%2Fnanoflux","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fohager%2Fnanoflux/lists"}