Skip to content

Instantly share code, notes, and snippets.

@dariye
Forked from ryanflorence/folder-structure.md
Created June 25, 2019 11:43

Revisions

  1. @ryanflorence ryanflorence revised this gist Feb 6, 2015. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion folder-structure.md
    Original 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, etc)
    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)

  2. @ryanflorence ryanflorence revised this gist Jan 20, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion folder-structure.md
    Original 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/createStore.js` live in `shared/__tests__/createStore.test.js`.
    `shared/util/createStore.js` live in `shared/util/__tests__/createStore.test.js`.

    Now our app has a bunch of `__tests__` directories:

  3. @ryanflorence ryanflorence revised this gist Jan 20, 2015. 1 changed file with 0 additions and 247 deletions.
    247 changes: 0 additions & 247 deletions migration.md
    Original file line number Diff line number Diff line change
    @@ -1,247 +0,0 @@
    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.
  4. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 247 additions and 0 deletions.
    247 changes: 247 additions & 0 deletions migration.md
    Original 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.
  5. @ryanflorence ryanflorence renamed this gist Jan 19, 2015. 1 changed file with 0 additions and 0 deletions.
    File renamed without changes.
  6. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 9 additions and 17 deletions.
    26 changes: 9 additions & 17 deletions migration.md
    Original file line number Diff line number Diff line change
    @@ -1,18 +1,17 @@
    Reactissance
    ============

    Folder Structure
    ----------------
    ================

    ### Motivations
    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
    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
    ### 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
    ### 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

    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"?
    ### 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
    -------

    Flux
    ----

  7. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion migration.md
    Original 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
    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.
  8. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 4 additions and 3 deletions.
    7 changes: 4 additions & 3 deletions migration.md
    Original 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. This way you don't
    have to `require('../../../../../../../../../../shared/Avatar')` you can
    simply do `require('components/Avatar')` no matter where you are.
    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

  9. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions migration.md
    Original 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: its
    all relative from the current file.
    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
  10. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion migration.md
    Original file line number Diff line number Diff line change
    @@ -131,7 +131,7 @@ app
    └── index.js
    ```

    These components are used *only in the current screens*, not even the
    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?

  11. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 3 additions and 2 deletions.
    5 changes: 3 additions & 2 deletions migration.md
    Original 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*. So what about
    when you've got some shared components between screens?
    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

  12. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 2 additions and 1 deletion.
    3 changes: 2 additions & 1 deletion migration.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,8 @@ Folder Structure
    ### Motivations

    - Clear feature ownership
    - Module usage predictibility (refactoring, maintainence, etc)
    - 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)

  13. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions migration.md
    Original 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)
    - Module usage predictibility (refactoring, maintainence, etc)
    - CI runs only the tests that matter (future)
    - Code Splitting (future)
    - Code splitting (future)

    ### How it works

  14. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions migration.md
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,5 @@
    React Migration
    ===============
    Reactissance
    ============

    Folder Structure
    ----------------
    @@ -190,7 +190,7 @@ move it toward the root as needed.

    #### Shared module resolution

    The way modules in common-js are resolved is pretty straightforward: its
    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
  15. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 2 additions and 4 deletions.
    6 changes: 2 additions & 4 deletions migration.md
    Original 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 otherwords, we've introduced "scope" into our application file
    structure.
    modules. In other words, we've introduced "scope" into our application
    file structure.

    Each will probably have a `components` directory.

  16. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 8 additions and 4 deletions.
    12 changes: 8 additions & 4 deletions migration.md
    Original file line number Diff line number Diff line change
    @@ -233,10 +233,14 @@ app
    └── index.js
    ```

    Dev Workflow
    ------------


    #### 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
    -------
  17. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion migration.md
    Original file line number Diff line number Diff line change
    @@ -50,7 +50,7 @@ var routes = (
    );
    ```

    We would now set up our directires like this:
    We would now set up our directories like this:

    ```
    app
  18. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 1 addition and 2 deletions.
    3 changes: 1 addition & 2 deletions migration.md
    Original 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, with unit tests for modules in a
    `__tests__` directory sibling to the modules.
    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
  19. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 2 additions and 2 deletions.
    4 changes: 2 additions & 2 deletions migration.md
    Original 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 knows what tests to run (and ignore)
    - Code Splitting
    - CI runs only the tests that matter (future)
    - Code Splitting (future)

    ### How it works

  20. @ryanflorence ryanflorence revised this gist Jan 19, 2015. 1 changed file with 7 additions and 2 deletions.
    9 changes: 7 additions & 2 deletions migration.md
    Original file line number Diff line number Diff line change
    @@ -7,7 +7,7 @@ Folder Structure
    ### Motivations

    - Clear feature ownership
    - Code Usage Predictibility (refactoring, maintainence, etc)
    - 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. Each will probably have a `components` directory.
    modules.

    In otherwords, we've introduced "scope" into our application file
    structure.

    Each will probably have a `components` directory.

    ```
    app
  21. @ryanflorence ryanflorence created this gist Jan 19, 2015.
    242 changes: 242 additions & 0 deletions migration.md
    Original 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
    ----