ã¹ã¯ãªãŒã³ã·ã§ããã䜿çšããŠã¬ã€ã¢ãŠãã®ååž°ããã¹ãããã®ã¯æµè¡ã§ãã誰ãé©ããªãã§ãããã ç§ãã¡ã¯é·ãéããã®çš®ã®ãã¹ããèªå®
ã§å°å
¥ããããšèããŠããŸããã ãµããŒããšã¢ããªã±ãŒã·ã§ã³ã®äœ¿ããããã®è³ªåã¯åžžã«æ··ä¹±ãæããŸããããããã¯å€§éšåããœãªã¥ãŒã·ã§ã³ã®åž¯åå¹
ã§ããã ç§ã¯ããã䜿ãããããåäœãéããã®ã§ããããšãæãã§ããŸããã æ¢è£œã®ãœãªã¥ãŒã·ã§ã³ã¯é©åããªãã£ããããç§ãã¡ã¯ç¬èªã®ããšãããããšãçŽæããŸããã
ã«ããã®äžã§ããã®çµæã解決ããã¿ã¹ã¯ãããã³ã¹ã¯ãªãŒã³ã·ã§ããã§ã®ãã¹ãããã¹ãã®å®äºã«ããã£ãåèšæéã«å®è³ªçã«åœ±é¿ããªãããšã確èªããæ¹æ³ã説æããŸãã ãã®æçš¿ã¯ã HolyJS 2017 Moscowã§é
ä¿¡ãããã¬ããŒãã®è»¢åã§ãã ãªã³ã¯ã§ãããªãèŠãããšãã§ããäžã®ã¹ã©ã€ããèªãã§èŠãããšãã§ããŸãã

ã¿ãªãããããã«ã¡ã¯ãç§ã®ååã¯ããŒãã§ãã ç§ã¯Avitoã§åããŠããŸãã ç§ã¯ããªãŒãã³ãœãŒã¹ãããã€ãã®ãããžã§ã¯ãã®äœæè
ãå«ãå€ãã®ããšã«åŸäºããŠããŸãïŒ CSSTree ã base.js ã rempl ã CSSOã¡ã³ãããŒãªã© ã
ä»æ¥ã¯ãã¹ã¯ãªãŒã³ã·ã§ããã䜿çšããŠåäœãã¹ãã«ã€ããŠèª¬æããŸãã ãã®ã¬ããŒãã¯ããšã³ãžãã¢ãªã³ã°ãœãªã¥ãŒã·ã§ã³ã®æ€çŽ¢ã«é¢ããã¹ããŒãªãŒã§ãã ãã¹ãŠã®æ©äŒã«ã¬ã·ããæäŸããããã§ã¯ãããŸããã ããããç§ã¯æèã®æ¹åãå
±æããŸãïŒãã¹ãŠãããŸãããããã«ã©ããžè¡ããã
èªè»¢è»ã¯å¿
ãããæªãããã§ã¯ãããŸããã ç§ãç¥ã£ãŠãã人ã¯ãããããã®æ¢è£œãããã«ãããããããç§ã¯ãã°ãã°æ°ããããšãããããšããããšãèŠããŠããŸãã ããã¯äœã«ã€ãªãããŸããïŒ ãããããªããã°ã解決çãèŠã€ããããšãã§ããŸãããæ¢ããŠããå Žæã§ã¯ãããŸããã
æ¬æ¥ãã¹ã¯ãªãŒã³ã·ã§ããã®ããŒããçºè¡šããã®ã§ãã³ãŒããæé©åããã ãã§ãªãããã¹ããå éã§ãããšèšããŸãã åé¡ã¯ããã ãã§ã¯ãªããããããŸããã ãããŠãå®éšããŠãé¢çœãåããšè§£æ±ºçãåŸãããšãã§ããŸãã
åé¡ãçºçããå ŽåãçŸä»£ã®ããã³ããšã³ããã³ããŒã¯éåžžãããã«NPMãStackOverflowã«ã¢ã¯ã»ã¹ããæ¢è£œã®ãœãªã¥ãŒã·ã§ã³ã䜿çšããããšããŸãã ãã ããnpm installã圹ç«ã€ãšã¯éããŸããã ãåéºäž»çŸ©ã®ç²Ÿç¥ã¯ç§ãã¡ã®äžã«æ¶ããŠããŸã£ããïŒç§ãã¡ã¯èªåèªèº«ã§äœããæ·±ããããšããããšã¯ãã£ãã«ãããŸããã

ä¿®æ£ããŸãã
åäœãã¹ãïŒããŒã«
ãã¹ãã¯ç°ãªãå ŽåããããŸãïŒãŠããããæ©èœãçµ±å...ãã®ã¬ããŒãã§ã¯ãã¬ã€ã¢ãŠãã®ãªã°ã¬ãã·ã§ã³ããã¹ãããã³ã³ããŒãã³ããŸãã¯ãããã¯ã®ãŠããããã¹ãã«ã€ããŠèª¬æããŸãã
ç§ãã¡ã¯ãã®ãããã¯ã«é·ãéåãçµãã ãã£ãã®ã§ããããã¹ãŠãæã«å±ããŸããã§ããã ã·ã³ãã«ã§å®äŸ¡ã§é«éãªãœãªã¥ãŒã·ã§ã³ãå¿
èŠã§ããã
ãªãã·ã§ã³ã¯äœã§ããïŒ
- æºåãµãŒãã¹
- Geminiãªã©ã®æ¢è£œããŒã«ã
- ç¬èªã«æžãããšãã§ããŸãã
ç¹å®ã®çç±ã«ããããµãŒãã¹ã¯ç§ãã¡ã«åããŸãããå€éšã®ãµãŒãã¹ã䜿çšããããªãããã¹ãŠãå
éšã«ãããã®ã§ãã
å®æããããŒã«ã¯ã©ãã§ããïŒ ãããã¯ããã€ããããŸãããéåžžã¯URLãæ©ããŠç¹å®ã®ãããã¯ããã¯ãªãã¯ãããããšã«çŠç¹ãåãããŠããŸãã ããã¯ç§ãã¡ã«ã¯ããŸãé©ããŠããŸããã§ãããã¹ã¯ãªãŒã³ã·ã§ãããæ®ã£ãŠãã³ã³ããŒãã³ããšãããã¯ããããã®ç¶æ
ããã¹ããããã£ãã®ã§ãã
Yandex GeminiããŒã«ã¯äŸ¿å©ã§ãããå®å®è¹ã®ããã«èŠããŸãã å§ããŠèšå®ããã®ã¯é£ãããããããã®ã³ãŒããæžãå¿
èŠããããŸãã ããããããã¯åé¡ã§ã¯ãããŸããã ããããç§ã«ãšã£ãŠã®åé¡ã¯ãreadmeããç°¡åãªãã¹ããè¡ããããã100åã³ããŒãããšããã®å³ãåŸãããããšã§ãã100åã®282x200ã€ã¡ãŒãžãçŽ2åéãã§ãã¯ãããŸãã ããã¯éåžžã«é·ãæéã§ãã
ãã®çµæã圌ãã¯èªåã®ããšãå§ããŸããã ããã«ã€ããŠã¯ãä»æ¥ã®ã¬ããŒãã«ãªããŸãã å
ã«é²ã¿ãŸãïŒäœãèµ·ãã£ãã®ãã瀺ããŸãã

