Revisions
-
ryanflorence revised this gist
Feb 6, 2015 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -6,7 +6,8 @@ Motivations - Clear feature ownership - Module usage predictibility (refactoring, maintainence, you know what's shared, what's not, prevents accidental regressions, avoids huge directories of not-actually-reusable modules, etc) - CI runs only the tests that matter (future) - Code splitting (future) -
ryanflorence revised this gist
Jan 20, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -207,7 +207,7 @@ do `require('components/Avatar')` no matter where you are. ### Tests Tests live next to the modules they test. Tests for `shared/util/createStore.js` live in `shared/util/__tests__/createStore.test.js`. Now our app has a bunch of `__tests__` directories: -
ryanflorence revised this gist
Jan 20, 2015 . 1 changed file with 0 additions and 247 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,247 +0,0 @@ -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 247 additions and 0 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,247 @@ Folder Structure ================ Motivations ----------- - Clear feature ownership - Module usage predictibility (refactoring, maintainence, you know what's shared, what's not, etc) - CI runs only the tests that matter (future) - Code splitting (future) How it works ------------ The file structure maps directly to the route hierarchy, which maps directly to the UI hierarchy. It's inverted from the model that we've used in other systems. If we consider all folders being either a "generic" or a "feature" folder, we only have one "feature" folder but many "generic" folders. Examples of "feature" folders: - Surveys - Admin - Users - Author Examples of "generic" folders: - components - helpers - stores - actions Given this route config: ```js var routes = ( <Route name="App"> <Route name="Admin"> <Route name="Users"/> <Route name="Reports"/> </Route> <Route name="Course"> <Route name="Assignments"/> </Route> </Route> ); ``` We would now set up our directories like this: ``` app └── screens └── App └── screens ├── Admin │ └── screens │ ├── Reports │ └── Users └── Course └── screens └── Assignments ``` Next, each of these screens has an `index.js` file, which is the file that handles the entry into the screen, also known as a "Route Handler" in react router. Its very much like a `Route` in Ember. We'll also have some top-level application bootstrapping stuff at the root, like `config/routes.js`. ``` app ├── config │ └── routes.js ├── screens │ └── App │ ├── screens │ │ ├── Admin │ │ │ ├── screens │ │ │ │ ├── Reports │ │ │ │ │ └── index.js │ │ │ │ └── Users │ │ │ │ └── index.js │ │ │ └── index.js │ │ └── Course │ │ ├── screens │ │ │ └── Assignments │ │ │ └── index.js │ │ └── index.js │ └── index.js └── index.js ``` With this structure, each screen has its own directory to hold its modules. In other words, we've introduced "scope" into our application file structure. Each will probably have a `components` directory. ``` app ├── config │ └── routes.js ├── screens │ └── App │ ├── components │ ├── screens │ │ ├── Admin │ │ │ ├── components │ │ │ ├── screens │ │ │ │ ├── Reports │ │ │ │ │ ├── components │ │ │ │ │ └── index.js │ │ │ │ └── Users │ │ │ │ ├── components │ │ │ │ └── index.js │ │ │ └── index.js │ │ └── Course │ │ ├── components │ │ ├── screens │ │ │ └── Assignments │ │ │ ├── components │ │ │ └── index.js │ │ └── index.js │ └── index.js └── index.js ``` These components are used *only in the current screen*, not even the child screens. So what about when you've got some shared components between screens? ### Shared Modules Every screen also has a "shared" generic directory. If its children share any components with each other or the parent, we put the shared code in "shared". Here is our growing app with some new shared, and not shared modules. ``` app ├── config │ └── routes.js ├── screens │ └── App │ ├── components │ ├── screens │ │ ├── Admin │ │ │ ├── components │ │ │ ├── screens │ │ │ │ ├── Reports │ │ │ │ │ ├── components │ │ │ │ │ ├── stores │ │ │ │ │ │ └── ReportsStore.js │ │ │ │ │ └── index.js │ │ │ │ └── Users │ │ │ │ ├── components │ │ │ │ └── index.js │ │ │ ├── shared │ │ │ │ └── stores │ │ │ │ ├── AccountStore.js │ │ │ │ └── UserStore.js │ │ │ └── index.js │ │ └── Course │ │ ├── components │ │ ├── screens │ │ │ └── Assignments │ │ │ ├── components │ │ │ └── index.js │ │ └── index.js │ ├── shared │ │ └── components │ │ ├── Avatar.js │ │ └── Icon.js │ └── index.js ├── shared │ └── util │ └── createStore.js └── index.js ``` Note `Admin/shared`; `Reports` and `Users` can both access the shared stores. Additionally, every screen in the app can use `Avatar.js` and `Icon.js`. We put shared components in the nearest `shared` directory possible and move it toward the root as needed. ### Shared module resolution The way modules in CommonJS are resolved is pretty straightforward in practice: its all relative from the current file. There is one piece of "magic" in the way modules resolve. When you do a non-relative require like `require('moment')` the resolver will first try to find it in `node_modules/moment`. If its not there, it will look in `../node_modules/moment`, and on up the tree until it finds it. We've made it so that `shared` resolves the same way with webpack `modulesDirectories`. This way you don't have to `require('../../../../../../../../../../shared/Avatar')` you can simply do `require('components/Avatar')` no matter where you are. ### Tests Tests live next to the modules they test. Tests for `shared/createStore.js` live in `shared/__tests__/createStore.test.js`. Now our app has a bunch of `__tests__` directories: ``` app ├── __tests__ ├── config │ └── routes.js ├── screens │ └── App │ ├── components │ │ ├── __tests__ │ │ │ └── AppView.test.js │ │ └── AppView.js ... etc. ├── shared │ └── util │ ├── __tests__ │ │ └── createStore.test.js │ └── createStore.js └── index.js ``` Since the folder structure tells you where the modules are used, we can configure CI to only run the tests in the `__tests__` directories of the changed files. ### Why "Screens"? The other option is "views", which has become a lot like "controller". What does it even mean? Screen seems pretty intuitive to me to mean "a specific screen in the app" and not something that is shared. It has the added benefit that there's no such thing as an "MSC" yet, so the word "screen" causes people to ask "what's a screen?" instead of assuming they know what a "view" is supposed to be. -
ryanflorence renamed this gist
Jan 19, 2015 . 1 changed file with 0 additions and 0 deletions.There are no files selected for viewing
File renamed without changes. -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 9 additions and 17 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,18 +1,17 @@ Folder Structure ================ Motivations ----------- - Clear feature ownership - Module usage predictibility (refactoring, maintainence, you know what's shared, what's not, etc) - CI runs only the tests that matter (future) - Code splitting (future) How it works ------------ The file structure maps directly to the route hierarchy, which maps directly to the UI hierarchy. @@ -135,7 +134,7 @@ These components are used *only in the current screen*, not even the child screens. So what about when you've got some shared components between screens? ### Shared Modules Every screen also has a "shared" generic directory. If its children share any components with each other or the parent, we put the shared @@ -190,7 +189,7 @@ stores. Additionally, every screen in the app can use `Avatar.js` and `Icon.js`. We put shared components in the nearest `shared` directory possible and move it toward the root as needed. ### Shared module resolution The way modules in CommonJS are resolved is pretty straightforward in practice: its all relative from the current file. @@ -205,7 +204,7 @@ We've made it so that `shared` resolves the same way with webpack `require('../../../../../../../../../../shared/Avatar')` you can simply do `require('components/Avatar')` no matter where you are. ### Tests Tests live next to the modules they test. Tests for `shared/createStore.js` live in `shared/__tests__/createStore.test.js`. @@ -234,18 +233,11 @@ app └── index.js ``` ### Why "Screens"? The other option is "views", which has become a lot like "controller". What does it even mean? Screen seems pretty intuitive to me to mean "a specific screen in the app" and not something that is shared. It has the added benefit that there's no such thing as an "MSC" yet, so the word "screen" causes people to ask "what's a screen?" instead of assuming they know what a "view" is supposed to be. -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -238,7 +238,7 @@ app The other option is "views", which has become a lot like "controller". What does it even mean? Screen seems pretty intuitive to me to mean "a specific screen in the app" and not something that is shared. It has the added benefit that there's no such thing as an "MSC" yet, so the word "screen" causes people to ask "what's a screen?" instead of assuming they know what a "view" is supposed to be. -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 4 additions and 3 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -200,9 +200,10 @@ non-relative require like `require('moment')` the resolver will first try to find it in `node_modules/moment`. If its not there, it will look in `../node_modules/moment`, and on up the tree until it finds it. We've made it so that `shared` resolves the same way with webpack `modulesDirectories`. This way you don't have to `require('../../../../../../../../../../shared/Avatar')` you can simply do `require('components/Avatar')` no matter where you are. #### Tests -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -192,8 +192,8 @@ move it toward the root as needed. #### Shared module resolution The way modules in CommonJS are resolved is pretty straightforward in practice: its all relative from the current file. There is one piece of "magic" in the way modules resolve. When you do a non-relative require like `require('moment')` the resolver will first -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -131,7 +131,7 @@ app └── index.js ``` These components are used *only in the current screen*, not even the child screens. So what about when you've got some shared components between screens? -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 3 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -131,8 +131,9 @@ app └── index.js ``` These components are used *only in the current screens*, not even the child screens. So what about when you've got some shared components between screens? #### Shared Modules -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 2 additions and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,7 +7,8 @@ Folder Structure ### Motivations - Clear feature ownership - Module usage predictibility (refactoring, maintainence, you know what's shared, what's not, etc) - CI runs only the tests that matter (future) - Code splitting (future) -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,9 +7,9 @@ Folder Structure ### Motivations - Clear feature ownership - Module usage predictibility (refactoring, maintainence, etc) - CI runs only the tests that matter (future) - Code splitting (future) ### How it works -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 3 additions and 3 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -1,5 +1,5 @@ Reactissance ============ Folder Structure ---------------- @@ -190,7 +190,7 @@ move it toward the root as needed. #### Shared module resolution The way modules in CommonJS are resolved is pretty straightforward: its all relative from the current file. There is one piece of "magic" in the way modules resolve. When you do a -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 2 additions and 4 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -96,10 +96,8 @@ app ``` With this structure, each screen has its own directory to hold its modules. In other words, we've introduced "scope" into our application file structure. Each will probably have a `components` directory. -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 8 additions and 4 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -233,10 +233,14 @@ app └── index.js ``` #### Why "Screens"? The other option is "views", which has become a lot like "controller". What does it even mean? Screen seems pretty intuitive to me to mean "a specific screen in the app" and not something that is shared, it has the added benefit that there's no such thing as an "MSC" yet, so the word "screen" causes people to ask "what's a screen?" instead of assuming they know what a "view" is supposed to be. Testing ------- -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 1 addition and 1 deletion.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -50,7 +50,7 @@ var routes = ( ); ``` We would now set up our directories like this: ``` app -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 1 addition and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -14,8 +14,7 @@ Folder Structure ### How it works The file structure maps directly to the route hierarchy, which maps directly to the UI hierarchy. It's inverted from the model that we've used in other systems. If we consider all folders being either a "generic" or a "feature" folder, we -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 2 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -8,8 +8,8 @@ Folder Structure - Clear feature ownership - Module Usage Predictibility (refactoring, maintainence, etc) - CI runs only the tests that matter (future) - Code Splitting (future) ### How it works -
ryanflorence revised this gist
Jan 19, 2015 . 1 changed file with 7 additions and 2 deletions.There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -7,7 +7,7 @@ Folder Structure ### Motivations - Clear feature ownership - Module Usage Predictibility (refactoring, maintainence, etc) - CI knows what tests to run (and ignore) - Code Splitting @@ -97,7 +97,12 @@ app ``` With this structure, each screen has its own directory to hold its modules. In otherwords, we've introduced "scope" into our application file structure. Each will probably have a `components` directory. ``` app -
ryanflorence created this gist
Jan 19, 2015 .There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode charactersOriginal file line number Diff line number Diff line change @@ -0,0 +1,242 @@ React Migration =============== Folder Structure ---------------- ### Motivations - Clear feature ownership - Code Usage Predictibility (refactoring, maintainence, etc) - CI knows what tests to run (and ignore) - Code Splitting ### How it works The file structure maps directly to the route hierarchy, which maps directly to the UI hierarchy, with unit tests for modules in a `__tests__` directory sibling to the modules. It's inverted from the model that we've used in other systems. If we consider all folders being either a "generic" or a "feature" folder, we only have one "feature" folder but many "generic" folders. Examples of "feature" folders: - Surveys - Admin - Users - Author Examples of "generic" folders: - components - helpers - stores - actions Given this route config: ```js var routes = ( <Route name="App"> <Route name="Admin"> <Route name="Users"/> <Route name="Reports"/> </Route> <Route name="Course"> <Route name="Assignments"/> </Route> </Route> ); ``` We would now set up our directires like this: ``` app └── screens └── App └── screens ├── Admin │ └── screens │ ├── Reports │ └── Users └── Course └── screens └── Assignments ``` Next, each of these screens has an `index.js` file, which is the file that handles the entry into the screen, also known as a "Route Handler" in react router. Its very much like a `Route` in Ember. We'll also have some top-level application bootstrapping stuff at the root, like `config/routes.js`. ``` app ├── config │ └── routes.js ├── screens │ └── App │ ├── screens │ │ ├── Admin │ │ │ ├── screens │ │ │ │ ├── Reports │ │ │ │ │ └── index.js │ │ │ │ └── Users │ │ │ │ └── index.js │ │ │ └── index.js │ │ └── Course │ │ ├── screens │ │ │ └── Assignments │ │ │ └── index.js │ │ └── index.js │ └── index.js └── index.js ``` With this structure, each screen has its own directory to hold its modules. Each will probably have a `components` directory. ``` app ├── config │ └── routes.js ├── screens │ └── App │ ├── components │ ├── screens │ │ ├── Admin │ │ │ ├── components │ │ │ ├── screens │ │ │ │ ├── Reports │ │ │ │ │ ├── components │ │ │ │ │ └── index.js │ │ │ │ └── Users │ │ │ │ ├── components │ │ │ │ └── index.js │ │ │ └── index.js │ │ └── Course │ │ ├── components │ │ ├── screens │ │ │ └── Assignments │ │ │ ├── components │ │ │ └── index.js │ │ └── index.js │ └── index.js └── index.js ``` These components are used *only in the current screens*. So what about when you've got some shared components between screens? #### Shared Modules Every screen also has a "shared" generic directory. If its children share any components with each other or the parent, we put the shared code in "shared". Here is our growing app with some new shared, and not shared modules. ``` app ├── config │ └── routes.js ├── screens │ └── App │ ├── components │ ├── screens │ │ ├── Admin │ │ │ ├── components │ │ │ ├── screens │ │ │ │ ├── Reports │ │ │ │ │ ├── components │ │ │ │ │ ├── stores │ │ │ │ │ │ └── ReportsStore.js │ │ │ │ │ └── index.js │ │ │ │ └── Users │ │ │ │ ├── components │ │ │ │ └── index.js │ │ │ ├── shared │ │ │ │ └── stores │ │ │ │ ├── AccountStore.js │ │ │ │ └── UserStore.js │ │ │ └── index.js │ │ └── Course │ │ ├── components │ │ ├── screens │ │ │ └── Assignments │ │ │ ├── components │ │ │ └── index.js │ │ └── index.js │ ├── shared │ │ └── components │ │ ├── Avatar.js │ │ └── Icon.js │ └── index.js ├── shared │ └── util │ └── createStore.js └── index.js ``` Note `Admin/shared`; `Reports` and `Users` can both access the shared stores. Additionally, every screen in the app can use `Avatar.js` and `Icon.js`. We put shared components in the nearest `shared` directory possible and move it toward the root as needed. #### Shared module resolution The way modules in common-js are resolved is pretty straightforward: its all relative from the current file. There is one piece of "magic" in the way modules resolve. When you do a non-relative require like `require('moment')` the resolver will first try to find it in `node_modules/moment`. If its not there, it will look in `../node_modules/moment`, and on up the tree until it finds it. We've made it so that `shared` resolves the same way. This way you don't have to `require('../../../../../../../../../../shared/Avatar')` you can simply do `require('components/Avatar')` no matter where you are. #### Tests Tests live next to the modules they test. Tests for `shared/createStore.js` live in `shared/__tests__/createStore.test.js`. Now our app has a bunch of `__tests__` directories: ``` app ├── __tests__ ├── config │ └── routes.js ├── screens │ └── App │ ├── components │ │ ├── __tests__ │ │ │ └── AppView.test.js │ │ └── AppView.js ... etc. ├── shared │ └── util │ ├── __tests__ │ │ └── createStore.test.js │ └── createStore.js └── index.js ``` Dev Workflow ------------ Testing ------- Flux ----