Project Structure

├── src
   ├── assets
      ├── images
      ├── css
      ├── js
      └── media
   ├── config
      ├── index.js
      └── default.js
   ├── components
      ├── Button
      ├── Input
      ├── Text
      ├── Link
      └── ...
   ├── containers
      ├── ThemeProvider
      ├── LocaleProvider
      ├── Layout
      ├── SignInForm
      └── ...
   ├── pages
      ├── SignIn
      ├── SignUp
      ├── Home
      ├── OrderDetails
      └── ...
   ├── hooks
      ├── useToggle.js
      ├── useEventListener.js
      ├── useResponsive.js
      ├── useLocale.js
      └── ...
   ├── services
      ├── user.js
      ├── order.js
      └── ...
   ├── store
      ├── index.js (exports `configureStore`)
      ├── redux
         ├── index.js (exports `rootReducer` here)
         └── *.js (namespaced reducer such as `app`, `user`, ...)
      └── sagas
          ├── index.js (exports `rootSaga` here)
          └── *.js (namespace-related saga such as `app`, `user`, ...)
   ├── utils
      ├── helpers.js
      ├── constants.js
      ├── request.js (prepare a http client)
      ├── firebase.js
      └── ...
   ├── routes.js
   ├── app.js

/src/config

/index.js

const config = {
  env: process.env.NODE_ENV || 'development',
  get isProd() {
    return this.env === 'production'
  },
  isBrowser: typeof window === 'object',
  api: {
    backend: {
      host: process.env.HOST,
      port: process.env.PORT,
      get url() {
        return `${this.host}:${this.port}`
      },
    },
    cms: {
      host: process.env.CMS_HOST,
      port: process.env.CMS_PORT,
      get url() {
        return `${this.host}:${this.port}`
      },
    },
  },
}

prepare default config values in default.js in case of development environment

/src/store/index.js

import { createStore, applyMiddleware, compose } from 'redux'
import createSagaMiddleware from 'redux-saga'
import { routerMiddleware } from 'connected-react-router'

import config from '../config'
import history from '../utils/history'
import createRootReducer from './redux'
import rootSaga from './sagas'

const initStore = (initialState = {}) => {
  let composeEnhancers = compose
  if (!config.isProd) {
    composeEnhancers = require('redux-devtools-extension').composeWithDevTools
  }

  const sagaMiddleware = createSagaMiddleware()

  const middlewares = [
    routerMiddleware(history),
    sagaMiddleware,
  ]

  const enhancers = [applyMiddleware(...middlewares)]

  const store = createStore(
    createRootReducer(history),
    initialState,
    composeEnhancers(...enhancers),
  )

  store.sagaTask = sagaMiddleware.run(rootSaga)

  return store
}

export default initStore

/src/store/sagas/index.js

import { all } from 'redux-saga/effects'

import appSagas from './app'
import userSagas from './user'
import orderSagas from './order'

export default function* root() {
  yield all([
    ...appSagas,
    ...userSagas,
    ...orderSagas,
  ])
}

Last updated