ãã®ãããReactã«ããçš®ã®ãã¹ãããŒã¯ã¢ããã³ã³ããŒãã³ããtoMatchSnapshotImage()
ãã¹ã¯ãªãŒã³ã·ã§ãããæ®ãããããžãã¯ãã¡ãœããtoMatchSnapshotImage()
ãåŒã³åºã1è¡ãè¿œå ããŸãã ã€ãŸãããã¹ãã«1è¡è¿œå ããŸããç¹ã«ãã¹ã¯ãªãŒã³ã·ã§ããã§ã³ã³ããŒãã³ãã®ã¹ããŒã¿ã¹ã確èªããŸãã
æ°åã§ïŒãµã€ãºã800x600ã®2ã€ã®åäžã®ã¹ã¯ãªãŒã³ã·ã§ãããæ¯èŒãããšããœãªã¥ãŒã·ã§ã³ã§ã¯çŽ0ããªç§ããããŸãã ã¹ã¯ãªãŒã³ã·ã§ãããå°ãç°ãªããç°ãªããã¯ã»ã«ãæ°ããå¿
èŠãããå ŽåãçŽ100ããªç§ããããŸãã åç
§ã¹ã¯ãªãŒã³ã·ã§ããã®ãããŒã¹ããåæåãããšããã¹ã¯ãªãŒã³ã·ã§ããã®æŽæ°ãåçã®ååŸãã¹ã¯ãªãŒã³ã·ã§ããããšã«çŽ25ããªç§ããããŸãã ãããããããã§ããããšå°ãã§ããããšãç§ãã¡ã¯åŸã§èŠãã§ãããã
çŸåšã®ã¬ã€ã¢ãŠãããã¹ã¯ãªãŒã³ã·ã§ãããåããæšæºãšæ¯èŒã§ãã決å®ãäžãå Žåãäœãããå¿
èŠããããŸããïŒ ãŸããå¿
èŠãªã¹ã¿ã€ã«ãšãªãœãŒã¹ãåããã³ã³ããŒãã³ãã®éçã¬ã€ã¢ãŠããååŸããããããã¹ãŠãã©ãŠã¶ãŒã«ããŒãããã¹ã¯ãªãŒã³ã·ã§ãããæ®ã£ãŠãåç
§ã¹ã¯ãªãŒã³ã·ã§ãããšæ¯èŒããŸãã ããã»ã©é£ãããããŸããã

ããŒã¯ã¢ããçæ
ããŒã¯ã¢ããã®çæããå§ããŸãããã ããã€ãã®ã¹ãããã«åãããŠããŸãã æåã«ãHTMLã³ã³ããŒãã³ããçæããŸãã 次ã«ãã©ã®åŸå±éšåã§ãããã決å®ããŸãã圌ã䜿çšããã¹ã¿ã€ã«ãå¿
èŠãªç»åã®çš®é¡ãªã©ã§ãã ããããã¹ãŠãåäžã®HTMLããã¥ã¡ã³ãã«å
¥ããããšããŠããŸãããã®ããã¥ã¡ã³ãã«ã¯ãããŒã«ã«ãªãœãŒã¹ããã¡ã€ã«ãžã®ãªã³ã¯ã¯ãããŸããã
HTMLçæ
HTMLã®çæã¯ã䜿çšããŠããã¹ã¿ãã¯ã«å€§ããäŸåããŠããŸãã ç§ãã¡ã®å Žåãããã¯Reactã§ãã æ¢è£œã®react-dom / serverã©ã€ãã©ãªã䜿çšããŸããããã«ãããå¿
èŠãªHTMLã§ããéçãªæååãçæã§ããŸãã

ã€ãŸãã react-dom/server
ãæ¥ç¶ãã renderToStaticMarkup()
ã¡ãœãããåŒã³åºãreact-dom/server
renderToStaticMarkup()
ãååŸããŸãã
CSSçæ
ããã«é²ãïŒCSSçæã ãã§ã«HTMLããããŸãããå€ãã®ã¹ã¿ã€ã«ããã®ä»ã®ãªãœãŒã¹ããŸã æ®ã£ãŠããå¯èœæ§ããããŸãã ãããã¯ãã¹ãŠåéããå¿
èŠããããŸãã ããã§ã®è¡åèšç»ã¯äœã§ããïŒ ãŸããã³ã³ããŒãã³ãã§æ¥ç¶ãã䜿çšãããŠãããã¡ã€ã«ãèŠã€ããå¿
èŠããããŸãã CSSãã¡ã€ã«ãå€æããŠããªãœãŒã¹ãžã®ãªã³ã¯ãå«ãŸããªãããã«ããŸãã ã€ãŸãããªãœãŒã¹ãžã®ãªã³ã¯ãèŠã€ããŠãããããCSSèªäœã«ã€ã³ã©ã€ã³åããŸãã 次ã«ããã¹ãŠãæ¥çããŸãã
ããã§ãã解決çã¯ã¹ã¿ãã¯ã«äŸåããŸãã ãã®ã±ãŒã¹ã§ã¯ã Jestããã¹ãã©ã³ããŒã Babelã䜿çšããŠJavaScriptããã³CSSã¢ãžã¥ãŒã«ãå€æããã¹ã¿ã€ã«ãèšè¿°ããŸãã
éå§ããã«ã¯ãCSSãã¡ã€ã«æ€çŽ¢ãå®è¡ããŸãã

