Skip to content

Instantly share code, notes, and snippets.

@azinit
Last active November 14, 2020 11:03
Show Gist options
  • Save azinit/81e382a1a8bc5e4e0f8445fb5573305c to your computer and use it in GitHub Desktop.
Save azinit/81e382a1a8bc5e4e0f8445fb5573305c to your computer and use it in GitHub Desktop.
React app files structure

Structure

At the moment I prefer Feature Driven Development for projects structuring.

Principles

  • low coupling
    • feature should not depend from other features
    • page should not depend from other pages
    • shared resources should not depend from each other
  • all needed resources (store / async effects / components) - locate in features/ dir
  • all common used resources (components / helpers / fixtures) - locate in shared/ dir
  • about pre-optimization
    • not need to strive to optimize modules for changing
      • because of we can't predict future
    • instead of this - it's desirable to optimize their for deleting
      • because of it's only one thing we know - that all code transform to chaos =)
      • and it's easier to refactor totally (clean up) only few modules, instead of one app totally

more details

Root

└── src/                            # Source files
    ├── app/                        # Base app's resources
    ├── features/                   # Crucial domain splitted app's features
    ├── pages/                      # App's pages (build from features, shared)
    └── shared/                     # Common used modules for dev

Feature

Feature - a self-contained, user-facing, (maybe) reusable between pages and complex logic contained building block (module).

More details - here

└── features/
    └── feature-name/
            ├── components/            # UI components (`React`, `Canvas`)
            ├── {store/}               # (optional) Store of feature (redux)
            ├── {context/}             # (optional) Store of feature (context)
            ├── {**.gql}               # (optional) Feature request (graphql)
            ├── {**.gen.ts}            # (optional) Feature request (apollo hook generated)
            ├── {...}/                 # (optional) Potentially, you can locate here and other **required** modules (but without fanaticism)
            └── index.ts               # Feature's `entry-point` (with declared public feature's API)

API

  • src/models.gen.ts - generated models types from graphql schema
  • src/{path/to/feature}/{query}.gql - request file (query / mutation) for fetch / post information by server API
  • src/{path/to/feature}/{query}.gen.ts - READONLY module with generated ts code of related request (in same dir with same name)

Usage:

Use requests

import { useTodoQuery } from "./queries.gen";
...
function YourComponent(props: Props) {
    const { data, loading, error } = useTodoQuery({ variables: { id }});
    ...
}

Use models

// Non runtime imports (better)
import("models.gen").Claim
// ES2015 module imports (little bit worse, since without runtime code)
import { Claim } from "models.gen"

codegen by @graphql-codegen, more details in codegen.yml

Shared

Shared module - everything that:

  • Needed in at least 2 places
  • Has non-trivial logic
  • Has low frequency of change
└── shared/
   ├── components/             #   **Common used** React components
   ├── helpers/                #   **Common used** Helpers
   ├── hocs/                   #   **Common used** React HOCs
   ├── hooks/                  #   **Common used** React Hooks
   ├── fixtures/               #   **Common used** data helpers / dataSets
   ├── get-env                 #   Module with **env**-vars
   ├── mixins.scss             #   **Common used** SCSS mixins
   └── consts.scss             #   **Common used** SCSS consts (not colors)

There is public API declaration file (index.ts) in all shared modules (with module's API for other modules)

Recommends to get all needed submodules namely with its

Other words, if you want to import common component Loader:

// Bad (private module path using)
import Loader from "shared/components/loader";
// Good (API is controlled by module entry-point file)
import { Loader } from "shared/components";

Shared/Assets

Perfectly, all static assets files should locate on related components level (on using level).

Because of - generally - there is own unique icons collection for every UI area

If its very necesary and matter for you - to have common-used icons, then locate their in shared folder (in this case - you can import them from any point of app)

└── shared/
      ├── assets/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment