рдирдорд╕реНрдХрд╛рд░, рд╣реЗрдмреНрд░! рдЙрди рджреВрд░ рдХреЗ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдирд╣реАрдВ, "рдкреНрд░реЛрдЧреНрд░рд╛рдорд░" рд╕рдВрдХрд╛рдп рдХреЗ рдкрд╣рд▓реЗ рд╡рд░реНрд╖ рдореЗрдВ, рдореИрдВрдиреЗ рд╕рд╛рдереА рдЫрд╛рддреНрд░реЛрдВ рд╕реЗ рд╕рд╡рд╛рд▓ рдкреВрдЫрдирд╛ рдкрд╕рдВрдж рдХрд┐рдпрд╛: "рдЖрдк рдпрд╣рд╛рдВ рдЕрдзреНрдпрдпрди рдХрд░рдиреЗ рдХреЗ рд▓рд┐рдП рднреА рдХреНрдпреЛрдВ рдЧрдП?" рдмреЗрд╢рдХ, рдореИрдВрдиреЗ рдЙрддреНрддрд░реЛрдВ рдХреЗ рд╕рдЯреАрдХ рдЖрдВрдХрдбрд╝реЗ рдирд╣реАрдВ рд░рдЦреЗ рдереЗ, рд▓реЗрдХрд┐рди рдореБрдЭреЗ рдХреБрдЫ рдпрд╛рдж рд╣реИ: рдЖрдзреЗ рд╕реЗ рдЬреНрдпрд╛рджрд╛ рдЧреЗрдо рдмрдирд╛рдирд╛ рдЪрд╛рд╣рддреЗ рдереЗред рдЗрд╕ рддрд░рд╣ рд╕реЗ рдЙрддреНрддрд░ рджреЗрдиреЗ рд╡рд╛рд▓реЛрдВ рдореЗрдВ рд╕реЗ рдЕрдзрд┐рдХрд╛рдВрд╢ рд╡рд┐рднрд┐рдиреНрди рдкреНрд░рдХрд╛рд░ рдХреЗ "рдЧрдгрд┐рддрдЬреНрдЮреЛрдВ" рдФрд░ "рднреМрддрд┐рдХрд╢рд╛рд╕реНрддреНрд░реА" рдХреА рдкреНрд░рдЪреБрд░рддрд╛ рдХреЗ рд▓рд┐рдП рддреИрдпрд╛рд░ рдирд╣реАрдВ рдереЗ, рдЬрд┐рдирдХреЗ рд╕рд╛рде рд╣рдо рдЕрдзреНрдпрдпрди рдХреЗ рдкрд╣рд▓реЗ рджреЛ рд╡рд░реНрд╖реЛрдВ рдореЗрдВ рдЕрднрд┐рднреВрдд рдереЗред рд╕рднреА рдмрдЪреЗ рдирд╣реАрдВ - рдкрд╛рдВрдЪ рднреАрдбрд╝рднрд╛рдбрд╝ рд╡рд╛рд▓реЗ рд╕рдореВрд╣реЛрдВ рдХреЗ рджреВрд╕рд░реЗ рд╡рд░реНрд╖ рдХреЗ рдЕрдВрдд рддрдХ рддреАрди рдЕрдзреВрд░реЗ рдереЗред
рдмрд╣реБрдд рд╕рдордп рдкрд╣рд▓реЗ рдирд╣реАрдВ, рд╣рдорд╛рд░реА рдлреНрд░рдВрдЯ-рдПрдВрдб рдЯреАрдо рдХреЛ gamedev рдХреА рднреВрдорд┐рдХрд╛ рдореЗрдВ рдЦреБрдж рдХреЛ рдЖрдЬрдорд╛рдиреЗ рдХрд╛ рдЕрд╡рд╕рд░ рджрд┐рдпрд╛ рдЧрдпрд╛ рдерд╛ред рдмрд╣реБрдд рд╕рдВрдХреНрд╖реЗрдк рдореЗрдВ, рдХрд╛рд░реНрдп рдпрд╣ рд╣реИ: рдПрдХ рдЕрд╕рд▓реА 3 рдбреА рдЧреЗрдо рдмрдирд╛рдиреЗ рдХреЗ рд▓рд┐рдП, рддрд╛рдХрд┐ рдЖрдк рдХреЗрд╡рд▓ рдмреНрд░рд╛рдЙрдЬрд╝рд░ рдЦреЛрд▓рдХрд░ рдЦреЗрд▓ рд╕рдХреЗрдВред рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рдореЛрдмрд╛рдЗрд▓ рднреАред рдпрд╣рд╛рдВ рддрдХ тАЛтАЛрдХрд┐ рд╡реЗрдмрд╡реНрдпреВ рдореЗрдВ рднреАред