CSSã¢ãžã¥ãŒã«ã¯ãCSSãJavaScriptã§éåžžã®ã¢ãžã¥ãŒã«ãšããŠæ¥ç¶ãããŠããããšãæå³ããŸããã€ãŸãã import
ãŸãã¯require()
䜿çšããŸãã
æè¡çã«ã¯ããã®ãããªåŒã³åºãããã¹ãŠã€ã³ã¿ãŒã»ããããèŠæ±ããããã¹ãä¿æããããã«å€æããå¿
èŠããããŸãã
ãããè¡ãããã«ãBabelã®ãã©ã°ã€ã³ãäœæããŸããã Jestã«ã¯JavaScriptå€æãã«ã¹ã¿ãã€ãºããæ©èœããããŸãïŒJestã䜿çšããŠããå Žåã¯ããã§ã«ãããè¡ã£ãŠããå¯èœæ§ããããŸãïŒã transform
èšå®ã䜿çšããŠãã«ãŒã«ã«äžèŽãããªãœãŒã¹ãå€æããã¹ã¯ãªãããè¿œå ãããŸãã ãã®å ŽåãJavaScriptãã¡ã€ã«ãå¿
èŠã§ãã

ã¹ã¯ãªããã¯ã babel-jest
ã䜿çšããŠãã©ã³ã¹ãã©ãŒããŒãäœæããŸãã ä»ã®èšå®ã«ãç¬èªã®ãã©ã°ã€ã³ãè¿œå ããå¿
èŠããããŸããããã¯å¿
èŠãªããšãè¡ããŸãã

ãã©ã°ã€ã³ã¿ã¹ã¯ã¯2ã€ã®éšåã§æ§æãããŠããŸãã æåã«ã require()
ãããã¹ãŠã®import
ã«å¯ŸããŠæ€çŽ¢ãè¡ããããããCSSæ¥ç¶ãæ¢ãæ¹ãç°¡åã§ãã ãã®åŸããã¹ãŠã®require()
ç¹å¥ãªé¢æ°ã«çœ®ãæããããŸãïŒ

ãã®ãããªé¢æ°ã¯ããã¹ãæ ŒçŽããããã«ã°ããŒãã«é
åãåæåãããã®é
åã«æ°ãããã¹ãè¿œå ããŠã眮æãããå
ã®ãšã¯ã¹ããŒããè¿ããŸãã ãã©ã°ã€ã³ã³ãŒãã¯52è¡ã§ãã ãœãªã¥ãŒã·ã§ã³ã¯ç°¡çŽ åã§ããŸããããããŸã§ã¯å¿
èŠãããŸããã§ããã
ã³ã³ããŒãã³ãã®HTMLããŒã¯ã¢ãããçæãããšãã includedCssModules
é
åã«ã¯ã require()
ä»ããŠrequire()
ããããã¹ãŠã®ãã¹ãå«ãŸããŸãã æ®ã£ãŠããã®ã¯ããã¹ããããã®ãã¡ã€ã«ã®ã³ã³ãã³ãã«å€æããããšã ãã§ãã
CSSåŠç
ãã®æ®µéã§ã¯ããã¹ãŠã®CSSãã¡ã€ã«ã調ã¹ãŠããããã®ãªãœãŒã¹ãžã®ãªã³ã¯ãèŠã€ããŠã€ã³ã©ã€ã³åããå¿
èŠããããŸãã ãŸãããã€ããã¯ã¹ããªãã«ããå¿
èŠããããŸããã¢ãã¡ãŒã·ã§ã³ãŸãã¯äžéšã®ãã€ãããã¯ããŒãã䜿çšãããšãçµæãç°ãªãå Žåããããäºæž¬ã§ããªãç¬éã«ã¹ã¯ãªãŒã³ã·ã§ãããæ®ãããšãã§ããŸãã
ã€ã³ã©ã€ã³ãªãœãŒã¹
ãªãœãŒã¹ãã€ã³ã©ã€ã³åããããã«ãå¥ã®ãã©ã°ã€ã³ãäœæããŸããã ïŒæ¢è£œã®ãã®ã䜿çšã§ããŸããããã®å Žåãç¬èªã®ãã®ãäœæããæ¹ãç°¡åã§ããããšãå€æããŸããïŒã

ããã¯ãã¹ãŠã©ã®ããã«èŠããŸããïŒ ãã©ã°ã€ã³ãjest-transform
è¿œå ããããšãèŠããŠããŸããïŒ è©±ã¯ããã§ãåãã§ããCSSã¢ãžã¥ãŒã«çšã®ç¹å¥ãªãã©ã°ã€ã³ãã€ãŸãbabel-jest
css-modules-transform
ã®ã¿ã䜿çšãcss-modules-transform
ãããã¯ãCSSããªããã»ã¹ãã«ã¹ã¿ãã€ãºããæ©èœãåããŠããŸãã
ãããã£ãŠã processCss
ã§ãã©ã°ã€ã³ãžã®ãã¹ãè¿œå ãããã©ã°ã€ã³èªäœãèšè¿°ããŸãã CSSTreeããŒãµãŒã䜿çšãããŸãã ããã¯ç§ããã®èè
ã ãšããã ãã§ã¯ãããŸãã;ïŒ-ããã¯é«éã§è©³çŽ°ã§ãããäŸãã°è€éãªRegExp
ãªãã§ãã¹ãšURLãæ€çŽ¢ããããšãå¯èœã«ããŸãã ãŸãããšã©ãŒèæ§ããããŸããCSSã«ç解ã§ããªãéšåãããå Žåãäœãå£ããããããã®éšåã ããçµã¿ç«ãŠãããªããŸãŸã«ãªããŸãã ããããããã¯ãã£ãã«èµ·ãããŸããã

ãã©ã°ã€ã³ã¯URLã§CSSãæ€çŽ¢ããã€ã³ã©ã€ã³ãªãœãŒã¹ã«çœ®ãæããŸãã
ããã§äœãèµ·ãã£ãŠããŸããïŒ æåã®è¡ã§ASTãååŸããŸããã€ãŸããCSSæååãããªãŒã«è§£æããŸãã 次ã«ããã®ããªãŒãäžåšãã Url
ã¿ã€ãã®ããŒããèŠã€ããããããå€ãéžæããŠãã€ã³ã©ã€ã³åãããã¡ã€ã«ãžã®ãã¹ãšããŠäœ¿çšããŸãã æåŸã«ã translate
ãåŒã³åºãã ãã§ããã€ãŸããå€æãããããªãŒãæååã«å€æããŸãã

