Twitter LiteãšReacté«æ§èœããã°ã¬ãã·ãWebã¢ããªã±ãŒã·ã§ã³
React.jsã§äžçæ倧ã®ããã°ã¬ãã·ãWebã¢ããªã±ãŒã·ã§ã³ïŒPWAïŒã®1ã€ãäœæããéã«ãå®æçããã³ç°åžžãªããã©ãŒãã³ã¹ããã«ããã¯ãã©ã®ããã«åé€ããããã確èª-Twitter Lite
é«éãªWebã¢ããªã±ãŒã·ã§ã³ãäœæããã«ã¯ãæéãç¡é§ã«ãªãå€ãã®æž¬å®ãµã€ã¯ã«ãå¿ èŠã§ãã ããããªãèµ·ãã£ãŠããã®ããç解ããæœåšçãªä¿®æ£ãé©çšããå¿ èŠããããŸãã æ®å¿µãªãããç°¡åãªè§£æ±ºçã¯ãããŸããã ããã©ãŒãã³ã¹ã¯ç¡éã®ã²ãŒã ã§ãããæ¹åã®ããã«é åãæ€çŽ¢ããã³æž¬å®ããŸãã Twitter Liteã¯ãåæããŠã³ããŒãæããReactã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°ïŒããã³åã¬ã³ããªã³ã°ã®é²æ¢ïŒãç»åã®ã¢ããããŒããªã©ãããŸããŸãªåéã§å€ãã®å°ããªæ¹åãè¡ããŸããã ã»ãšãã©ã®å€æŽã¯å°ããªãã®ã§ãããåèšãããšæçµçã«ã¯æ倧ãã€æéã®ããã°ã¬ãã·ãWebã¢ããªã±ãŒã·ã§ã³ã® 1ã€ã«ãªããŸã ã
èªãåã«
Webã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãæ¹åããããã«æž¬å®ãšäœæ¥ãå§ããã°ããã®å ŽåããŸã ãããç¥ããªãå Žåã¯ãã¬ãŒã ã°ã©ãã£ãã¯ã®èªã¿æ¹ãåŠã¶ããšã匷ããå§ãããŸãã
åã»ã¯ã·ã§ã³ã§ã¯ãChromeããããããŒããŒã«ã®ã¿ã€ã ã©ã€ã³ã¹ã¯ãªãŒã³ã·ã§ããã®äŸã瀺ããŸãã äŸãããããããããããã«ãã¹ã¯ãªãŒã³ã·ã§ããã®åãã¢ã§ãæªãç¹ïŒäžïŒãšè¯ãç¹ïŒäžïŒã匷調ããŸãã
ã¿ã€ã ã©ã€ã³ãšãã¬ãŒã ã°ã©ãã«é¢ããç¹èšäºé ã ç§ãã¡ã¯éåžžã«åºç¯å²ã®ã¢ãã€ã«ããã€ã¹ã«çŠç¹ãåœãŠãŠãããããéåžžããããã5åé ãCPUãš3Gæ¥ç¶ãšãã人工çãªç°å¢ã§èšé²ããŸãã ããã¯ããçŸå®çã§ããã ãã§ãªããåé¡ãããæ確ã«çŸããŸãã React v15.4.0ãããã¡ã€ãªã³ã°ã³ã³ããŒãã³ãã䜿çšãããšãã¹ãã¥ãŒãæªåããå¯èœæ§ããããŸã ã ãã¹ã¯ãããã®ã¿ã€ã ã©ã€ã³ã®å®éã®ããã©ãŒãã³ã¹å€ã¯ãå³ãããã¯ããã«é«ããªããŸãã
ãã©ãŠã¶ã®æé©å
ã«ãŒãã«åºã¥ããŠã³ãŒããåãã
Webpackã¯åŒ·åã§ãããåŠã¶ã®ã¯é£ããã§ãã ãã°ããã®éã CommonsChunkPluginã«åé¡ããããããã€ãã®ãªã³ã°ã³ãŒãã®äŸåé¢ä¿ã§ã©ã®ããã«æ©èœããããåé¡ã§ãã ã ãã®ãããåèšãµã€ãºã1 MBïŒè»¢éæã«420 KB gzipïŒãè¶ ããJavaScriptãªãœãŒã¹ãã¡ã€ã«ã3ã€ãããããŸããã§ããã
ä»äºã«å¿ èŠãª1ã€ãŸãã¯ããã€ãã®éåžžã«å€§ããªJavaScriptãã¡ã€ã«ãããŠã³ããŒãããããšã¯ãã¢ãã€ã«ãŠãŒã¶ãŒã«ãšã£ãŠå€§ããªé害ãšãªãããµã€ãããã°ãã確èªããŠå¯Ÿè©±ãéå§ããããšãã§ããŸããã ã¹ã¯ãªããã®ãµã€ãºã«ããããããã¯ãŒã¯ãä»ããã¹ã¯ãªããã®éä¿¡æéã ãã§ãªãããã©ãŠã¶ã§ã®è§£ææéãå¢å ããŸãã
å€ãã®è°è«ã®æ«ãããããCommonsChunkãã«ãŒãã«åºã¥ããŠåå¥ã®æçã«åå²ããããšãã§ããŸããïŒäžã®äŸãåç §ïŒã 解æã³ãŒããã¡ãŒã«ããã¯ã¹ã«èœã¡ããã®æ¥ãæ¥ãŸããïŒ
const plugins = [ // extract vendor and webpack's module manifest new webpack.optimize.CommonsChunkPlugin({ names: [ 'vendor', 'manifest' ], minChunks: Infinity }), // extract common modules from all the chunks (requires no 'name' property) new webpack.optimize.CommonsChunkPlugin({ async: true, children: true, minChunks: 4 }) ];
詳现ãªã«ãŒãããŒã¹ã®ã³ãŒãåé¢ã䜿çšããŸãã ããé«éãªåæããã³HomeTimelineã¬ã³ããªã³ã°ã¯ãã¢ããªã±ãŒã·ã§ã³å šäœã®ãµã€ãºãå¢ããããšã§å®çŸãããŸããããã¯ã40å以äžã«åå²ãããã»ãã·ã§ã³å šäœã«ããã£ãŠååŽãããŸãã - ãã³ã©ã¹ã»ã®ã£ã©ã¬ãŒ
ã³ãŒãåââå²ã®åïŒäžïŒãšåŸïŒäžïŒã®ã¿ã€ã ã©ã€ã³
åææ§æã§ã¯ãã¡ã€ã³ããã±ãŒãžã®èªã¿èŸŒã¿ã«5ç§ä»¥äžããããã«ãŒãã«åºã¥ããŠæçåããåŸãããŠã³ããŒãæéã¯3ç§ã«ã»ãšãã©éããŸããïŒ3Gãããã¯ââãŒã¯ã·ãã¥ã¬ãŒã·ã§ã³ïŒã
ããã©ãŒãã³ã¹ã®æé©åã«é¢ããäœæ¥ã®æåã®æ®µéã§ãã®ãããªå€æŽãè¡ããŸãããã1ã€ã®å€æŽã«ãããGoogle Lighthouse Webã¢ããªã±ãŒã·ã§ã³ç£æ»ããŒã«ã®çµæãåçã«æ¹åãããŸããã
æé©åã®åïŒå·ŠïŒãšåŸïŒå³ïŒã«Lighthouseãµã€ãã§çµæã確èªããŸã
ã¹ããŒããŠã³ãåŒãèµ·ããæ©èœãé¿ãã
ç¡éã¹ã¯ããŒã«ã¿ã€ã ã©ã€ã³ã®å€ãã®å埩ã®éçšã§ãããŸããŸãªæ¹æ³ã䜿çšããŠã¹ã¯ããŒã«ã®äœçœ®ãšæ¹åãèšç®ããŸãããããã¯ãè¿œå ã®ãã€ãŒããèªã¿èŸŒãã§è¡šç€ºããããã«APIãèŠæ±ãããã©ããã決å®ããããã«å¿ èŠã§ãã æè¿ãŸã§ãç§ãã¡ã¯åé¡ãªãåå¿ãããŠã§ã€ãã€ã³ãã䜿çšããŠããŸããã ãã ããäž»èŠã³ã³ããŒãã³ãã®1ã€ã§æ倧ã®ããã©ãŒãã³ã¹ãéæããã«ã¯ãåã«ååã«é«éã§ã¯ãããŸããã
ãã€ã³ãïŒãŠã§ã€ãã€ã³ãïŒã¯ãèŠçŽ ã®é«ããå¹ ãäœçœ®ã®ããŸããŸãªã€ã³ãžã±ãŒã¿ãŒãèšç®ããŠãçŸåšã®ã¹ã¯ããŒã«äœçœ®ãåãšããžããã®è·é¢ãã¹ã¯ããŒã«ããæ¹åã決å®ããŸãã ãããã®æ å ±ã¯ãã¹ãŠæçšã§ãããã¹ã¯ããŒã«ã€ãã³ãããšã«èšç®ããããããã³ã¹ããããããŸãããããã®èšç®ã«ããããžã£ã³ã¯ã®é床ãäœäžããŸãã
ãã ããæåã«ãéçºããŒã«ãã¹ããŒããŠã³ã«ã€ããŠéç¥ãããšãã®éçºããŒã«ã®æå³ãç解ããå¿ èŠããããŸãã
ææ°ã®ããã€ã¹ã®ã»ãšãã©ã¯ã1ç§éã«60åç»é¢ãæŽæ°ããŸãã ã¢ãã¡ãŒã·ã§ã³ãŸãã¯ãã©ã³ãžã·ã§ã³å¹æãããå ŽåããŸãã¯ãŠãŒã¶ãŒãããŒãžãã¹ã¯ããŒã«ããå Žåããã©ãŠã¶ãŒã¯æŽæ°é床ã«åãããŠããããã®ç»é¢æŽæ°ããšã«1ã€ã®æ°ããç»åãŸãã¯ãã¬ãŒã ãçºè¡ããå¿ èŠããããŸãã
ãããã®åãã¬ãŒã ã®ããžã§ããã¯16ããªç§ãå°ãè¶ ããŠããŸãïŒ1ç§/ 60 = 16.66ããªç§ïŒã ãã ããå®éã«ã¯ããã©ãŠã¶ãŒã¯è£å©çãªã¿ã¹ã¯ãå®è¡ããå¿ èŠãããããããã¹ãŠã®äœæ¥ã¯10ããªç§ã§å®äºããå¿ èŠããããŸãã äºç®ã«åãŸããªãå Žåã¯ããã¬ãŒã ã¬ãŒããäœäžããã³ã³ãã³ããç»é¢äžã§ããããã移åããŸãã ããã¯ãããžã£ã³ã¯ãšåŒã°ãã䜿ãåæã«æªåœ±é¿ãåãŒããŸãã - ããã©ãŒãã³ã¹ã¬ã³ããªã³ã°ã®ããŒã«ã«ã€ã¹
æéã®çµéãšãšãã«ã VirtualScrollerãšåŒã°ããç¡éã¹ã¯ããŒã«çšã®æ°ããã³ã³ããŒãã³ããéçºããŸããã ãã®æ°ããã³ã³ããŒãã³ãã䜿çšãããšããã€ãŒããã£ãŒãã®ã©ã®ãã©ã°ã¡ã³ãããã€ã§ãã¿ã€ã ã©ã€ã³ã«ã¬ã³ããªã³ã°ãããã®ã§ãèŠèŠçãªäœçœ®ã®ãªãœãŒã¹ã倧éã«æ¶è²»ããèšç®ãå®è¡ããå¿ èŠããªããªããŸããã
ããã¯ãã»ã©éèŠã§ã¯ãªãããã«æãããããããŸããããããŸããŸãªèŠçŽ ã®é«ããèšç®ããããããã¹ã¯ããŒã«äžïŒäžããïŒã«ã¬ã³ããªã³ã°äžã«é床ãäœäžããŸããã ïŒäžããïŒã¹ã¯ããŒã«ãé«éã§å®è¡ããããšãã«ã³ã³ãã³ãã®ãããããäžæåæ¢ããªããªããŸãã
åŒã³åºããæåŠããåŸãè¿œå ã®ã¹ããŒããŠã³ãçºçããããããã€ãŒããã£ãŒãã®ã¹ã¯ããŒã«ãæ»ããã§ãã£ããããŠãããã¢ããªã±ãŒã·ã§ã³ã®ããè±ãã§ã»ãŒãã€ãã£ããªå°è±¡ãäžããŸãã æé©åã®äœå°ã¯åžžã«ãããŸããããã®å€æŽã«ãããããŒããã¹ã¯ããŒã«ããéã®æ»ããããé¡èã«æ¹åãããŸããã ããã©ãŒãã³ã¹ã«é¢ããŠã¯ãããããäºçŽ°ãªããšãéèŠã§ããããšãæãåºããŠãã ããã
å°ããåçã䜿çšãã
ç§ãã¡ã¯ã CDNããããŠã³ããŒããããæ°ããå°ããªåçã§ããã€ãã®ã°ã«ãŒããšååããŠãTwitter Liteã®ãã©ãã£ãã¯ã®æé©åãéå§ããŸããã ç»åã®çž®å°ã«ãããã¢ããªã±ãŒã·ã§ã³ã¯æå°éã®ã¬ã³ããªã³ã°ã®ã¿ãæäŸããããã¯çµ¶å¯Ÿã«å¿ èŠã§ãïŒãµã€ãºãšå質ã®äž¡æ¹ïŒããã©ãã£ãã¯ãåæžããã ãã§ãªããç¹ã«å€§éã®ç»åãå«ããã€ãŒããã£ãŒããã¹ã¯ããŒã«ããå Žåããã©ãŠã¶ã®çç£æ§ãåäžããŸãã ã
å°ããªç»åãããã©ãŒãã³ã¹ã«äžãã圱é¿ãå€æããã«ã¯ãChromeããããããŒããŒã«ã®ã©ã¹ã¿ãŒã¿ã€ã ã©ã€ã³ãã芧ãã ããã 以äžã®2ã€ã®ã¿ã€ã ã©ã€ã³ã®äžéšã«ç€ºãããã«ãç»åãµã€ãºãæé©åããåã«ãåäžã®ç»åã®ãã³ãŒãã«ã¯300ããªç§ä»¥äžããããŸããã ããã¯ãã€ã¡ãŒãžãããŠã³ããŒããããŠããããŒãžã«è¡šç€ºããããŸã§ã®æéã®é·ãã§ãã
ããŒãžãã¹ã¯ããŒã«ãããšãã«æ¯ç§60ãã¬ãŒã ã®æšæºãç®æãå Žåãå¯èœãªéãå€ãã®åŠçã16.667ããªç§ïŒ1ãã¬ãŒã ïŒã«çµãå¿ èŠããããŸãã 1ã€ã®ç»åã®ã¬ã³ããªã³ã°ã«ã¯18ãã¬ãŒã ãå¿ èŠã§ããããšãå€æããŸããããããã¯å€ãããŸãã ããŒãã«é¢ããŠã¯ããã1ã€æ³šæããå¿ èŠããããŸããã芧ã®ãšããã ã¡ã€ã³ã®ã¿ã€ã ã©ã€ã³ã¯ãç»åã®ãã³ãŒããå®äºãããŸã§åäœãç¶ç¶ããããšãã»ãŒå®å šã«ãããã¯ãããŠããŸãïŒçœãã®ã£ããã§ç€ºãããŠããŸãïŒã ããã¯ãããã§ããã©ãŒãã³ã¹ã®ããã«ããã¯ãããããšãæå³ããŸãïŒ
倧ããªç»åïŒäžèšïŒã¯ã18ãã¬ãŒã ã®ã¡ã€ã³ã¹ããªãŒã ããããã¯ã§ããŸãã å°ããªç»åïŒäžïŒã¯1ãã¬ãŒã ã®ã¿
åçã®ãµã€ãºãå°ãããªã£ãã®ã§ãæ倧ã®ç»åããã³ãŒãããã«ã¯1ãã¬ãŒã 以äžå¿ èŠã§ãã
React Optimization
shouldComponentUpdateã¡ãœããã䜿çšãã
Reactã§ã¢ããªã±ãŒã·ã§ã³ã®ããã©ãŒãã³ã¹ãæé©åããããã®äžè¬çãªãã³ãã¯ãshouldComponentUpdateã¡ãœããã䜿çšããããšã§ãã å¯èœãªéããããããããšããŸããããæã«ã¯é倧ãªééããä¿®æ£ããŸããã
æåã®ãã€ãŒããæ°ã«å ¥ã£ããã圌ãšä»¥äžã®ãã¹ãŠã®ãã£ã¹ã«ãã·ã§ã³ãåã³è¡šç€ºãããŸãïŒ
åžžã«æŽæ°ãããã³ã³ããŒãã³ãã®äŸã ãã€ãŒãã®äžã«ããããŒãã®ã¢ã€ã³ã³ãã¯ãªãã¯ããŠã¹ããªãŒã å ã§æ°ã«å ¥ã£ãå Žåãç»é¢äžã®
Conversation
ã³ã³ããŒãã³ããåã³ã¬ã³ããªã³ã°ãããŸãã ã¢ãã¡ãŒããããäŸã§ã¯ããã€ãŒãã®äžã§
Conversation
ã³ã³ããŒãã³ãå šäœã匷å¶çã«æŽæ°ããããããã©ãŠã¶ãè£å ãããå Žæã瀺ãç·è²ã®é·æ¹åœ¢ãèŠãããšãã§ããŸãã
ãã®ã¢ã¯ã·ã§ã³ã®2ã€ã®ãã¬ãŒã ã°ã©ãã以äžã«ç€ºããŸãã
shouldComponentUpdate
ãªã
shouldComponentUpdate
ïŒäžèšïŒãããªãŒå šäœãæŽæ°ãããç»é¢äžã®ã©ããã®ããŒãã®è²ãå€æŽããã ãã§åæç»ãããŸãã
shouldComponentUpdate
ïŒäžèšïŒãè¿œå ããåŸãããªãŒå šäœãæŽæ°ãããªãããã«ãã0.1ç§éã®äžèŠãªããŒã¿åŠçãç¯çŽããŸããã
以åïŒäžéšïŒãå€éšã®ãã€ãŒãã«ããããèšå®ãããšããã£ã¹ã«ãã·ã§ã³å šäœãæŽæ°ãããåã³ã¬ã³ããªã³ã°ãããŸããã shouldComponentUpdateããžãã¯ãè¿œå ããåŸïŒäžïŒãã³ã³ããŒãã³ããšåããã»ã¹ã¯CPUãµã€ã¯ã«ãæ¶è²»ããªããªããŸãã
äžèŠãªäœæ¥ãcomponentDidMountã«è»¢éãã
ãã®å€æŽã¯æãããªããã«æãããããããŸããããTwitter Liteã®ãããªå€§èŠæš¡ãªã¢ããªã±ãŒã·ã§ã³ãéçºãããšãããã®ãããªå°ããªããšãå¿ããã¡ã§ãã
ã³ãŒãã®å€ãã®å Žæã§ãReactã®ã©ã€ããµã€ã¯ã«ã¡ãœãããã€ãŸãcomponentWillMountã®å®è¡äžã«ãåæã®ããã«ãªãœãŒã¹éçŽåã®èšç®ãå®è¡ãããããšã«æ°ä»ããŸããã æ¯åãã³ã³ããŒãã³ãã®ã¬ã³ããªã³ã°ãäžæçã«ãããã¯ãããŸããã ããã§20ããªç§ãããã«90ããªç§ããã¹ãŠãæ¥éã«çºå±ããŸããã æåã«ãå®éã®ã¬ã³ããªã³ã°ãéå§ãããåïŒ2ã€ã®ã¹ã¯ãªãŒã³ã·ã§ããã®äžéšïŒã§ãããã€ãŒããæç»ããå¿ èŠããã
componentWillMount
ã®åæãµãŒãã¹ã«æ å ±ãèšé²ããŠéä¿¡ããããšããŸããã
ã³ãŒãã®éèŠã§ã¯ãªãéšåããcomponentWillMountããããcomponentDidMountãã«ç§»åãããšãç»é¢ã«ãã€ãŒãã衚瀺ããããã®æéãå€§å¹ ã«ç¯çŽã§ããŸãã
ãããã®èšç®ãšãããã¯ãŒã¯åŒã³åºããReactã³ã³ããŒãã³ãã®
componentDidMount
ã¡ãœããã«è»¢éããããšã«ãããã¡ã€ã³ã¹ã¬ããã®ããã¯ã解é€ããã³ã³ããŒãã³ãã¬ã³ããªã³ã°äžã®ã¹ããŒããŠã³ãåæžããŸããïŒã¿ã€ã ã©ã€ã³ã®ççž®ïŒã
dangerlySetInnerHTMLãé¿ãã
Twitter Liteã§ã¯ãSVGã¢ã€ã³ã³ãæãã³ã³ãã¯ãã§ã¹ã±ãŒã©ãã«ãªåœ¢åŒã§ãããããSVGã¢ã€ã³ã³ã䜿çšããŠããŸãã æ®å¿µãªãããReactã®å€ãããŒãžã§ã³ã§ã¯ãã³ã³ããŒãã³ãããèŠçŽ ãäœæãããšãã«ã»ãšãã©ã®SVGå±æ§ããµããŒããããŠããŸããã§ããã ãããã£ãŠãã¢ããªã±ãŒã·ã§ã³ã®äœæãå§ããã°ããã®ãšããReactã®ã³ã³ããŒãã³ããšããŠSVGã¢ã€ã³ã³ã䜿çšããã«ã¯ã
dangerouslySetInnerHTML
ã䜿çšããå¿ èŠããããŸããã
ããšãã°ãæåã®HeartIconããŒãã¢ã€ã³ã³ã¯æ¬¡ã®ããã«ãªããŸããã
const HeartIcon = (props) => React.createElement('svg', { ...props, dangerouslySetInnerHTML: { __html: '<g><path d="M38.723 12c-7.187 0-11.16 7.306-11.723 8.131C26.437 19.306 22.504 12 15.277 12 8.791 12 3.533 18.163 3.533 24.647 3.533 39.964 21.891 55.907 27 56c5.109-.093 23.467-16.036 23.467-31.353C50.467 18.163 45.209 12 38.723 12z"></path></g>' }, viewBox: '0 0 54 72' });
dangerlySetInnerHTMLã®äœ¿çšã¯ ãã»ãã¥ãªãã£ã®èŠ³ç¹ããæšå¥šãããŠããããããŠã³ããšã¬ã³ããªã³ã°ã®ããã»ã¹ãé ããªããŸãã
以åïŒäžèšïŒã4ã€ã®SVGã¢ã€ã³ã³ãããŠã³ãããã®ã«çŽ20ããªç§ããããŸããããçŸåšïŒä»¥äžïŒçŽ8ããªç§ããããŸã
ãã¬ãŒã ã°ã©ãã®åæã«ãããåæããŒãžã§ã³ã§ã¯ãäœéããã€ã¹ã§åãã€ãŒãã®äžéšã«4ã€ã®SVGã¢ã€ã³ã³ãããŠã³ãããã®ã«çŽ20ããªç§ããã£ãŠããããšãããããŸãã å°ãèŠããŸããããã®ãããªã¢ã€ã³ã³ã¯èšå€§ãªæ°ã®ã€ã¶ããã®ã¹ããªãŒã ãã¹ã¯ããŒã«ããªãã倧éã«ããŠã³ããããŸããããã¯æéã®å€§å¹ ãªæ倱ã§ããããšãããããŸããã
React v15ã§ã»ãšãã©ã®SVGå±æ§ã®ãµããŒããè¿œå ãããšãã«ãdangerlySetInnerHTMLãæŸæ£ããå Žåã«ã©ããªããã確èªããããšã«ããŸããã 2çªç®ã®ãã¬ãŒã ã°ã©ãïŒã°ã©ãã®äžçªäžã®ãã¢ã®äžéšïŒã§ãããããã«ããã®ã¢ã€ã³ã³ã»ãããããŠã³ãããŠæç»ããå¿ èŠããããã³ã«å¹³å60ïŒ ç¯çŽã§ããŸãïŒ
SVGã¢ã€ã³ã³ã¯ãã¹ããŒãã¬ã¹ã§ã·ã³ãã«ãªã³ã³ããŒãã³ãã«ãªããŸããã ãå±éºãªãæ©èœã䜿çšãããå¹³å60ïŒ é«éã§ããŠã³ããããŸãã ãããã¯æ¬¡ã®ããã«ãªããŸãã
const HeartIcon = (props = {}) => ( <svg {...props} viewBox='0 0 ${width} ${height}'> <g><path d='M38.723 12c-7.187 0-11.16 7.306-11.723 8.131C26.437 19.306 22.504 12 15.277 12 8.791 12 3.533 18.163 3.533 24.647 3.533 39.964 21.891 55.907 27 56c5.109-.093 23.467-16.036 23.467-31.353C50.467 18.163 45.209 12 38.723 12z'></path></g> </svg> );
å€æ°ã®ã³ã³ããŒãã³ãã®ããŠã³ãããã³ã¢ã³ããŠã³ãäžã®ã¬ã³ããªã³ã°ã®é 延
é ãããã€ã¹ã§ã¯ãã¯ãªãã¯ã«å¯ŸããŠã¡ã€ã³ããã²ãŒã·ã§ã³ããŒãããã«è¡šç€ºããããå€ãã®å Žåãè€æ°ã®ã¯ãªãã¯ãçºçããããšã«æ°ä»ããŸãã-ãŠãŒã¶ãŒã¯æåã®ã¯ãªãã¯ã¯ä¿®æ£ãããŠããªããšèããŠããŸãã
以äžã®ã¢ãã¡ãŒã·ã§ã³ã«æ³šæããŠãã ããã ããŒã ã¢ã€ã³ã³ãæŽæ°ãããã¯ãªãã¯ãããããšã瀺ãã®ã«çŽ2ç§ããããŸãã
é 延ã¬ã³ããªã³ã°ããªããã°ãããã²ãŒã·ã§ã³ããŒã¯ããã«å¿çããŸãã
ããããGIFã¢ãã¡ãŒã·ã§ã³ã«é 延ã¯ãããŸããã æŽæ°ã¯æ¬åœã«é ãã§ãã ããããçµå±ã®ãšããã ããŒã ç»é¢ã®ãã¹ãŠã®ããŒã¿ã¯æ¢ã«ããŠã³ããŒããããŠããã®ã«ããªãããã»ã©é·ã衚瀺ãããªãã®ã§ããããïŒ
Reactã§ã³ã³ããŒãã³ãããªãŒïŒãã€ãŒããã£ãŒããªã©ïŒãããŠã³ãããã³ã¢ã³ããŠã³ããããšãå€ãã®ãªãœãŒã¹ãæ¶è²»ãããããšãå€æããŸããã
å°ãªããšããããã²ãŒã·ã§ã³ããŒããŠãŒã¶ãŒã®ã¯ãªãã¯ã«åå¿ããªããšããå°è±¡ãæé€ããããšèããŠããŸãã ãããè¡ãããã«ãé«æ¬¡ã®å°ããªã³ã³ããŒãã³ããäœæããŸããã
import hoistStatics from 'hoist-non-react-statics'; import React from 'react'; /** * Allows two animation frames to complete to allow other components to update * and re-render before mounting and rendering an expensive `WrappedComponent`. */ export default function deferComponentRender(WrappedComponent) { class DeferredRenderWrapper extends React.Component { constructor(props, context) { super(props, context); this.state = { shouldRender: false }; } componentDidMount() { window.requestAnimationFrame(() => { window.requestAnimationFrame(() => this.setState({ shouldRender: true })); }); } render() { return this.state.shouldRender ? <WrappedComponent {...this.props} /> : null; } } return hoistStatics(DeferredRenderWrapper, WrappedComponent); }
Katie SievertãäœæããHigherOrderComponentã³ã³ããŒãã³ã
ãããHomeTimelineã«é©çšãããšãããã²ãŒã·ã§ã³ããŒã®å¿çãã»ãŒç¬æã«ãªããå šäœçãªå éãæããã«ãªããŸããã
const DeferredTimeline = deferComponentRender(HomeTimeline);
render(<DeferredTimeline />);
é 延ã¬ã³ããªã³ã°ã§ã¯ãããã²ãŒã·ã§ã³ããŒãå³åº§ã«å¿çããŸã
Reduxæé©å
é »ç¹ã«ç¶æ ãä¿åããªãã§ãã ãã
å¶åŸ¡ãããã³ã³ããŒãã³ãã䜿çšããããšããå§ãããŸãããããŒã¿ã®å ¥åãå¶åŸ¡ããå Žåã¯ãããŒã¹ãããŒã¯ããšã«åã¬ã³ããªã³ã°ããå¿ èŠããããŸãã
3 GHzããã»ããµãæèŒãããã¹ã¯ãããã³ã³ãã¥ãŒã¿ãŒã§ã¯ãããã¯ç®ç«ã¡ãŸããããCPUãªãœãŒã¹ãéåžžã«éãããŠããå°åã®ã¢ãã€ã«ããã€ã¹ã§ã¯ãç¹ã«ãã£ãŒã«ãããå€æ°ã®æåãåé€ããå Žåãã¯ãªãã¯ã®éã«å€§å¹ ãªé 延ãçºçããŸãã
ãã€ãŒãã®ã³ã³ãã€ã«ã®å©äŸ¿æ§ãç¶æããæåæ°ã®ã«ãŠã³ã¿ãŒãæ®ãããã«ãå¶åŸ¡ãããã³ã³ããŒãã³ãã䜿çšããå ¥åãã£ãŒã«ãã®çŸåšã®å€ãããŒãæŒããã³ã«Reduxç¶æ ã«æž¡ããŸããã
ããã€ãã®ã¹ã¯ãªãŒã³ã·ã§ããã®äžéšã«ã¯å žåçãªAndroid 5ããã€ã¹ããããã¯ãªãã¯ããšã«çŽ200ããªç§ã®äœåãªæéããããå€æŽãçºçããŸãã 人ãæ¬åœã«ãã°ããã¿ã€ãããå ŽåããŠãŒã¶ãŒãã«ãŒãœã«ããã©ãŒã å ãã©ã³ãã ã«åããæãæ··ä¹±ããããšäžå¹³ãèšããšãéåžžã«æªãç¶æ ã«ãªããŸãã
ç¶æ ãReduxã«è»¢éããåãšæé©ååŸã®åããŒã¹ãããŒã¯åŸã®æŽæ°ã«ãããæéã®æ¯èŒ
ãã€ãŒãã®ãã©ããç¶æ ãReduxã®ã¡ã€ã³ç¶æ ãæŽæ°ããã®ãé²ãã代ããã«ããŒã«ã«ã§Reactã³ã³ããŒãã³ãã®ç¶æ ãç¶æãããšãã«ãå®è¡æéã50ïŒ å éããŸããã
ã¢ã¯ã·ã§ã³ãåäžã®é åžããã±ãŒãžã«ã°ã«ãŒãåãã
Twitter Liteã§ã¯ã reduxããã³react-reduxã䜿çšããŠãããŒã¿ç¶æ ã®å€æŽãã³ã³ããŒãã³ãã«å²ãåœãŠãŸãã NormalizrãšcomposeReducersã䜿çšããŠã倧èŠæš¡ã¹ãã¬ãŒãžã®ããŸããŸãªé åã§ããŒã¿ãæé©åããŸãã ã ããã¯ãã¹ãŠããŸããããããŒã¿ã®éè€ãé²ããã¹ãã¬ãŒãžãµã€ãºãå°ããä¿ã¡ãŸããã ãã ããæ°ããããŒã¿ãåä¿¡ãããã³ã«ã察å¿ãããªããžããªã«è¿œå ããããã«å€æ°ã®ã¢ã¯ã·ã§ã³ãéä¿¡ããå¿ èŠããããŸããã
react-reduxã®ã¡ã«ããºã ãèãããšãããã¯ãéä¿¡åŸã®åã¢ã¯ã·ã§ã³ããå€æŽã®åèšç®ãšé¢é£ã³ã³ããŒãã³ãïŒã³ã³ãããŒãšåŒã°ããïŒã®åã¬ã³ããªã³ã°ã®å¯èœæ§ã«ã€ãªããããšãæå³ããŸããã
ç¹å¥ã«éçºãããããã«ãŠã§ã¢ã䜿çšããŠããŸãã ããããäœæ¥ã«å©çšã§ãã ä»ã® ããã«ãŠã§ã¢ã ãããŸã ã é©åãªãã®ã䜿çšããããç¬èªã®ã¢ãžã¥ãŒã«ãäœæããŠãã ããã
ãããåŠçã®å©ç¹ã瀺ãæè¯ã®æ¹æ³ã¯ã Chrome React Perf Extensionã䜿çšããããšã§ãã ããªããŒãåŸãããã¢ã¯ãã£ããã£ãã·ã¥ãå®è¡ããããã¯ã°ã©ãŠã³ãã§æªèªã®ãã©ã€ããŒãã¡ãã»ãŒãžãèšç®ããŸãã çŸæç¹ã§ã¯ãããŸããŸãªãªããžã§ã¯ãïŒäŒè©±ããŠãŒã¶ãŒãé²é³ã¡ãã»ãŒãžãªã©ïŒãè¿œå ããŸãã ãããåŠçãªã ïŒã¹ã¯ãªãŒã³ã·ã§ããã®äžéšïŒãåã³ã³ããŒãã³ãã¯ããããåŠçã®å Žå ïŒçŽ8åïŒã®2åïŒçŽ16åïŒã¬ã³ããªã³ã°ãããŸãã
Reduxã§ã®ãããåŠçãªãïŒäžèšïŒãšããã±ãŒãžïŒä»¥äžïŒã䜿çšããChromeã®React Perfæ¡åŒµæ©èœã®åäœã®æ¯èŒ
ãµãŒãã¹ã¯ãŒã«ãŒ
ãµãŒãã¹ã¯ãŒã«ãŒã¯ãã¹ãŠã®ãã©ãŠã¶ã§å©çšã§ããããã§ã¯ãããŸããããTwitter Liteã®è²Žéãªéšåã§ãã å¯èœãªå Žåã¯åžžã«ãããã·ã¥éç¥ããªãœãŒã¹ã®äºåãã£ãã·ã¥ãªã©ã«äœ¿çšããŸãã æ®å¿µãªãããããªãæ°ãããã¯ãããžãŒã§ã¯ãå€ãã®ããã©ãŒãã³ã¹ã®åé¡ãçºçããŸãã
ãªãœãŒã¹ãã£ãã·ã³ã°
ã»ãšãã©ã®è£œåãšåæ§ãTwitter Liteã¯å®ç§ãšã¯ã»ã©é ããã®ã§ãã ãŸã ç©æ¥µçã«éçºãæ©èœã®è¿œå ããã°ã®ä¿®æ£ãé«éåãè¡ã£ãŠããŸãã ããã¯ãJavaScriptãªãœãŒã¹ã®æ°ããããŒãžã§ã³ãé »ç¹ã«æçš¿ããå¿ èŠãããããšãæå³ããŸãã
ãŠãŒã¶ãŒãã¢ããªã±ãŒã·ã§ã³ãéããšãäžå¿«ãªç¶æ³ãçºçããå¯èœæ§ããããŸã-ãããŠã1ã€ã®ãã€ãŒããèŠãããã ãã«ãã¹ã¯ãªãããã¡ã€ã«ãå床ããŠã³ããŒãããå¿ èŠããããŸãã
ãµãŒãã¹ã¯ãŒã«ãŒããµããŒããããã©ãŠã¶ãŒã§ã¯ãå€æŽããããã¡ã€ã«ãããã¯ã°ã©ãŠã³ãã§èªåçã«æŽæ°ãããŠã³ããŒãããã£ãã·ã¥ãã䟿å©ãªæ©äŒããããŸãã ããã¯ãã¢ããªã±ãŒã·ã§ã³ãéãåã«èªåçã«çºçããŸãã
ããã¯ãŠãŒã¶ãŒã«ãšã£ãŠäœãæå³ããŸããïŒ æ°ããããŒãžã§ã³ããªãªãŒã¹ããå Žåã§ããããã°ã©ã ã®ã»ãŒãã®åŸã®ããŠã³ããŒãïŒ
ãµãŒãã¹ã¯ãŒã«ãŒãªãïŒäžïŒããã³ãµãŒãã¹ã¯ãŒã«ãŒããïŒäžïŒã®ãããã¯ãŒã¯ãªãœãŒã¹ã®ããŒãæé
äžã®å³ã§ã¯ããµãŒãã¹ã¯ãŒã«ãŒãããªãå Žåãã¢ããªã±ãŒã·ã§ã³ãéãããšãã«çŸåšã®ãã¥ãŒã®åãªãœãŒã¹ããããã¯ãŒã¯ããããŠã³ããŒãããå¿ èŠããããŸãã åªãã3Gãããã¯ââãŒã¯ã§ã¯ãããã«ã¯çŽ6ç§ããããŸãã ãã ãããªãœãŒã¹ããµãŒãã¹ã¯ãŒã«ãŒã«ãã£ãŠäºåã«ãã£ãã·ã¥ãããŠããå ŽåïŒäžã®ã¹ã¯ãªãŒã³ã·ã§ããïŒãåã3Gæ¥ç¶ã§åãããŒãžã®èªã¿èŸŒã¿ã1.5ç§ã§å®äºããŸãã 75ïŒ å éïŒ
Service Workerã®ç»é²ãé ããã
å€ãã®ã¢ããªã±ãŒã·ã§ã³ã§ã¯ãããŒãžãèªã¿èŸŒãŸãããããã«Service Workerãç»é²ããæ¹ãå®å šã§ãã
<script>
window.navigator.serviceWorker.register('/sw.js');
</script>
å®æããããŒãžãã¬ã³ããªã³ã°ããããã«ãã§ããã ãå€ãã®ããŒã¿ããã©ãŠã¶ãŒã«éä¿¡ããããšããŠããŸãããTwitter Liteã§ã¯ãããåžžã«å¯èœã§ãããšã¯éããŸããã ååãªããŒã¿ãéä¿¡ããªãã£ããããã®ããŒãžã¯ãµãŒããŒããã®ããŒã¿ã®äºååä¿¡ããµããŒãããŠããŸããã ãããããã³ãã®ä»ã®ããŸããŸãªå¶éã®ãããæåã®ããŒãžã®ããŒãçŽåŸã«ããã€ãã®APIãªã¯ãšã¹ããè¡ãå¿ èŠããããŸãã
éåžžãããã¯åé¡ã§ã¯ãããŸããã ãã ãããã©ãŠã¶ãŒããµãŒãã¹ã¯ãŒã«ãŒã®çŸåšã®ããŒãžã§ã³ããŸã ã€ã³ã¹ããŒã«ããŠããªãå Žåã¯ãã€ã³ã¹ããŒã«ã®å¿ èŠæ§ã«ã€ããŠéç¥ããå¿ èŠããããŸããããã«ãããããŸããŸãªJSãCSSãªãœãŒã¹ãããã³ã€ã¡ãŒãžã®äºåãã£ãã·ã¥ã§çŽ50件ã®ãªã¯ãšã¹ããçºçããŸãã
ãµãŒãã¹ã¯ãŒã«ãŒãããã«ç»é²ããç°¡åãªã¢ãããŒãã䜿çšããå Žåããã©ãŠã¶ãŒã§ã®ãããã¯ãŒã¯ã®æ··éã芳å¯ãããèš±å¯ãããåæãªã¯ãšã¹ãã®æ°ã®äžéã«éããŸããïŒ2ã3ã®ã¹ã¯ãªãŒã³ã·ã§ããã®äžéšïŒã
Service Workerãããã«ç»é²ãããšãä»ã®ãã¹ãŠã®ãããã¯ãŒã¯èŠæ±ïŒäžèšïŒããããã¯ã§ããããšã«æ³šæããŠãã ããã èã«çœ®ããšïŒäžïŒããã©ãŠã¶ã§ã®åææ¥ç¶æ°ã®å¶éã«ãããããã¯ãããããšãªããããŒãžãããŒããããå¿ èŠãªãããã¯ãŒã¯èŠæ±ãè¡ãããšãã§ããŸãã
è¿œå ã®APIãªã¯ãšã¹ããå®äºããŠCSSãªãœãŒã¹ãšç»åãããŒãããããŸã§ããµãŒãã¹ã¯ãŒã«ãŒã®ç»é²ãé ãããŸããã ããã«ãããäžã®ã¹ã¯ãªãŒã³ã·ã§ããã«ç€ºãããã«ãããŒãžã®ã¬ã³ããªã³ã°ãå®äºããå¿çæéãççž®ã§ããŸããã
äžè¬ã«ãããã«Twitter Liteã®éçšã§è¡ã£ãå€ãã®æ¹åã®ã»ãã®äžéšã瀺ããŸããééããªããä»ã®æ¹åç¹ããããçºèŠãããåé¡ãšãã®è§£æ±ºæ¹æ³ã«ã€ããŠåŒãç¶ã話ãåãããšãæãã§ããŸããReactãšPWAã«é¢ãããªã¢ã«ã¿ã€ã ã®æ å ±ãšæ°ããæŽå¯ã«ã€ããŠã¯ãTwitterã§ç§ãšéçºããŒã ããã©ããŒããŠãã ããã