Node 9+
$ npm install -g eslint jest now
$ npm install
$ npm install --save-dev husky prettier-eslint
In order to start, just execute the following command line:
$ npm run dev
And then, open a browser with the following link:
http://localhost:3000
$ npm run test
$ npm run test:watch
-
Re-Ducks: Following this proposal structure improve modularity and encapsulation (only expose
index.tsx
from each dock folder, for instance:state/ducks/catalog/index.ts
). Also allow us to scale better and improve testability of actions, action creators, reducers, operators and selectors in a really flexible way. -
In order to be easy to search your resources, the file name conventions of the project is the following:
- [module_name].[type-file].ts Eg:
article.actions.ts
article.d.ts
article.operations.ts
article.reducers.ts
article.selectors.ts
- etc
-
Typescript: Implementing check typing in a dynamic interpreted language like JS, help us and also to Ides, to catch typos and errors while your are coding. That is a really important when you app will be large.
-
Selectors (
selectors
): Implementing selectors improve complex operations and also to lifting our state in a more granular way (help us to keep following SRP principle). Also we open a windows of improvements to implementreselect
or other mechanism of memoization. -
Selectors naming convention:
Selector name: get<Noun>
-
Following top down best practice redeability declaration (most important and public collaborates first, like a news paper).
-
BEM: using block element modifier and with some variation of SMACSS like (
is-visible
instead ofblock--visible
) is a really clean way to style components. Also it's a really a performance way to style component instead use neested selectors. (you don't care any more about not pass to 3 nested level) -
Server: the end-point should be prefixed with:
/api/v1
. That help us to versioning our API, and also to be a common pre-fix url to apply easy filters, middlewares, etc. -
REST calls in a middleware, instead of action creators: That allow us to decrease the coupling between our action creators and the side-effect libraries(
redux-thunk
,redux-saga
,redux-observable
, etc). Also make test simpler and our modules more isolates. Also give us teh possibility to implement in parallel with other libraries likeredux-observable
with Epics idea. -
Action Types naming convention: All async action, should be post fixed with:
REQUESTING_COMPLETED
REQUESTING_FAILED
And also should have a attributeasync:true
in their body, and has the following data structure:
type: types.REQUEST_SEARCH,
meta: {
async: true,
path: `/search?text="${text}"`,
method: 'GET',
},
Following that convention, help us to avoid boilerplate code using api-service.ts
middleware.
- Action Types names convention is:
- ACTION: Effect is most commonly a noun that means the result of an action —> _ —>
CATALOG_ADDED
|CATALOG_REMOVED
- ASYNC ACTION CREATOR: Affect is most commonly a verb —> —>
REQUESTING_CATALOG
|REQUESTING_CATALOG_COMPLETED
|REQUESTING_CATALOG_FAILED
- NextJS used to provider server rendering for performance, SEO and Code splitting reasons.
- React-testing-Library: A really useful library to help us to test React component in a clean, predictable and readable way.
- Redux: The reactive programming allow us to build more predictable, scalable & Solid web application.
- Immutablejs: For performance reason, allowing us to perform shallow equality and avoid unheeded rendering. (only for container component and reducer layer. In order to avoid problems when handling data, try to minimize the interoperability, and only keep your container component with immutable info. Lets dumb components with native objects.
- Lodash: For cross browsing support, performance and reliable way to handler data. (only for dump component and action creators).
- Prettier/husky/lint-staged/Eslint, Help us to avoid commit and push some code that don't follow with the default standards of the project and also prevent to push some code that don't pass the UT. (It's already configure airbnb, and eslint:recommended practices)
- Following in each part of the app SRP (Single responsibility principle). One reason to change. Each module/class/function has their own level of the abstraction.
- Test should follow the SRP principle too (single responsibility principle). Do one thing, test one thing.
- Test files, should be ended with
*.test.tx
and should be placed in the same folder from their SUT (Subject under test). - Keep in mind the implicit structure of test must be AAA (Arrange, Act, Assert).
- Each test must be isolated, means that one test not be dependent to another in order to get given result, therefore it should not matter the order of execution of them.
- Avoid global variables. Instead, declare them in setup method.
- Follow the DRY principle (Don’t Repeat Yourself). If we identify that we have repeated code throughout our tests use beforeEach function to put the code in one place.
- Putting comments in the header of the test is an anti-pattern, avoid them.
- Don't test action isolate, when testing reducer I like to test action as well in order to avoid unwanted testing. (I know that sounds like an integrating test instead of unit test, but it make sense for me.)
- Improve in a way that much closer to be a full PWA application.
- Implement Normalize, to have a flatten state. That help you to make more performance the shallow equality performed and also to deal with a easy structure store.
- Implement some CI such as Circle or Travis.
- E2E Testing with Cypress. It's really powerful implement it, in order to save time in the regressions testing.
- Improve Logging report in Backend side and also in front-end side to be sure that your app are working properly, otherwise send a email when throws some error.
- implement reselect to improve performance in out selectors.
- Increase UT code coverage from FE and BE.
- I choose to be build
Card
component in a uncontroller way, because I didn't want to populate the global state, with custom states of the inner context. I prefer in this particular case, let the global state clean of custom behaviors from that particular component. That allow us, to be focus in buisiness logic, and high level state of your app. And also avoid potencial performance problem. Please take a look this comment for more detail. Also Kent Dodds, also mentioned that. In some use cases, you state should be near as much as possible from their origin. A general rule, it's try to build controller component, as much as possible. But, the component that has a really complex behavior, didn't make sense to populate your global state, with internal state of the component. - Aslo
Card
component could be large, and I didn't split in sub component as well. That was for the reason, to prevent that my application surface, don't keep growing unneeded. Just, if you need to re-use some port of the component, split that. But, don't split from the start. This Rule, is some trend the las year that I saw that is doing several React expert.