ã€ã³ã©ã€ã³ãªãœãŒã¹ã®å®è£
ã¯ãèŠããã»ã©è€éã§ã¯ãããŸããã
- URIãååŸããããã䜿çšãããŠããCSSãã¡ã€ã«ã«é¢é£ããŠè§£æ±ºããŸãïŒãã¹ãçžå¯Ÿçã§ããããïŒã
- ãã¡ã€ã«ãããã€ããªããŒã¿ãèªã¿åããŸãã
- æ¡åŒµæ©èœã«ãã£ãŠMIMEã¿ã€ããèšç®ããŸãã
- ãªãœãŒã¹ã®ããŒã¿URIãçæããŸãã
ããã ãã§ãïŒ ã€ã³ã©ã€ã³ãªãœãŒã¹ããããŸãã 説æãããŠããæ©èœã¯ãå¿
èŠãªãã¹ãŠãå®è¡ãã26è¡ã®ã³ãŒãã§ãã
ç¬èªã®ãœãªã¥ãŒã·ã§ã³ãäœæããã®ã«åœ¹ç«ã€ãã®ã¯ä»ã«ãããŸããããšãã°ããããæ¡åŒµã§ããŸããããšãã°ãåŸã§ã¢ãã¡ãŒã·ã§ã³GIFã®éçç»åãžã®å€æãè¿œå ããŸããã ããããããã«ã€ããŠã¯åŸã§ã
ãã€ããã¯ã¹ãåãé€ã
次ã®ã¹ãããã¯ããã€ããã¯ã¹ãåãé€ãããšã§ãã ã¢ãã¡ãŒã·ã§ã³ãããªãŒãºããæ¹æ³ãšããã¯ã©ãã§çºçããŸããïŒ
ãã€ããã¯ã¹ã¯æ¬¡ã®å Žæã«è¡šç€ºãããŸãã
- CSSãã©ã³ãžã·ã§ã³
- CSSã¢ãã¡ãŒã·ã§ã³
- å
¥åãã£ãŒã«ãã®ç¹æ»
ãããã£ãªããžã§ããã€ã§ãæ¶ããã衚瀺ããããããããšããããŸãã
- ã¢ãã¡ãŒã·ã§ã³GIFããã®ä»ã®ç¬éã
åãçµæãåžžã«åŸãããããã«ããã®ãã¹ãŠããåæãããããšããŸãã
CSSã®ç§»è¡
ãã¹ãŠã®transitions-delay
ããã³transition-duration
ãŒãã«ããŸãã

ãã®å Žåããã¹ãŠã®transition
ãæçµç¶æ
ã«ããããšãä¿èšŒãããŸãã
CSSã¢ãã¡ãŒã·ã§ã³
CSSã¢ãã¡ãŒã·ã§ã³ã§ãåãããšãè¡ããŸãã

ããã§ã¯ããã®ããã¯ãèŠãããšãã§ããŸãïŒ

animation-delay: â0.0001s
å€ã«æ³šæããŠãã ããanimation-delay: â0.0001s
ã å®éã®ãšãããããããªããšãSafariã§ã¯ã¢ãã¡ãŒã·ã§ã³ã«æçµç¶æ
ããããŸããã
ãããŠæåŸïŒã¢ãã¡ãŒã·ã§ã³ãæåŸãŸã§é§åããŸããïŒæçµç¶æ
ïŒããã¢ãã¡ãŒã·ã§ã³ã¯é·ç§»ãç¹°ãè¿ãããšãã§ãããšããç¹ã§ç°ãªããŸãã ãããã£ãŠã animation-play-state
ãpaused
èšå®ããŠã animation-play-state
ãpaused
ãŸãã ãããã£ãŠãã¢ãã¡ãŒã·ã§ã³ã¯äžæåæ¢ãã€ãŸãåçãåæ¢ããŸãã

ãã£ãªããž
次ã®ç¬éã¯ããã£ãŒã«ãã§ã®ééã§ãã åé¡ã¯ç¹æ»
ããããšã§ããããæç¹ã§åçŽç·ã衚瀺ãããããæç¹ã§-ãããã ããã¯ãçµæã®ã¹ã¯ãªãŒã³ã·ã§ããã«åœ±é¿ããå ŽåããããŸãã
ããæ°ãæã§ã caret-color
ãªã©ã®æ©èœããã©ãŠã¶ãŒã«ç»å ŽããŸãããæåã¯Chromeã§ã次ã«FirefoxãšSafariïŒãã¯ãããžãŒãã¬ãã¥ãŒïŒã§ããã ãã£ãªããžãããªããã«ããã«ã¯ããã£ãªããžãéæã«ããŸãïŒè²ãtransparent
èšå®ããŸãïŒã ãããã£ãŠããã£ãªããžã¯åžžã«é衚瀺ã«ãªããçµæã«ã¯åœ±é¿ããŸããã
ä»ã®ããŒãžã§ã³ã®ãã©ãŠã¶ã®å Žåãä»ã®ããŒãžã§ã³ãäœæããå¿
èŠããããŸãããããã¯ã¹ã¯ãªãŒã³ã·ã§ããã«äœ¿çšããå Žåã®ã¿ã§ãã

GIF
GIFã®å Žåãç¶æ³ã¯ããå°ãè€éã§ãã ã¿ã¹ã¯ã¯ãã¢ãã¡ãŒã·ã§ã³GIFãã1ã€ã®éçãã¬ãŒã ãæ®ãããšã§ãã ç§ã¯ãã®ããã®ã¢ãžã¥ãŒã«ãèŠã€ããããšãããããå
¥ããŠåé¡ãå¿ããããšããŸããã ãã®çµæãåçã®ãµã€ãºãå€æŽãããããã¬ãããå€æŽããããè€æ°ã®ç»åããGIFãäœæããããéã«ã¢ãã¡ãŒã·ã§ã³GIFããäžé£ã®ç»åãäœæãããããå€ãã®ã©ã€ãã©ãªãèŠã€ããŸããã ããããã¢ãã¡ãŒã·ã§ã³GIFãéçã«ããããã±ãŒãžã¯èŠã€ãããŸããã§ããã ç§ã¯èªåã§æžããªããã°ãªããŸããã§ããã
ã©ã€ãã©ãªã2æéæ€çŽ¢ããåŸãç§ã¯GIF圢åŒãã©ãã»ã©è€éãã調ã¹ãããšã«ããŸããã ç§ã¯Vickiãèªãã§ã89幎ç®ããä»æ§ãå
¬ââéããŸããã