, , , тАФ React + Redux, ┬л ┬╗, , , .
RnD , : ┬л CodeFest тАФ . тАФ ┬╗. , , , . Gods in the sky.

CodeFest .
MMO TPS , , . , , , . CodeFest. , .
2 , , 2 . , , .
: -, тАФ , . , N , тАФ 1 . , тАФ 15 . , , 16-. , , :
- 30 . CodeFest, тАФ , ┬л┬╗. , .
- ┬л┬╗ . , :
- 90 CPU;
- 120 ;
- 270 /c тАФ , 675 /c тАФ .
- 4,2 /c. , . тАФ UDP WebRTC, . .
- . 2 , , , . , - Node.js , .
, , ( ?), , , , . .
, . , ┬л┬╗. тАФ .
:
, , , . , , 5 , , 40 .
-. , , тАФ . React Redux. c 3D-, , Gods in the sky, three.js.
, .
:

, Node.js. :
- , - ( , IE11);
- access-;
- html- .
SSR . kubernetes , . , . , , , , ( ). . Nginx.
. TS, AppState, :
interface AppState {
gameState: GameState;
gameObjects: GameObjects;
data: Data;
requests: RequestsState;
}
requests
тАФ , тАФ . , тАФ . .
data
тАФ , , , , ┬л┬╗. .
GameState
:
stage: 'factoids' | 'citySelect' | 'flyShow' | 'game' | 'results';
тАФ . :
elapsedTime: number;
тАФ , , .
, factoids
flyShow
, , тАФ elapsedTime
. 0, . , . , , , . , . тАж - , .
, , :
interface GameObjects {
user: UserInGame;
gifts: { [id: string]: GiftInGame; };
boosts: { [id: string]: Boost; };
bombs: { [id: string]: Bomb; };
}
, : , , . тАФ .
GameObjects тАФ . , FPS . GPU 100 . Redmi Note 7 40 FPS ( ). MI 5S 30 FPS, 20 , .
, . .
- Redux, тАФ . Redux , . ? Redux, .
, . , . ┬л┬╗ ( . behavior тАФ ). , .
. тАФ tick, . , . tick . :
- , , , . , , , .
- ( Redux-), .
, ┬л┬╗ . - , gameObjects, . , ┬л┬╗, .
25 ( ).
. ( ), React, . - , ┬л- ┬╗ ( , , ).

. pixabay.com
, FPS- 13. , , - MI 5S, FPS- тАФ 5-6, . .
: performance тАФ , . , , .
FPS=30 , :
- Redux
FPS * ~[ ] ~= 750
, , . - ReactтАЩ
FPS * ~2 * ~[ ]
. - three.js , , WebGL . , .
- (.. 150 ) 4-6 , .. .
- CSS- .
- , FPS 2-4 ( , ┬л┬╗ ).
- React.memo, - , .
React :
* ~2
, connect
. connect
тАФ - HOC, , .- , React тАУ (render pass), CPU, GPU.
: React.memo , , ┬л┬╗, , DOM-, .
, React + Redux, .
Redux
Redux тАФ . ~1 , . ~1, - тАФ . -, , GameObjects , :
export function setNextGameObjects(payload: GameObjects) {
return {
type: 'SET_NEXT_GAME_OBJECTS' as const,
payload,
};
}
GameObjects :
- , .
SET_NEXT_GAME_OBJECTS
. - , , GameObjects. Redux , - .
SET_NEXT_GAME_OBJECTS
.
:
let state = store.getState().gameObjects;
for (const action of this.collectedActions) {
state = gameObjectsFakeStateReducer(state, action);
}
store.dispatch(setNextGameObjects(state));
collectedActions тАФ , . тАФ , .
тАФ ~25 10 : ~2 . , gameObjectsFakeStateReducer . 25 . , .
? , perf-. 3 :
- ES2018, ~50 < ES2018 (, Firefox тАФ ). , spread.
- Object.assign 300 .
- 500 , ┬л ┬╗ .
, , , тАФ ES2018, . Firefox.
тДЦ3 , тАж . .
Object.assign. gameObjectsFakeStateReducer
gameObjectsFastStateReducer
, - :
switch (action.type) {
case 'PARTIAL_GIFT_STATE_PATCH':
if (!state.gifts[action.payload.id]) {
return state;
}
Object.assign(state.gifts[action.payload.id], action.payload);
break;
}
? , . , . 25 1 2-4 ( CPU). :

