Our Practices of Building a React Web App
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767711/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767729/pasted-from-clipboard.png)
ZHUORAN LI
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6788286/pasted-from-clipboard.png)
GitHub: @lzhuor
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6788304/pasted-from-clipboard.png)
🎵 Clarinet, 🏀 Basketball, 🎿 Ski
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6799674/pasted-from-clipboard.png)
🤯 What's happening?
The "library"
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6799045/pasted-from-clipboard.png)
Small Scope
Evan You on Vue.js: Seeking the Balance in Framework Design | JSConf.Asia 2019
"Warning"
![](https://media1.giphy.com/media/Hw3YuZo2qZ0xa/giphy.gif)
- Opinionated
- Mostly for SPA
- Different thoughts are more than welcome!
Delivery of Design
![](https://media2.giphy.com/media/TYlus7VAr9c4M/giphy.gif)
![](https://media1.giphy.com/media/d5pGYhWb3T1Hyyl8OB/giphy.gif)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6792147/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6792148/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6792151/pasted-from-clipboard.png)
😭 Sketch
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6798238/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6787345/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6787341/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767766/pasted-from-clipboard.png)
Components
Core
Frontend
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767837/pasted-from-clipboard.png)
workspace
Monorepo
Check out once, develop all!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767766/pasted-from-clipboard.png)
Components
- Shared components, usable across scenes, modals and layouts that are behaving in the same way
- Generic, in the way that different components could potentially use them with specific implementations
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6787366/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6799089/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767766/pasted-from-clipboard.png)
Core
- Contains all the Redux & Saga modules shared across the platform
- composing data of micro-services or BFF*
- model the resources of your domain
- API interactions
- Only needed if you really know why you need it, usually for complex domain models
- client-side Cryptowallet is a good usecase
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767766/pasted-from-clipboard.png)
Core
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797036/pasted-from-clipboard.png)
Redux & Sagas
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767766/pasted-from-clipboard.png)
Core
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797038/pasted-from-clipboard.png)
API Client
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797056/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767766/pasted-from-clipboard.png)
Frontend
- The actual web app implements business logics
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6798286/pasted-from-clipboard.png)
👨💻
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767766/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6767837/pasted-from-clipboard.png)
workspace
Monorepo
{
"test": "cross-env yarn wsrun test:build --fast-exit && yarn wsrun test"
}
{
"test:components": "yarn workspace silver-components test"
}
Styling
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6788753/pasted-from-clipboard.png)
- Inline props
- Flexibility
- Generic HTML tags
- Wrap existing components
- Global styles
- Theme
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6793166/pasted-from-clipboard.png)
styled-components
const Container = styled.div`
background: ${props => props.bgColor};
`
const Container = styled(BaseContainer)`
background: red;
`
Use defined name of color instead of hex code
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6788208/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6788215/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6798308/pasted-from-clipboard.png)
Layouts
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797081/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797085/pasted-from-clipboard.png)
<PublicLayout />
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797097/pasted-from-clipboard.png)
<SilverLayout />
- Authentication
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797114/pasted-from-clipboard.png)
const ShareFormContainer = styled.div`
margin: 3.2rem 0;
display: flex;
align-items: center;
${media.maxWidth.mobile`
margin-bottom: 0;
flex-direction: column;
`};
`
- Consistent
- breakpoints of Grid system
- breakpoints of Media Query (in CSS)
- <MediaContext /> API (in JSX)
Responsiveness
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797529/pasted-from-clipboard.png)
const { mobile } = useContext(MediaContext)
Responsiveness
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797525/pasted-from-clipboard.png)
Bundle Analysis
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6792996/pasted-from-clipboard.png)
"scripts": {
"analyze": "cross-env-shell ANALYZE=true NODE_ENV=production webpack-cli --config webpack.config.prod.js"
}
Code Split
- By route (URL)
- By frequency
- By feature
- By region / language
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6793036/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6794284/pasted-from-clipboard.png)
💪 Alternative (SPA): React.lazy & <Suspense />
https://reactjs.org/docs/code-splitting.html
Code Split
import Loadable from 'react-loadable'
import LoadableLoading from 'scenes/Common/LoadableLoading'
const Declaration = Loadable({
loader: () =>
import(
/* webpackChunkName: "declarations" */ 'scenes/Onboarding/Declaration'
),
loading: LoadableLoading
})
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6793262/pasted-from-clipboard.png)
Code Split
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6793433/pasted-from-clipboard.png)
Survey.sg.a9dn1kdf7.js
Survey.us.f6alekd5m.js
Tooltips
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797120/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797123/pasted-from-clipboard.png)
Declare once, use anywhere!
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797175/pasted-from-clipboard.png)
Layout Component
Modals
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797173/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797175/pasted-from-clipboard.png)
Layout Component
Modals
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797146/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797150/pasted-from-clipboard.png)
HOC
Declare once, use anywhere!
Error Tracking
- React Render
- <ErrorBoundary/>
- Anything else in JavaScript
- selectors
- reducers
- helpers, services, providers
- and more...
- Redux & Redux-Saga
- use middleware
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6797091/pasted-from-clipboard.png)
- User
- HTML Events & Redux Actions
- URL, Device, IP, Browser
- Stack Trace
- API Interactions
- App Version
- etc.
Sentry
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6798970/pasted-from-clipboard.png)
Staging
Sample
Sentry
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6798981/pasted-from-clipboard.png)
Staging
Sample
Sentry
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6798984/pasted-from-clipboard.png)
Staging
Sample
Internationalisation
- Translation
- en.json
- zh.json
- Formatting
- Money, Date, Number, Plurals etc.
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6799000/pasted-from-clipboard.png)
Internationalisation
- String
- HTML (not encouraged)
- React Component
- Templating
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6799023/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6799026/pasted-from-clipboard.png)
plugin
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6799181/pasted-from-clipboard.png)
Coding Styles
FP with Ramda.js
- Immutable
- Expressive
- Purity, code is easy to test
- Conceptually compatible with HOC, Functional Component, Redux
Migrating to Hooks
- Lifecycle
- Local State
- Context consumer
- react-redux connector
- Custom HOCs
Note: One challenge you may encounter with useEffect Hooks
react-redux v7.1 Hooks
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6789403/pasted-from-clipboard.png)
Migrating to Hooks
useAction
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6789351/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6789358/pasted-from-clipboard.png)
Migrating to Hooks
useNotifications
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6789372/pasted-from-clipboard.png)
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6789381/pasted-from-clipboard.png)
Redux-Form
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6787542/pasted-from-clipboard.png)
<Context />
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6796794/pasted-from-clipboard.png)
Forms
![](https://s3.amazonaws.com/media-p.slid.es/uploads/720526/images/6798010/pasted-from-clipboard.png)
20+
QA
![](https://media1.giphy.com/media/NiU9MQUOSaOPe/giphy.gif)
![](https://media1.giphy.com/media/l0Ex8rdyy2QdX6Li8/giphy.gif)