GIFã¯ããã€ãã®ãããã¯ã§æ§æãããŠããŸããæåã«ãç»åã®ãµã€ãºã説æãã眲åãšãã€ã³ããã¯ã¹ä»ãã®è²ã®è¡šããããŸãã 次ã«ããããã¯ã¯é çªã«ç§»åããŸããã°ã©ãã£ãã¯ã¹ãæ
åœããç»åèšè¿°åãããã¯ãšããã¬ãããããã¹ããã³ã¡ã³ããèäœæš©ãªã©ãä¿åã§ããæ¡åŒµãããã¯ã§ãã ãã¡ã€ã«ã®æåŸã«ã¯TrailerããããŸããããã¯ãGIFãçµãã£ããšããç¹å¥ãªãããã¯ã§ãã
ãããã£ãŠããããã®ãããã¯ãééããŠãæåãé€ããã¹ãŠã®ç»åèšè¿°åãããã¯ããã£ã«ã¿ãªã³ã°ïŒåé€ïŒããå¿
èŠããããŸãã å¿
èŠãªã³ãŒããå«ãGistãžã®ãªã³ã¯ã次ã«ç€ºããŸãã æ°æéã§æžããŠãããã°ããŸããããå®ç§ã«æ©èœããŠããŸããããåé¡ã¯èŠã€ãããŸããã§ããã
çµè«ïŒGIFç»åã¯éçãã¢ãã¡ãŒã·ã§ã³ã¯ãªãããã¹ãŠã®CSSãã¹ããããŸãã æ¥çå€ã®ãŸãŸã§ãã ãã£ãšã·ã³ãã«ã«ã§ãããã®ãããããã«æããŸããïŒ
CSSã¹ãã©ã€ã·ã³ã°
Jestã®ä»çµã¿ãèŠãŠã¿ãŸãããã éåžžã䞊è¡ããŠå®è¡ããããã¹ããå®è¡ããè€æ°ã®ã¹ã¬ãããå®è¡ããŸãã åãã¹ããã¡ã€ã«ã¯ããããã®ã¹ããªãŒã ã§èµ·åãããåãã¡ã€ã«ã¯å¥ã®ã³ã³ããã¹ãã§ãããä»ã®ã³ã³ããã¹ãéã§ããŒã¿ã移åããŸããã ãããŠåé¡ã¯ãCSSãã¡ã€ã«ã®ãœãŒã¹ã³ãŒãã«ã¢ã¯ã»ã¹ããCSSå€æããã¹ãã®ã³ã³ããã¹ãå€ã«ããããã®ã³ã³ãã³ãã«ã¢ã¯ã»ã¹ã§ããªãããšã§ãã CSSã¯ãã¡ã€ã«ãããèªã¿åãããšãã§ããŸãããCSSã¯ãã§ã«å€æãããŠãããJavaScriptèªäœã«äœããã®ç°å¢ãã³ã³ããã¹ããã¯ãŒã«ãŒã§ä¿åãããŠããããã§ãã
ãã¹ãéã§CSSã調ã¹ãæ¹æ³ã¯ïŒ å°ããªããã¯ãäœããŸããã åã¯ãŒã«ãŒã¯JSON圢åŒã®äžæãã¡ã€ã«ãäœæããŸããããŒã¯CSSãžã®ãã¹ã§ãããå€èªäœã¯æ¢ã«CSSã«å€æãããŠããŸãã åã¹ã¬ããã¯ãã®ãã¡ã€ã«ãèªã¿åããããããå¿
èŠãªãã®ãååŸãããã¹ãã®ã³ã³ããã¹ãå
ã§é£çµããŸãã

ããã§ãäžæãã¡ã€ã«ãèªã¿åããJSONã§è§£æããå¿
èŠãªã³ã³ãã³ããè¿œå ããŸãã ãã¡ã€ã«åãããŒãCSSãå€æãããå€ã§ãã ãããŠãå€æãããããããæžãæ»ããŸãã

ã¹ã¯ãªãŒã³ã·ã§ããã®CSSãçæãããšãããã®ãã¡ã€ã«ããèªã¿åãã includedCssModules
ïŒCSSãã¹ã®é
åïŒã䜿çšããå¿
èŠãªãã¡ã€ã«ã®ã³ã³ãã³ããååŸããŠjoin()
ãŸãã
ãã¹ãŠãäžç·ã«åéããããšãæ®ã£ãŠããŸãã
æçµçµç«

