{"id":16296002,"url":"https://github.com/naugtur/backbone-redux-migrator","last_synced_at":"2025-03-20T04:31:11.032Z","repository":{"id":66078510,"uuid":"80308846","full_name":"naugtur/backbone-redux-migrator","owner":"naugtur","description":"Lets Backbone and Redux apps coexist, so you don't have to rewrite everything at once","archived":false,"fork":false,"pushed_at":"2020-05-25T20:57:13.000Z","size":55,"stargazers_count":23,"open_issues_count":3,"forks_count":2,"subscribers_count":4,"default_branch":"master","last_synced_at":"2025-03-17T14:49:00.711Z","etag":null,"topics":["backbone","data-flow","javascript-fatigue","migration","react","redux"],"latest_commit_sha":null,"homepage":null,"language":"JavaScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"apache-2.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/naugtur.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2017-01-28T20:30:55.000Z","updated_at":"2021-06-14T15:39:42.000Z","dependencies_parsed_at":"2023-02-20T17:15:32.068Z","dependency_job_id":null,"html_url":"https://github.com/naugtur/backbone-redux-migrator","commit_stats":{"total_commits":23,"total_committers":3,"mean_commits":7.666666666666667,"dds":"0.17391304347826086","last_synced_commit":"ff09483984806d95569fd5cc106e3695aba04cec"},"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naugtur%2Fbackbone-redux-migrator","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naugtur%2Fbackbone-redux-migrator/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naugtur%2Fbackbone-redux-migrator/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/naugtur%2Fbackbone-redux-migrator/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/naugtur","download_url":"https://codeload.github.com/naugtur/backbone-redux-migrator/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":244552304,"owners_count":20471049,"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":["backbone","data-flow","javascript-fatigue","migration","react","redux"],"created_at":"2024-10-10T20:20:53.319Z","updated_at":"2025-03-20T04:31:11.027Z","avatar_url":"https://github.com/naugtur.png","language":"JavaScript","funding_links":[],"categories":[],"sub_categories":[],"readme":"# backbone-redux-migrator\n\n[![Greenkeeper badge](https://badges.greenkeeper.io/naugtur/backbone-redux-migrator.svg)](https://greenkeeper.io/)\n[![Build Status](https://travis-ci.org/naugtur/backbone-redux-migrator.svg?branch=master)](https://travis-ci.org/naugtur/backbone-redux-migrator)\n\nA tool for migrating from Backbone stack to react+redux without disturbing the project or putting it on hold for a rewrite.\n\nLets Backbone and Redux apps coexist, so you can write new features in redux and continue with regular releases while a rewrite is progressing.\n\n## Migration path\n\n*Initial state:*\nYou have a Backbone or Backbone+Marionette app to migrate away from\n\n0. Learn how redux works, at least a tiny bit (embrace a world where inheritance and event emitters are not the way)\n1. Create a redux app and embed it in your old stack\n2. Rewrite one view to redux\n  - use as many components as you want in place of one complex view\n  - use one-way data flow in redux and fetch the data separately, forget Backbone models\n  - use migrator's simple view generator to plug your redux app in Backbone and point to the right component\n3. Delete old view, delete its model if nothing else uses it\n4. If any Backbone views left, goto 2\n5. With all the app rewritten, remove Backbone routing and layout. Replace `Chooser` with router of your choice\n\n*Final state:*\nAll features rewritten to redux, project is still alive, people stopped avoiding your job offers.\n\nOne more tip: You don't have to rewrite your whole single page app, just split it into more apps. People will accept a page load when going from main application to settings.\n\n\n## Installation\n```\nnpm install backbone-redux-migrator\n```\n\nbackbone-redux-migrator requires `react` and `react-redux` installed in the project. It's not listing them as dependencies in package.json, so you don't end up having duplicated dependencies when you use a different version of react or old version of `npm`.\n\n## API\n\n### Backbone side\n`require(\"backbone-redux-migrator\")`: `migrator` factory function that wraps your redux app\n\n`migrator` instance API exposes functionalities to Backbone:\n- `getView` - returns a View class for displaying redux app within Backbone layout\n- `getViewMarionetteCompat` - returns a View class that uses Marionette's `onRender` and `onDestroy` instead of `render`. Use it only if getView breaks your complicated Marionette view logic.\n- `getModelReadonly` - returns a Model class for reading store\n- `dispatchAction` - dispatches a redux action\n\n### Redux side\n\n\"backbone-redux-migrator/Chooser\" exports `Chooser`, `ConnectedChooser`, `Choice` components\n\n## Usage\n\nIn your main redux app entrypoint reduxMain.js\n```js\n/* all the redux dependencies would also be here */\nimport {ConnectedChooser, Choice} from \"backbone-redux-migrator/Chooser\"\nimport migrator from \"backbone-redux-migrator\"\n\n//I bet you have a nicer way to pass it to Backbone app, but I didn't want to add a build system in readme\nwindow.Backbone.reduxApp = migrator({/*options*/}, function(renderRoot, choiceReducer){\n\n  const createStoreWithMiddleware = applyMiddleware(...middleware)(createStore);\n  store = createStoreWithMiddleware(combineReducers({\n      /* your reducers here */\n      choice: choiceReducer\n  }));\n\n  ReactDOM.render(\n      \u003cProvider store={ store }\u003e\n          \u003cConnectedChooser\u003e\n            \u003cChoice name=\"home\"\u003e\n              \u003cMyHomeComponent /\u003e\n            \u003c/Choice\u003e\n            \u003cChoice name=\"item\"\u003e\n              \u003cMyItemComponent /\u003e\n            \u003c/Choice\u003e\n          \u003c/ConnectedChooser\u003e\n      \u003c/Provider\u003e,\n      renderRoot\n  );\n\n  return store; //This is very important!\n})\n```\n\nNow in Backbone/Marionette app just get a view and use it without a model\n```js\nvar reduxHomeView = Backbone.reduxApp.getView(\"home\")\nvar reduxHomeView = Backbone.reduxApp.getViewMarionetteCompat(\"home\", CustomView)\n\n//IF inheriting from a complex Marionette view that didn't work for you with getView\nvar reduxHomeViewMarionetteCompatible = Backbone.reduxApp.getViewMarionetteCompat(\"home\", Backbone.Marionette.ItemView)\n```\n\nHow do I render a parametrized item view if I can only choose components by name?\nThe redux way - by setting it in store using an action.\n```js\nBackbone.reduxApp.dispatchAction({ type: SET_ITEM, item: itemId })\n```\n\n### Chooser use pattern\n\n`ConnectedChooser` is using `connect` from `react-redux` to automatically retrieve the choice from your store. If you decide to use a different key in your store instead of `choice` you can import `Chooser` and wrap it in `connect` on your own. You can also use `Chooser` directly. It requires you to pass `chosen` property.\n\n### Store based model\n\n*Readonly access to store form Backbone app*\n\nSometimes, when you rewrite a functionality to redux side it turns out that something else depended on reading a field from your functionality's model. You can provide a model based on redux store contents, which will update from store on every `fetch()` call.\n\nThe model calls `fetch()` in `initialize`, so it should be ready to use without calling `fetch()` manually.\n\n\n```js\nvar HomeTilesModel = Backbone.reduxApp.getModelReadonly(function mapStateToModel(state){\n  return state.home.tiles\n})\nvar customModel = Backbone.reduxApp.getModelReadonly(function mapStateToModel(state){ /* ... */ }, CustomModelClass)\n```\n\n\n# Who took this migration path\n*Let me know if you're also migrating!*\n\n[![Egnyte Imc.](http://egnyte.com/assets/2015/images/logo.png)](https://egnyte.com/)\n\n\n\n----\n\n# QYMH\nQuestions You Might Have\n\n### Why not pass full routing path from Backbone to redux?\n\nThat would require forcing consumers of this library to use react-router (or any other router I integrate with, but not their choice). Letting Backbone app dispatch actions seems like a good replacement and is much more versatile. Any parametrized route can be a field in store instead.\n\nWith the right reducers in place, one can even push content of a fetched model into the redux app to save some http requests using `dispatchAction`. But this is only recommended if you're in the process of rewriting multiple views to react+redux and some still need the model.\n\n### How do I pass data from Backbone app to redux app so that it doesn't have to be fetched twice?\n\nSee paragraph above :)\n\n### How does this compare to Backbone-React mixins/bridges?\n\nWhen they were first created, react mixins/bridges for Backbone were very promising. They enabled a lot of good rewrites of ugly views to reusable Rect components, but they didn't eliminate the complexity of 2way bindings. Many projects found them to be a dead-end, with all the component lifecycle functions to connect to models and mistakes in event handling causing bursts of re-renders.\n\nThis migrator package is aiming at letting you build a new redux app inside existing codebase, but in total isolation in terms of data flows. Backbone keeps the routing (and probably main layout) while your redux rewrite is growing.\n\nAlso, backbone-redux-migrator is sooo much simpler.\n\n### How do I communicate from redux to Backbone?\n\n`window.location` updates to change route.\nYou can use store based model to get data that redux app fetched from the server.\n\nHopefully you won't need anything else.\n\nI didn't find a way to communicate back that wouldn't introduce unwanted dependencies or \"magic\" into your nice new redux app. But if I figure it out, I'll let you know.\n\n\n### Why can't the store based model accept writes?\n\nIt could, but the aim of this library is to help migrating away from old codebase, so all features here are focused on making sure redux app can be easily separated and doesn't depend on any behavior logic from Backbone side except routing.\n\n#### Are you aware that store based model + dispatchAction is enough to try to use redux from Backbone and only implement reducers?\n\nYes, but if that was a good idea, I would have implemented it in the store based model.\n\nI'm sure if you try, it can get ugly really fast. Please don't do it. :) Feel free to get in touch for suggestions on how to avoid this.\n\n## Roadmap\n\n- add a step-by-step migration example\n- add helpful warnings\n- continue to look for ways to let redux app use a router of any kind\n- ~~write tests to encourage collaboration~~\n- ~~add a way to communicate from redux to Backbone with which it's not easy to shoot yourself in a foot.~~ with store based model it should be enough.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaugtur%2Fbackbone-redux-migrator","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fnaugtur%2Fbackbone-redux-migrator","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fnaugtur%2Fbackbone-redux-migrator/lists"}