{"action":"created","issue":{"url":"https://api.github.com/repos/davezuko/react-redux-starter-kit/issues/684","repository_url":"https://api.github.com/repos/davezuko/react-redux-starter-kit","labels_url":"https://api.github.com/repos/davezuko/react-redux-starter-kit/issues/684/labels{/name}","comments_url":"https://api.github.com/repos/davezuko/react-redux-starter-kit/issues/684/comments","events_url":"https://api.github.com/repos/davezuko/react-redux-starter-kit/issues/684/events","html_url":"https://github.com/davezuko/react-redux-starter-kit/pull/684","id":145100732,"number":684,"title":"Fractal Project Structure","user":{"login":"justingreenberg","id":1539088,"avatar_url":"https://avatars.githubusercontent.com/u/1539088?v=3","gravatar_id":"","url":"https://api.github.com/users/justingreenberg","html_url":"https://github.com/justingreenberg","followers_url":"https://api.github.com/users/justingreenberg/followers","following_url":"https://api.github.com/users/justingreenberg/following{/other_user}","gists_url":"https://api.github.com/users/justingreenberg/gists{/gist_id}","starred_url":"https://api.github.com/users/justingreenberg/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/justingreenberg/subscriptions","organizations_url":"https://api.github.com/users/justingreenberg/orgs","repos_url":"https://api.github.com/users/justingreenberg/repos","events_url":"https://api.github.com/users/justingreenberg/events{/privacy}","received_events_url":"https://api.github.com/users/justingreenberg/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":21,"created_at":"2016-04-01T06:44:50Z","updated_at":"2016-04-18T14:25:59Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/davezuko/react-redux-starter-kit/pulls/684","html_url":"https://github.com/davezuko/react-redux-starter-kit/pull/684","diff_url":"https://github.com/davezuko/react-redux-starter-kit/pull/684.diff","patch_url":"https://github.com/davezuko/react-redux-starter-kit/pull/684.patch"},"body":" RFC: Fractal Project Structure\r\n\r\nPlease provide feedback! [Structure excerpt from README](https://github.com/justingreenberg/react-redux-starter-kit/tree/fractal) (Updated 4/11/16):\r\n\r\n```\r\n.\r\n├── bin                      # Build/Start scripts\r\n├── blueprints               # Blueprint files for redux-cli\r\n├── build                    # All build-related configuration\r\n│   └── webpack              # Environment-specific configuration files for webpack\r\n├── config                   # Project configuration settings\r\n├── interfaces               # Type declarations for Flow\r\n├── server                   # Koa application (uses webpack middleware)\r\n│   └── main.js              # Server application entry point\r\n├── src                      # Application source code\r\n│   ├── main.js              # Application bootstrap and rendering\r\n│   ├── components           # Reusable Presentational Components\r\n│   ├── containers           # Reusable Container Components\r\n│   ├── layouts              # Components that dictate major page structure\r\n│   ├── static               # Static assets (not imported anywhere in source code)\r\n│   ├── styles               # Application-wide styles (generally settings)\r\n│   ├── store                # Redux-specific pieces\r\n│   │   ├── createStore.js   # Create and instrument redux store\r\n│   │   └── reducers.js      # Reducer registry and injection\r\n│   └── routes               # Main route definitions and async split points\r\n│       ├── index.js         # Bootstrap main application routes with store\r\n│       ├── Root.js          # Wrapper component for context-aware providers\r\n│       ├── Home             # Fractal route\r\n│       │   ├── index.js     # Route definitions and async split points\r\n│       │   ├── assets       # Assets required to render components\r\n│       │   ├── components   # Presentational React Components\r\n│       │   ├── container    # Connect components to actions and store\r\n│       │   ├── modules      # Collections of reducers/constants/actions\r\n│       │   └── routes **    # Fractal sub-routes (** optional)\r\n│       └── NotFound         # Capture unknown routes in component\r\n└── tests                    # Unit tests\r\n```\r\n\r\n#### Fractal App Structure\r\n\r\n_Also known as: Self-Contained Apps, Recursive Route Hierarchy, Providers, etc_\r\n\r\nSmall applications can be built using a flat directory structure, with folders for `components`, `containers`, etc. However, this structure does not scale and can seriously affect development velocity as your project grows. Starting with a fractal structure allows your application to organically drive it's own architecture from day one.\r\n\r\nWe use `react-router` [route definitions](https://github.com/reactjs/react-router/blob/master/docs/API.md#plainroute) (`<route>/index.js`) to define units of logic within our application. *Additional child routes can be nested in a fractal hierarchy.*\r\n\r\nThis provides many benefits that may not be immediately obvious:\r\n- Routes can be be bundled into \"chunks\" using webpack's [code splitting](https://webpack.github.io/docs/code-splitting.html) and merging algorithm. This means that the entire dependency tree for each route can be omitted from the initial bundle and then loaded *on demand*.\r\n- Since logic is self-contained, routes can easily be broken into separate repositories and referenced with webpack's [DLL plugin](https://github.com/webpack/docs/wiki/list-of-plugins#dllplugin) for flexible, high-performance development and scalability.\r\n\r\nLarge, mature apps tend to naturally organize themselves in this way—analogous to large, mature trees (as in actual trees :evergreen_tree:). The trunk is the router, branches are route bundles, and leaves are views composed of common/shared components/containers. Global application and UI state should be placed on or close to the trunk (or perhaps at the base of a huge branch, eg. `/app` route).\r\n\r\n##### Layouts\r\n- Stateless components that dictate major page structure\r\n- Useful for composing `react-router` [named components](https://github.com/reactjs/react-router/blob/master/docs/API.md#components-1) into views\r\n\r\n##### Components\r\n- Prefer [stateless function components](https://facebook.github.io/react/docs/reusable-components.html#stateless-functions)\r\n  - eg: `const HelloMessage = ({ name }) => <div>Hello {name}</div>`\r\n- Top-level `components` and `containers` directories contain reusable components\r\n\r\n##### Containers\r\n- Containers **only** `connect` presentational components to actions/state\r\n  - Rule of thumb: **no JSX in containers**!\r\n- One or many container components can be composed in a stateless function component\r\n- Tip: `props` injected by `react-router` can be accessed using `connect`:\r\n  ```js\r\n    // CounterMusicQueryContainer.js\r\n    import { connect } from 'react-redux'\r\n    import Counter from 'components/Counter'\r\n\r\n    export default connect((state, ownProps) => ({\r\n      counter: state.counter,\r\n      music: ownProps.location.query.music // why not?\r\n    }))(Counter)\r\n\r\n    // Location -> 'localhost:3000/counter?music=reggae'\r\n    // Counter.props = { counter: 0, music: 'reggae' }\r\n  ```\r\n\r\n##### Routes\r\n- A route directory...\r\n  - *Must* contain an `index.js` that returns route definition\r\n  - **Optional:** assets, components, containers, redux modules, nested child routes\r\n  - Additional child routes can be nested within `routes` directory in a fractal hierarchy.\r\n\r\nNote: This structure is designed to provide a flexible foundation for module bundling and dynamic loading. **Using a fractal structure is optional—smaller apps might benefit from a flat routes directory**, which is totally cool! Webpack creates split points based on static analysis of `require` during compilation; the recursive hierarchy folder structure is simply for organizational purposes.\r\n\r\n-\r\n\r\n#### Todo (Updated 4/11/16):\r\n\r\n  - [ ] update `blueprints` and related `redux-cli` docs \r\n  - [ ] update `.flowconfig` and related files\r\n\r\n#### Summary:\r\n- [x] **Migrate to a Fractal Project Structure**\r\n  - [x] Code-splitting and async reducers, demo:\r\n      - Watch network tab and redux extension\r\n      - Navigate to `/counter` route\r\n      - Async chunks load over network and reducers are injected into store\r\n  - [x] Add some tests for new components\r\n    - [x] **Update current tests** to use enzyme APIs correctly (all except CoreLayout, I think)\r\n  - [x] Update project structure\r\n  - [x] [Update README with some explanation](https://github.com/justingreenberg/react-redux-starter-kit/tree/fractal#structure)\r\n- [x] **Use pure Webpack HMR**\r\n  - [x] Apply necessary `module.hot` instrumentation \r\n  - [x] Remove `react-transform` babel plugin from development builds\r\n  - [x] Use `redbox-react` to display render errors\r\n  - [x] Update to `React-v15.0.0`\r\n- [x] **Remove Redux DevTools Components**\r\n  - [x] [Update README to recommend chrome extension, provide recipe](https://github.com/justingreenberg/react-redux-starter-kit/tree/fractal#redux-devtools)\r\n  - [x] Remove packages, components, integrations\r\n- [x] **Improve idiomatic use of react and redux**\r\n  - [x] [Update README with recommendations and rationale](https://github.com/justingreenberg/react-redux-starter-kit/tree/fractal#layouts)\r\n  - [x] Update components and containers to follow recommended patterns\r\n\r\n-\r\n\r\nPlease leave questions/comments"},"comment":{"url":"https://api.github.com/repos/davezuko/react-redux-starter-kit/issues/comments/211403006","html_url":"https://github.com/davezuko/react-redux-starter-kit/pull/684#issuecomment-211403006","issue_url":"https://api.github.com/repos/davezuko/react-redux-starter-kit/issues/684","id":211403006,"user":{"login":"xquezme","id":814506,"avatar_url":"https://avatars.githubusercontent.com/u/814506?v=3","gravatar_id":"","url":"https://api.github.com/users/xquezme","html_url":"https://github.com/xquezme","followers_url":"https://api.github.com/users/xquezme/followers","following_url":"https://api.github.com/users/xquezme/following{/other_user}","gists_url":"https://api.github.com/users/xquezme/gists{/gist_id}","starred_url":"https://api.github.com/users/xquezme/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/xquezme/subscriptions","organizations_url":"https://api.github.com/users/xquezme/orgs","repos_url":"https://api.github.com/users/xquezme/repos","events_url":"https://api.github.com/users/xquezme/events{/privacy}","received_events_url":"https://api.github.com/users/xquezme/received_events","type":"User","site_admin":false},"created_at":"2016-04-18T14:25:59Z","updated_at":"2016-04-18T14:25:59Z","body":">Use pure Webpack HMR\r\n\r\nhttps://github.com/gaearon/react-hot-loader/commit/0cb9e65068f44a83dc315432864301f5dbd5fc9d"}}