æçµçãªHTMLãçæããŸãã æåã«ããã€ããã¯ã¹ïŒã¢ãã¡ãŒã·ã§ã³ïŒããªãã«ããã¹ã¿ã€ã«ãèšå®ããŸãã 2çªç®ã®ã¹ã¿ã€ã«ã§ã¯ãèŠã€ãã£ããã¹ãŠã®æ¥çãããCSSãæ¥ç¶ããŸãã åãã¹ãã«ã¯ãããã®ã¹ã¿ã€ã«ã®ç¬èªã®ã»ããããããŸããã³ã³ããŒãã³ãã®require()
ãè¡ãrequire()
ããªã¹ãã«ããäŸåé¢ä¿ããã«ã¢ãããããããã§ãã ãã®çµæã䜿çšãããCSSãã¡ã€ã«ã®ã¿ãæ¥ç¶ããããããžã§ã¯ãå
ã®ãã¹ãŠã®CSSã¯æ¥ç¶ãããŸããã HTMLããããã以åã«åãåã£ã-ããã¯ã³ã³ããŒãã³ãèªäœã®ã³ãŒãã§ãã
ãã®çµæãç®æšãéæããŸããã é©åãªç¶æ
ã®HTMLã³ã³ããŒãã³ããšãå¿
èŠãªCSSãçæã§ããŸãã
ããã§ããã¹ãŠã®ããŒã¯ã¢ãããçµã¿ç«ãŠãããã¢ãã¡ãŒã·ã§ã³ããªãã«ãªããŸã-ãã¹ãŠãã¹ã¯ãªãŒã³ã·ã§ãããæ®ãæºåãã§ããŸããã ãœãªã¥ãŒã·ã§ã³ã¯å®ç§ã§ã¯ãããŸããããããè¯ãããããšãã§ããŸããããããšã¬ã¬ã³ãã§å®å®ãããœãªã¥ãŒã·ã§ã³ãåŸãã«ã¯ãJestãBabelãCSSã¢ãžã¥ãŒã«ãªã©ãããã«æãäžããå¿
èŠããããŸãã ããããå
šäœãšããŠãããã¯ç§ãã¡ã«åã£ãŠãããå
ã«é²ãããšãã§ããŸãã
ã¹ã¯ãªãŒã³ã·ã§ãã
ä»æ¥ããã©ãŠã¶ã§ã¹ã¯ãªãŒã³ã·ã§ãããæ®ãã®ã¯ãšãŠãç°¡åã§ãã æ°å¹Žåãããã¯é£ããäœæ¥ã«ãªãå¯èœæ§ããããè€éãªãœãªã¥ãŒã·ã§ã³ã䜿çšããå¿
èŠããããŸããã çŸåšãGUIãªãã§å®è¡ããããããã¬ã¹ãã©ãŠã¶ãŒããããä»»æã®ã³ãŒããããŠã³ããŒãããŠãã¹ã¯ãªãŒã³ã·ã§ããã®æ®åœ±ãªã©ããã®åäœã確èªã§ããŸãã
ãŸããææ°ã®ãã©ãŠã¶ãŒã¯ãã¹ãŠWebDriverããµããŒãããŠããŸãã ããšãã°ãSeleniumã䜿çšããå Žåããã¹ãŠãæ¯èŒçç°¡åã§ãã ãã®ãããªç°å¢åãã®ãã¹ãã®èšè¿°ãç°¡çŽ åããã©ã€ãã©ãªãŒããã«ããŒããããŸãã
ãã®å Žåãåäžã®ãã©ãŠã¶ã䜿çšããŠç°¡åãªæ¯èŒãè¡ããŸããã ãã©ãŠã¶ãŒéã®æ¯èŒãè¡ãå¿
èŠã¯ãããŸããã§ããããChromeãããã¬ã¹ãå®è¡ã§ããç¹å¥ãªã©ã€ãã©ãªãŒã§ããPuppeteerã䜿çšãããããæäœããããã®é©åºŠã«äŸ¿å©ãªã€ã³ã¿ãŒãã§ãŒã¹ãæäŸããŸããã ã¹ã¯ãªãŒã³ã·ã§ãããæ®ãäž»ãªã³ãŒãã¯æ¬¡ã®ãšããã§ãã

Puppeteerãããã«æ¥ç¶ããããã©ãŠã¶ãŒãèµ·åããŸããã¹ã¯ãªãŒã³ã·ã§ãããæ®ãå¿
èŠãããå Žåã screenshot()
é¢æ°ãHTMLã§åŒã³åºããŸãã ãã®é¢æ°ã¯ãæ°ããããŒãžãäœæããéä¿¡ãããHTMLãæ¿å
¥ããã¹ã¯ãªãŒã³ã·ã§ãããæ®ããããŒãžãéããŠãã¹ã¯ãªãŒã³ã·ã§ããã®çµæãæäŸããŸãã åäœããŸãã ç°¡åã§ãã ããããããã¯ããã»ã©åçŽã§ã¯ãªãããšãå€æããŸããã
å®éãã³ãŒããããŒã«ã«ã§å®è¡ãããšããã¹ãŠãæ£åžžã«æ©èœããŸãã åç
§ã€ã¡ãŒãžãšæ°ããã€ã¡ãŒãžããããŸããããã¯ãåç
§ãäœæããåãã·ã¹ãã ã§ãåããã©ãŠã¶ãŒããŒãžã§ã³ã§æ°ããã€ã¡ãŒãžãäœæããããã§ãã ããããWindowsã§ã¯ãªãMacã§ã¯ãªããLinuxãç¬èªã®ããŒãžã§ã³ã®Chromeãç¬èªã®ã¢ã³ããšã€ãªã¢ã¹ã«ãŒã«ããã©ã³ããªã©ãååšããªãCIã§ããããã¹ãŠãå®è¡ãå§ãããšããç»åã¯ç°ãªã£ãŠããŸããã ã€ãŸãã圌ãã¯ç°ãªãçµæãåŸå§ããŸããã
ã©ããã ããã€ãã®è§£æ±ºçããããŸãã ããã€ãã®è§£æ±ºçã¯ãæ°åŠã®å©ããåããŠãã®éããå
æããããšããŸãã ãã¯ã»ã«ããšã«æ¯èŒããã®ã§ã¯ãªãããã¯ã»ã«ãšé£æ¥ãããã¯ã»ã«ãæ¯èŒããŸããã€ãŸããç¹å®ã®èš±å®¹å€ã䜿çšããå³å¯ã§ãªãæ¯èŒã§ãã ããã¯é«äŸ¡ã§ãã©ããããããå¥åŠã§ãããã¯ã»ã«ããšã«æ¯èŒããããšæããŸãã
å¥ã®ãœãªã¥ãŒã·ã§ã³ã®æ¹åã«é²ã¿ãŸãããHTMLã³ãŒãã§POSTãªã¯ãšã¹ããéä¿¡ã§ããå€éšãã€ã¯ããµãŒãã¹ãäœæããåºåã§å¿
èŠãªç»åãã¹ã¯ãªãŒã³ã·ã§ãããååŸããŸãã
ç§ãã¡ãåŸãå©ç¹ã¯äœã§ããïŒ ãã¹ããå®è¡ããããã·ã³ã«äŸåããããã©ãŠã¶ã®ããŒãžã§ã³ãæŽæ°ãå€æŽã§ããŸãããã€ã¯ããµãŒããŒã®åŽã«ã¯åžžã«åããã©ãŠã¶ããããåãçµæãåŸãããŸãã
ãŸããæ°ãããããžã§ã¯ãã®ããŒã«ã«èšå®ã¯å¿
èŠãããŸããã ãã©ãŠã¶ãèµ·åããããPuppeteerãªã©ãèšå®ãããããå¿
èŠã¯ãããŸãããPOSTãªã¯ãšã¹ããäœæããŠç»åãååŸããã ãã§ãã ãããã¯ãŒã¯ã³ã¹ãã¯ãããŸãããããã¯ããã«éããå¥åŠãªããšã«ååã§ãã ãµãŒãã¹ã«ãªã¯ãšã¹ããéä¿¡ããŸãããã£ãã·ã¥ãšãŠã©ãŒã ã¢ããããããã©ãŠã¶ã®äž¡æ¹ããããéåžžã«è¿
éã«ç»åãæäŸããŸãã ããã«ãPNGã¯ååã«å°ãããããæºãããããã¯ãŒã¯ãã©ãã£ãã¯ã¯ããã»ã©å€§ãããããŸããã
çæãã ãµãŒãã¹ã¯ãã€ã§ãäœäžããå¯èœæ§ãããããããå¥åº·ããç£èŠããå¿
èŠããããŸãã åçŽãªããŒãžã«ã¢ã¯ã»ã¹ãããšããŠãããã©ãŠã¶ã¯å€§éã®ã¡ã¢ãªããæ¶è²»ãã§ããããšã誰ããç¥ã£ãŠããŸãã ãµãŒãã¹ã¯çªç¶ããµãã察åŠã§ããããªãœãŒã¹ãéãããŠããŸãã ãŸãããµãŒãã¹ãã¯ã©ãã·ã¥ãããšãç»åãã¬ã³ããªã³ã°ã§ããŸãã-ãã¹ãã¯å€±æããŸãã
ãããã£ãŠãå
šå¡ãåæã«ã¹ã¯ãªãŒã³ã·ã§ããããã§ãã¯ããïŒå®è¡ããïŒããšã決å®ããå Žåã倧ããªè² è·ããããããé·æéåŸ
ããªããã°ãªããªããããµãŒãã¹ãå¿çããªããªãããšããããŸãã åŸè
ã¯å€ããå°ãªãã解決ãããŠããŸããè€æ°ã®ãµãŒãã¹ã€ã³ã¹ã¿ã³ã¹ãäœæããŠè² è·ãåæ£ã§ããããŒã«ã«ã¯ã©ãŠãããããŸãã ããã«ããããããããã®ãããªåé¡ãååšããŸãã ãµãŒãã¹ã®æ»ã¯ã©ã®ããã«èŠããŸããïŒ