┬л┬╗ , , Redux 10 . , - , , connect gameObjects. , .
React
React . тАФ DOM. , , тАФ reselect, React.memo/React.PureComponent, shouldComponentUpdate . .
, , ~2, тАФ 5. , React , .. DOM .
batch React + Redux. , тАФ . , ?
, , connect . , .
. , <ScoreBoard />
,
- ;
- , .

React.PureComponent, connect mapStateToProps. elapsedTime
score
. Score
, elapsedTime
тАФ . elapsedTime
- render. , FPS, shouldComponentUpdate. HOCтАЩa connect тАФ shouldComponentUpdate .
, ┬л┬╗ , :
- shouldComponentUpdate,
elapsedTime
( ). , HOCтАЩa connect. - mapStateToProps . , , . connectтАЩa.
- useSelector. , .. . , , , .
- тАФ connect, тАФ . , . ScoreBoard .
тАФ ! ScoreBoardтАЩa connect, , . mapStateToProps , .
, connect. , тАФ - - canvas-, three.js (, , .). render , :
return <div id="map" className={s.map} ref={mapRef} />;
return <canvas id="scene" className={s.scene} ref={sceneRef} />;
, DOM тАФ . , React . , componentDidUpdate, . , componentDidUpdate :
public componentDidUpdate() {
const { geoPos, orientedRotationQuanternion } = this.props;
const { map } = this.state;
map.setQuat(orientedRotationQuanternion);
map.setCenter([geoPos[0], geoPos[1]], { animate: false });
map.setZoom(getMapZoomFromHeight(geoPos[2]), { animate: false });
}
, componentDidUpdate . :
- connect. , mapStateToProps;
public shouldComponentUpdate() { return false; }
тАФ ┬л┬╗ ┬л┬╗;- Redux ( ) useStore ;
- (
store.subscribe(() => { /* тАж */})
); - ;
- !
:
store.subscribe(() => {
const state = store.getState();
const { map } = this.state;
const { geoPos, orientedRotationQuanternion } = state.gameObjects.user;
map.setQuat(orientedRotationQuanternion);
map.setCenter([geoPos[0], geoPos[1]], { animate: false });
map.setZoom(getMapZoomFromHeight(geoPos[2]), { animate: false });
});
, , .
, - , .

. тАФ React Tree Reconcilation + Commit

React Tree Reconcilation + Commit
React + Redux , :
- , , , ┬л┬╗ React , ;
- ;
- ┬л ┬╗, , ;
- , .
, . , . , . ? .
:
- , , , , . , .
- , ReactтАЩ 30 . : .
- , .
- . . , .
- .
- Performance тАФ . CPU тАФ , Intel i9.
- - : 12тАУ20 тАУ . , .
- , . , , . , .
- , , . IE11 , . 70- Edge 18- ( ).
- WebGL . - , , -, Firefox linux, . . тАФ . -, . , , ┬л ┬╗, .
, :
- Firefox. . , WebGL, тАФ spread. FPS Firefox , Chrome. , , .
- IPhone. Safari IE6 220 . , , . , , . . тАФ - .
- . . . , , (, , ). .
- . , , . , , , ┬л┬╗ .
- ( ), тАУ , . .
, , . iOS, Android Web .