åäœãããµãŒãã¹ã®ç¹å®ã®ã€ã³ã¹ã¿ã³ã¹ããããéãããéã®ã¡ã¢ãªïŒãã®å Žåã¯1 GBïŒããããå©çšå¯èœãªãã¹ãŠã®ã¡ã¢ãªããæ¶è²»ãããŠå¿çãåæ¢ã§ããŸãã ãã®ãããªå Žåãåèµ·åã®ã¿ã圹ç«ã¡ãŸãã
ãã€ã¯ããµãŒãã¹ã䜿çšãããœãªã¥ãŒã·ã§ã³ã«ã¯å¥ã®åŽé¢ããããŸãã ã³ãŒãã§ã¹ã¯ãªãŒã³ã·ã§ãããæ®ããšãã³ãŒãã ãã§ãªããURLãšç¹å®ã®ã»ã¬ã¯ã¿ãŒã§ãã¹ã¯ãªãŒã³ã·ã§ãããæäŸããããã«ãµãŒãã¹ã«æãããšããã¢ã€ãã¢ãçãŸããŸããã ãã®å Žåã®ãµãŒãã¹ã®åäœïŒããŒãžã«ç§»åããããŒãžã®å®å
šãªã¹ã¯ãªãŒã³ã·ã§ãããååŸããããæž¡ãããã»ã¬ã¯ã¿ãŒãäžèŽãããããã¯ãååŸããŸãã ããã¯ããã¹ãã«ãŸã£ããé¢ä¿ã®ãªãä»ã®ã¿ã¹ã¯ã«ãšã£ãŠäŸ¿å©ã§äŸ¿å©ã§ããããšãããããŸããã ããšãã°ãçŸåšå®éšäžã§ãïŒããŒãžã®ã¹ã¯ãªãŒã³ã·ã§ããããµãŒãã¹ã®èª¬æããµã€ãã®äžéšãããã¥ã¡ã³ãã«æ¿å
¥ããç»åã®ãµãŒãã¹ãžã®URLïŒ <img>
ïŒã䜿çšããŠãã¬ããžããŒã¹ã«æ¿å
¥ããŸãã ããã¥ã¡ã³ãã«ã¢ã¯ã»ã¹ãããšãåžžã«å®éã®ã¹ã¯ãªãŒã³ã·ã§ããã衚瀺ãããŸãã ãããŠãããããåžžã«æŽæ°ããå¿
èŠã¯ãããŸããã ããã¯éåžžã«èå³æ·±ããœãªã¥ãŒã·ã§ã³ã§ãããããèªäœãå€æããŸããã
ã¹ã¯ãªãŒã³ã·ã§ãããµãŒãã¹ã®URLãç»åãšããŠäœ¿çšããããŒãžãŸãã¯ãããã¯ã®ã¹ã¯ãªãŒã³ã·ã§ãããååŸã§ããã¡ãœããã®ã¢ããªã±ãŒã·ã§ã³ã¯ãããã¥ã¡ã³ãåã ãã§ãªããä»ã®ã¿ã¹ã¯ã«ãéåžžã«åœ¹ç«ã¡ãŸãã ããšãã°ããµã€ãã®æ©èœçãªã°ã©ããäœæã§ããŸããã°ã©ãã®åãããã¯ã«ã¯ããµã€ãã®ããŒã«ã¢ãŠãããšã«æŽæ°ãããããŒãžãŸãã¯ãããã¯ã®ã¹ã¯ãªãŒã³ã·ã§ããããããŸãã
ç»åæ¯èŒ
ãã®ãããã¹ã¯ãªãŒã³ã·ã§ããã䜿çšãããã¹ãã«çŽæ¥ç§»è¡ããŸãã ã³ãŒããååŸãããã®ã³ãŒãããã¹ã¯ãªãŒã³ã·ã§ãããååŸããŸããããããããæ¯èŒããå¿
èŠããããŸãã
Jestã䜿çšããŠã³ã³ããŒãã³ãããã¹ãããŸãã ããã¯éèŠã§ãã
Jestã«ã¯ãã©ãŒæ©èœããããŸã-ã¹ãããã·ã§ããã®æ¯èŒã

ãªããžã§ã¯ããããã€ãã®ããŒã¿ã®ããŒã¯ã¢ãããè¡ãããã®ããŒã¿ã«å¯ŸããŠtoMatchSnapshot()
ã¡ãœãããåŒã³åºãããšãã§ããŸãã ã¡ãœããã®ä»çµã¿ïŒ
JSON.stringify()
ãªã©ã®ããŸããŸãªã¡ãœããã䜿çšããŠJSON.stringify()
ãã§ãã¯ãããå€ãæååã«JSON.stringify()
ãŸãã- ãã¹ããæ°ããå Žåãçµæã¯åŸç¶ã®æ¯èŒã®ããã«çµæã®ããŒã«ã«ããŒã¿ããŒã¹ã«ä¿åãããŸãã
- ãã¹ããåéãããšã以åã®ã¹ãããã·ã§ãããããŒã¿ããŒã¹ããååŸãããçãããã©ããã«é¢ä¿ãªã2è¡ãæ¯èŒãããŸãã ããããçãããªãå Žåããšã©ãŒãçºçããŸããã€ãŸãããã¹ãã¯å€±æããŸãã ãã¹ããåé€ãããå ŽåãJestã¯ããŒã¿ããŒã¹ã«ç¡é¢ä¿ãªã¹ãããã·ã§ãããååšããããããŽãããªãããšã確èªããŸãã
toMatchSnapshot()
ã¡ãœããã䜿çšãããšãã³ã³ããŒãã³ãã®ããŒã¯ã¢ããïŒHTMLïŒãå€æŽããããã©ããã確èªã§ããã¹ãããã·ã§ããã®æ¯èŒãæŽæ°ãä¿åãªã©ã®ããã«ã³ãŒããèšè¿°ããå¿
èŠã¯ãããŸããã éæ³ïŒ
ããããç»åæ¯èŒã«æ»ããŸãã ãã€ããªç»åããããŸãããããã¯æååè¡šçŸã§ã¯ãããŸããã Jestã§ç»åãæ¯èŒããããã®çµã¿èŸŒã¿ããŒã«ã¯ãŸã ãããŸããã ãã®ãããã¯ã«é¢ãã GitHubã®ãã±ããããããŸã ã圌ãã¯ãã«ãªã¯ãšã¹ããåŸ
ã£ãŠããŸãã ãã¶ããæéããããŠèªåã§ããã§ãããã ããããçŸæç¹ã§ã¯American Expressã®ãã©ã°ã€ã³jest-image-snapshotããããŸãã ãã€ããªã€ã¡ãŒãžã®æ¯èŒãããã«éå§ããã®ã«é©ããŠããŸãã 次ã®ããã«ãªããŸãã

ãã®ã¢ãžã¥ãŒã«ããã©ã°ã€ã³expect
jest-image-snapshotããtoMatchImageSnapshot()
expect
æ°ããtoMatchImageSnapshot()
ã¡ãœããã§expect
æ¡åŒµexpect
ãŸãã

. â , , , .
, toMatchImageSnapshot()
. , toMatchSnapshot()
. , . , , , , ( â ), .
? , . , . Jest. ( , Jest : , , . CI, , , , ). , jest-image-snapshot
, , , , CI, CI , .
: , , , , .
â . 800600, 1,5-2 . ? , 300 . , , . 300 â .
jest-image-snapshot
. â . , 300 ( : « ») 10-20 , . 4,5 . , , . , Jest, 12-15 .
? , jest-image-snapshot
, blink-diff , , PNG.
, , 800600. â 480 . â . â 4 (RGB ). 2 . , , 4 . 300 â 300 4 , .
, Garbage Collector , . , . : .

. , blink-diff , , 1,5-2 (800x600). â pixelmatch . . , jest-image-snapshot
( , ). looks-same Gemini, , pixelmatch .
? : ( ) . . PNG , (, 800x600 , 2 , ). , .
? , !

node.js â crypto
, . , md5
sha1
, . , hex
, .
. 4 58 . , . 137 2 . , , .
. â overkill. , . ? , , ( ) . , . :

Buffer equals()
( compare()
, â1, 1 0, ). , , , equals()
. : 4 â 3 , 137 â 148 . 50-70 , .
, , . . , . , ? , , .

, : , PNG, , . GZIP, , , , .
, ( actualImage
expectedImage
), fast-png . Uint32Array . , , . , , . , , . actual.data
, , , Uint32Array, . , , , . : , , , , .
, , (: count / (width * height)
).
, . 800600 ~100 , , , .
diff-
: ? ?
, . , , . diff- .

, . , alloc()
, ( ). Uint32Array. . , , . . â , . , . â . , .
?

, â , , , â , â 255. . , . . gray
( ) . .
: , . , , , .

( actual
, expected
diff
) Buffer.concat()
, . fast-png, PNG. , , , .

, ( ), â diff: , . ? .
? , , 250 ( , diff-). . , .
. JS, / PNG, / GZIP . , . WebAssembly , . , , , .
: diff-, . diff ! , Git. , . , GitHub , . BitBucket (Stash), :
, . diff? , () . .
Jest, , expand
. , , . Jest , . â --expand
, . : expand
, , , diff-.
?
? , . . ããã¯ã©ãããæå³ã§ããïŒ , , . , , . , , , , ? , , .
, HTML , . :
. , , . , . -, .
, , , ( ), ( CI, ). , . , , . , , .
: ? â . ã©ãããŠïŒ , PNG , , . GIF , PNG «»?
, PNG. , PNG . , GIF. GIF , PNG 4 : , , .
() PNG, . , . . ãªã«ïŒ , , , . â , .
, . â . , . (, ). , ( ), , â . ( ), . , .
( ), , . 45-50 , - , 12-15 . 300 (800x600). .
: , - -, 300 . , ( â ). .
GIT
, , â Git. Git, , .
, Git, VCS, . , ( ). , Git , . Git.
Git â GIT LFS . , Git. ä»çµã¿ã¯æ¬¡ã®ãšããã§ãã

Git , : GIT LFS, . . pull , . push, , Git . git push/pull .
CI, beyond the frontend
: 12-15 , , CI . . CI , : 14 , 4 . : 700+ , 300+ . , â 3,5 . . , - , , devops-, , , ? , TeamCity , .
CI : , git, git checkout, , -, eslint-, stylelint- . . « », , , 3,5 . , , , , . , 30 .
çµæ
- 12-15 . 300 (800600). CI â 20-30 . : , , . 3,5 , , . 20-30 .
Jest. , : , , expand, , (, ). : , , Jest. , , jest-image-snapshot
, , .
â « », , . , , , Open Source.
ãŸãšã
Babel, CSS Modules, Jest. , , , , . , , - , .

: 11 , . . 328 : .
: , , . , : , . , - â .
? , Jest , GIF, PNG, . Buffer API, TeamCity, - .
: - . . , .
ããã ãã§ã ãããããé¡ãããŸãïŒ