亀éãå¢ããå¿ èŠã¯ãããŸããã
SEOã¯å¿ èŠãããŸãããã
ãããã¯ãŒã¯å ã®ãªã³ã¯äº€æã¯ãããŸããã
ã¹ãããŒïŒ æŸã£ãŠãããŠãã ããã
ã¢ã³ãã»ãã£ãªãŒã
ã¡ãã£ãšããæŽå²
2013幎ã«ãAirbnbã®Spike Brehmã¯ãSPAã¢ããªã±ãŒã·ã§ã³ïŒSingle Page ApplicationïŒã®æ¬ ç¹ãåæããããã°ã©ã èšäºãå ¬ââéãã代æ¿ãšããŠååWebã¢ããªã±ãŒã·ã§ã³ã®ã¢ãã«ãææ¡ããŸããã çŸåšã§ã¯ããŠãããŒãµã«Webã¢ããªã±ãŒã·ã§ã³ãšããçšèªãããé »ç¹ã«äœ¿çšãããŠããŸãïŒ èª¬æãåç §ïŒã
ãŠãããŒãµã«Webã¢ããªã±ãŒã·ã§ã³ã§ã¯ãåããŒãžã¯WebãµãŒããŒãŸãã¯Webãã©ãŠã¶ãŒåŽã®JavaScriptã«ãã£ãŠåœ¢æã§ããŸãã åæã«ãWebãµãŒããŒãšWebãã©ãŠã¶ãŒã«ãã£ãŠå®è¡ãããããã°ã©ã ã®ãœãŒã¹ã³ãŒãã¯ãäžæŽåãšéçºã³ã¹ãã®å¢å ãæé€ããããã«çµ±äžïŒãŠãããŒãµã«ïŒããå¿ èŠããããŸãã
ãã®ã¢ã€ãã¢ã®èè ã§ããAirbnbã®Spike Brehmãšã®ç©èªã¯ä»ãå®å šãªåå©ã§çµãããæè¿ã2017幎12æ7æ¥ã«åœŒã®Twitter㧠ãAirbnb Webãµã€ãããµãŒããŒããŒã¹ã®SPAã¢ããªã±ãŒã·ã§ã³ã®ã¬ã³ããªã³ã°ã«åãæ¿ãã£ãããšãçºè¡šããŸããã
SPAã¢ããªã±ãŒã·ã§ã³ã®æ¹å€
SPAã¢ããªã±ãŒã·ã§ã³ã®äœãåé¡ã«ãªã£ãŠããŸããïŒ ãããŠããŠãããŒãµã«ã¢ããªã±ãŒã·ã§ã³ãéçºãããšãã«ã©ã®ãããªåé¡ãçºçããŸããïŒ
SPAã¢ããªã±ãŒã·ã§ã³ã¯ããŸãäœãæ€çŽ¢ãšã³ãžã³ã©ã³ãã³ã°ïŒSEOïŒãäœæ¥é床ãããã³ã¢ã¯ã»ã·ããªãã£ã®ããã«æ¹å€ãããŠããŸãã ïŒããã¯ãããã¥ã¡ã³ãhttps://www.w3.org/Translations/WCAG20.ruã§ç解ãããŠããã¢ã¯ã»ã·ããªãã£ãæããŸã ãã¹ã¯ãªãŒã³ãªãŒããŒã§Reactã¢ããªã±ãŒã·ã§ã³ãå©çšã§ããªãå¯èœæ§ããããšãã蚌æ ããããŸããïŒ
éšåçã«ãSEO SPAã¢ããªã±ãŒã·ã§ã³ã®åé¡ã¯ãPrerender-chrome-remote-interfaceïŒä»¥åã¯phantomjsã§äœ¿çšãããŠããïŒã䜿çšããŠå®è£ ãããããããã¬ã¹ãWebãã©ãŠã¶ãŒãåãããµãŒããŒã«ãã£ãŠè§£æ±ºãããŸãã Prerenderã䜿çšããŠç¬èªã®ãµãŒããŒããããã€ãããã ãããªãã¯ãµãŒãã¹ã«ã¢ã¯ã»ã¹ã§ããŸãã åŸè ã®å Žåãã¢ã¯ã»ã¹ã¯ããŒãžæ°ã®å¶éä»ãã§ç¡æã«ãªããŸãã PrerenderããŒã«ã䜿çšããŠããŒãžãçæããããã»ã¹ã¯æéãããããŸããéåžžã¯3ç§ä»¥äžã§ããã€ãŸããæ€çŽ¢ãšã³ãžã³ã¯é床ãæé©åãããŠããªããµãŒãã¹ãèæ ®ãããã®è©äŸ¡ã¯äŸç¶ãšããŠäœããªããŸãã
éçºããã»ã¹äžã«ããã©ãŒãã³ã¹ã®åé¡ãçºçãããäœéã€ã³ã¿ãŒããããŸãã¯äœé»åã¢ãã€ã«ããã€ã¹ïŒããšãã°ã1GBã®RAMãš1.2GHzã®ããã»ããµåšæ³¢æ°ãåããæºåž¯é»è©±ãŸãã¯ã¿ãã¬ããïŒã§äœæ¥ããŠãããšãã«é¡èã«ãªãå ŽåããããŸãã ãã®å Žåããé£ã¶ãããŒãžãäºæããé·ãããŒããããå¯èœæ§ããããŸãã ããšãã°ã1åã ãã®ãããªé ãããŠã³ããŒãã«ã¯ãé垞瀺ãããŠãããããå€ãã®çç±ããããŸãã ãŸããã¢ããªã±ãŒã·ã§ã³ãJavaScriptãããŒãããæ¹æ³ãèŠãŠã¿ãŸãããã å€ãã®ã¹ã¯ãªãããããå ŽåïŒrequire.jsããã³amdã¢ãžã¥ãŒã«ã䜿çšããå Žåã«äžè¬çã§ããïŒãèŠæ±ããããã¡ã€ã«ããšã«ãµãŒããŒã«æ¥ç¶ããããã®ãªãŒããŒãããã«ãããããŒãæéãå¢å ããŸããã 解決çã¯æããã§ããïŒãã¹ãŠã®ã¢ãžã¥ãŒã«ã1ã€ã®ãã¡ã€ã«ã«çµåããŸãïŒrjsãwebpackãŸãã¯å¥ã®ãªã³ã«ãŒã䜿çšïŒã ããã«ãããæ°ããåé¡ãçºçããŸããããªãããªã€ã³ã¿ãŒãã§ã€ã¹ãšããžãã¯ãåããWebã¢ããªã±ãŒã·ã§ã³ã®å Žåãæåã®ããŒãžãèªã¿èŸŒããšãã«ã1ã€ã®ãã¡ã€ã«ã«èªã¿èŸŒãŸãããã¹ãŠã®JavaScriptã³ãŒããèªã¿èŸŒãŸããŸããã ãããã£ãŠãçŸåšã®åŸåã¯ã³ãŒãåââå²ã§ãã ãŠãããŒãµã«Webã¢ããªã±ãŒã·ã§ã³ã®æ§ç¯ã«å¿ èŠãªæ©èœãæ€èšããéã«ããã®åé¡ã«æ»ããŸãã åé¡ã¯ããããäžå¯èœãŸãã¯å°é£ã§ããããšã§ã¯ãããŸããã åé¡ã¯ããããæé©ã«è¡ãããŒã«ãéçºè åŽã«è¿œå ã®åŽåãªãã§æäŸããããšãæãŸãããšããããšã§ãã ãããŠæåŸã«ããã¹ãŠã®JavaScriptã³ãŒããããŠã³ããŒãããã解éããããšãDOMããã¥ã¡ã³ãã®æ§ç¯ãå§ãŸããæåŸã«ãç»åã®èªã¿èŸŒã¿ãå§ãŸããŸãã
ãŠãããŒãµã«ã¢ããªã±ãŒã·ã§ã³ãäœæããããã®ã©ã€ãã©ãª
github.comã§ã¯ããŠãããŒãµã«Webã¢ããªã±ãŒã·ã§ã³ã®ã¢ã€ãã¢ãå®è£ ããå€æ°ã®ãããžã§ã¯ããèŠã€ããããšãã§ããŸãã ãã ãããããã®ãããžã§ã¯ãã«ã¯ãã¹ãŠå ±éã®æ¬ ç¹ããããŸãã
- ãããžã§ã¯ãè²¢ç®è ã®æ°ãå°ãªã
- ãããã¯ã©ã€ãã©ãªã§ã¯ãªããã¯ã€ãã¯ã¹ã¿ãŒãçšã®ãã©ãããããžã§ã¯ãã§ãã
- react.jsã®æ°ããããŒãžã§ã³ã§ã¯ãããžã§ã¯ãã¯æŽæ°ãããŸããã§ãã
- ãŠãããŒãµã«ã¢ããªã±ãŒã·ã§ã³ã®éçºã«å¿ èŠãªæ©èœã®äžéšã®ã¿ããããžã§ã¯ãã«å®è£ ãããŠããŸãã
æåã®æåãããœãªã¥ãŒã·ã§ã³ã¯Next.jsã©ã€ãã©ãªã§ããã2018幎1æ14æ¥çŸåšãgithub.comã«ã¯338人ã®æçš¿è ãš21,137人ã®ãã¹ã¿ãŒããããŸãã ãã®ã©ã€ãã©ãªã®å©ç¹ãè©äŸ¡ããããã«ããŠãããŒãµã«Webã¢ããªã±ãŒã·ã§ã³ãæ©èœããããã«å¿ èŠãªæ©èœã®çš®é¡ãæ€èšããŸãã
ãµãŒããŒã¬ã³ããªã³ã°
react.jsãvue.jsãangular.jsãriot.jsãªã©ã®ã©ã€ãã©ãªã¯ãã¹ãŠããµãŒããŒåŽã¬ã³ããªã³ã°ããµããŒãããŠããŸãã éåžžããµãŒããŒã¬ã³ããªã³ã°ã¯åæçã«åäœããŸãã ããã¯ãã©ã€ããµã€ã¯ã«ã€ãã³ãã®éåæAPIèŠæ±ãèµ·åãããŸããããã®çµæã¯å€±ãããããšãæå³ããŸãã ïŒéåæãµãŒããŒã¬ã³ããªã³ã°ã®å¶éä»ããµããŒãã¯riot.jsã«ãã£ãŠæäŸãããŸãïŒ
éåæããŒã¿ã®èªã¿èŸŒã¿
ãµãŒããŒã¬ã³ããªã³ã°ã®éå§åã«éåæãªã¯ãšã¹ãã®çµæãååŸããããã«ãNext.jsã¯éåæéçéåægetInitialPropsïŒ{req}ïŒã©ã€ããµã€ã¯ã«ã€ãã³ããæã€ç¹å¥ãªã¿ã€ãã®ã³ã³ããŒãã³ããããŒãžããå®è£ ããŸãã
ãµãŒããŒã³ã³ããŒãã³ãã®ç¶æ ãã¯ã©ã€ã¢ã³ãã«æž¡ã
ã³ã³ããŒãã³ãã®ãµãŒããŒåŽã¬ã³ããªã³ã°ã®çµæãšããŠãHTMLããã¥ã¡ã³ããã¯ã©ã€ã¢ã³ãã«éä¿¡ãããŸãããã³ã³ããŒãã³ãã®ç¶æ ã¯å€±ãããŸãã ã³ã³ããŒãã³ãã®ç¶æ ã転éããããã«ãéåžžãWebãµãŒããŒã¯Webãã©ãŠã¶ãŒçšã®ã¹ã¯ãªãããçæãããµãŒããŒã³ã³ããŒãã³ãã®ç¶æ ãã°ããŒãã«JavaScriptå€æ°ã«æžã蟌ã¿ãŸãã
Webãã©ãŠã¶ãŒåŽã®ã³ã³ããŒãã³ãã®äœæãšHTMLããã¥ã¡ã³ããžã®ãã®ãã€ã³ãã£ã³ã°
ã³ã³ããŒãã³ãã®ãµãŒããŒåŽã¬ã³ããªã³ã°ããçæãããHTMLããã¥ã¡ã³ãã«ã¯ããã¹ããå«ãŸããã³ã³ããŒãã³ãïŒJavaScriptãªããžã§ã¯ãïŒã¯å«ãŸããŸããã ã³ã³ããŒãã³ãã¯Webãã©ãŠã¶ã§åäœæããåã¬ã³ããªã³ã°ããã«ããã¥ã¡ã³ãã«ãçµã³ä»ãããå¿ èŠããããŸãã react.jsã§ã¯ããã®ããã«hydrateïŒïŒã¡ãœãããå®è¡ãããŸãã åæ§ã®é¢æ°ã¡ãœããã¯vue.jsã©ã€ãã©ãªã«ãããŸã
ã«ãŒãã£ã³ã°
ãµãŒããŒãšã¯ã©ã€ã¢ã³ãã§ã®ã«ãŒãã£ã³ã°ããŠãããŒãµã«ã«ããå¿ èŠããããŸãã ã€ãŸããã«ãŒãã£ã³ã°ã®åãå®çŸ©ããµãŒããŒãšã¯ã©ã€ã¢ã³ãã®äž¡æ¹ã®ã³ãŒãã§æ©èœããã¯ãã§ãã
ã³ãŒãåââå²
åããŒãžã«ã¯ãã¢ããªã±ãŒã·ã§ã³å šäœã§ã¯ãªããå¿ èŠãªJavaScriptã³ãŒãã®ã¿ãããŒãããå¿ èŠããããŸãã 次ã®ããŒãžã«ç§»åãããšããæ¬ èœããŠããã³ãŒããããŒãããå¿ èŠããããŸã-åãã¢ãžã¥ãŒã«ããªããŒãããã«ãè¿œå ã®ã¢ãžã¥ãŒã«ããããŸããã
Next.jsã©ã€ãã©ãªã¯ãããããã¹ãŠã®åé¡ãæ£åžžã«è§£æ±ºããŸãã ãã®ã©ã€ãã©ãªã¯ãéåžžã«åçŽãªã¢ã€ãã¢ã«åºã¥ããŠããŸãã æ°ããã¿ã€ãã®ã³ã³ããŒãã³ããããŒãžããå°å ¥ããããšãææ¡ããŸãããããŒãžãã«ã¯ãéåæã¡ãœããstatic async getInitialPropsïŒ{req}ïŒããããŸãã ããŒãžã³ã³ããŒãã³ãã¯ãéåžžã®Reactã³ã³ããŒãã³ãã§ãã ãã®ã¿ã€ãã®ã³ã³ããŒãã³ãã¯ããã³ã³ããŒãã³ããããã³ã³ãããããããŒãžããšããã·ãªãŒãºã®æ°ããã¿ã€ããšèããããšãã§ããŸãã
å®æœäŸ
äœæ¥ã«ã¯ãnode.jsãšnpmããã±ãŒãžãããŒãžã£ãŒãå¿ èŠã§ãã ãŸã ã€ã³ã¹ããŒã«ãããŠããªãå Žåããããè¡ãæãç°¡åãªæ¹æ³ã¯ãã³ãã³ãã©ã€ã³ããã€ã³ã¹ããŒã«ãããsudoã¢ã¯ã»ã¹ãå¿ èŠãšããªãnvmïŒNode Version ManagerïŒã䜿çšããããšã§ãã
curl -o- https://raw.githubusercontent.com/creationix/nvm/v0.33.8/install.sh | bash
ã€ã³ã¹ããŒã«åŸãå¿ ãã¿ãŒããã«ãéããŠå床éããPATHç°å¢å€æ°ãèšå®ããŠãã ããã 次ã®ã³ãã³ãã«ããã䜿çšå¯èœãªãã¹ãŠã®ããŒãžã§ã³ã®ãªã¹ãã衚瀺ãããŸãã
nvm ls-remote
次ã®ã³ãã³ãã§ãnode.jsã®å¿ èŠãªããŒãžã§ã³ãšnpmããã±ãŒãžãããŒãžã£ãŒã®äºæããŒãžã§ã³ãããŠã³ããŒãããŸãã
nvm install 8.9.4
æ°ãããã£ã¬ã¯ããªïŒãã©ã«ãïŒãäœæãããã®äžã§ã³ãã³ããå®è¡ããŸãïŒ
npm init
ãã®çµæã package.jsonãã¡ã€ã«ãçæãããŸãã
ãããžã§ã¯ãã«å¿ããŠãäœæ¥ã«å¿ èŠãªããã±ãŒãžãããŠã³ããŒãããŠè¿œå ããŸãã
npm install --save axios next next-redux-wrapper react react-dom react-redux redux redux-logger
ãããžã§ã¯ãã®ã«ãŒããã£ã¬ã¯ããªã§ã ããŒãžãã£ã¬ã¯ããªãäœæããŸã ã ãã®ãã£ã¬ã¯ããªã«ã¯ãããŒãžã¿ã€ãã®ã³ã³ããŒãã³ããå«ãŸããŸãã pagesãã£ã¬ã¯ããªå ã®ãã¡ã€ã«ãžã®ãã¹ã¯ããããã®ã³ã³ããŒãã³ããå©çšã§ããURLã«å¯Ÿå¿ããŠããŸãã ãã€ãã®ããã«ããããžãã¯ããŒã ãã®index.jsã¯url / indexããã³/ã«ãããã³ã°ãããŸãã ã¯ã€ã«ãã«ãŒãã䜿çšããURLã®ããè€éãªã«ãŒã«ãå®è£ å¯èœã§ãã
pages / index.jsãã¡ã€ã«ãäœæããŸã ïŒ
import React from 'react' export default class extends React.Component { static async getInitialProps({ req }) { const userAgent = req ? req.headers['user-agent'] : navigator.userAgent return { userAgent } } render() { return ( <div> Hello World {this.props.userAgent} </div> ) } }
ãã®åçŽãªã³ã³ããŒãã³ãã¯ãNext.jsã®äž»ãªæ©èœã䜿çšããŸãã
- es7æ§æïŒã€ã³ããŒãããšã¯ã¹ããŒããéåæãã¯ã©ã¹ïŒã¯ãã®ãŸãŸäœ¿çšã§ããŸãã
- ããããªããŒãããã®ãŸãŸäœ¿çšã§ããŸãã
- éçãªéåægetInitialPropsïŒ{req}ïŒé¢æ°ã¯ããµãŒããŒãŸãã¯ã¯ã©ã€ã¢ã³ãã§ã³ã³ããŒãã³ããã¬ã³ããªã³ã°ããåã«éåæã§å®è¡ãããŸãïŒäžåºŠã ãïŒã ã³ã³ããŒãã³ãããµãŒããŒã§ã¬ã³ããªã³ã°ãããå Žåã reqãã©ã¡ãŒã¿ãŒãããã«æž¡ãããŸãã ãã®é¢æ°ã¯ããŒãžã¿ã€ãã®ã³ã³ããŒãã³ãã§ã®ã¿åŒã³åºããããã¹ããããã³ã³ããŒãã³ãã§ã¯åŒã³åºãããŸããã
package.jsonãã¡ã€ã«ã§ããscriptsãå±æ§ã«3ã€ã®ã³ãã³ããè¿œå ããŸãã
"scripts": { "dev": "next", "build": "next build", "start": "next start" }
次ã®ã³ãã³ãã§éçºè ãµãŒããŒãèµ·åããŸãã
npm run dev
ãµãŒããŒããããŒãžãããŒãããã«å¥ã®ããŒãžãžã®ç§»è¡ãå®è£ ããããã«ããªã³ã¯ã¯ç¹å¥ãªLinkã³ã³ããŒãã³ãã§ã©ãããããŸãã page / index.jsã«äŸåé¢ä¿ãè¿œå ããŸã ã
import Link from 'next/link'
ããã³ãªã³ã¯ã³ã³ããŒãã³ãïŒ
<Link href="/time"> <a>Click me</a> </Link>
ãªã³ã¯ãã¯ãªãã¯ãããšã404ãšã©ãŒã®ããããŒãžã衚瀺ãããŸãã
pages / index.jsãã¡ã€ã«ãpages / time.jsãã¡ã€ã«ã«ã³ããŒããŸã ã æ°ããtime.jsã³ã³ããŒãã³ãã§ã¯ããµãŒããŒããéåæã«åä¿¡ããçŸåšã®æå»ã衚瀺ããŸãã ãããŸã§ã®éããã®ã³ã³ããŒãã³ãã®ãªã³ã¯ãå€æŽããŠãã¡ã€ã³ããŒãžã«ç§»åããŸãã
<Link href="/"> <a>Back</a> </Link>
ãµãŒããŒããåããŒãžããªããŒãããŠãããŒãžéã移åããŠæ»ã£ãŠãã ããã ãããã®å ŽåãããµãŒããŒããã®ããŠã³ããŒãã¯ããµãŒããŒã¬ã³ããªã³ã°ãšããã®åŸã®ãã¹ãŠã®é·ç§»ã§è¡ãããŸã-Webãã©ãŠã¶ãŒã®æšªã«ããã¬ã³ããªã³ã°ããŒã«ã䜿çšããŸãã
pages / time.jsããŒãžã«ããµãŒããŒããåä¿¡ããçŸåšã®æå»ã瀺ãã¿ã€ããŒãé 眮ããŸãã ããã«ããããµãŒããŒã¬ã³ããªã³ã°äžã®éåæããŒã¿ã®èªã¿èŸŒã¿ã«æ £ããããšãã§ããŸããããã¯ãNext.jsãä»ã®ã©ã€ãã©ãªãšæ¯èŒããŠå¥œæçãªãã®ã§ãã
reduxã䜿çšããŠãããŒã¿ãã¹ãã¢ã«æ ŒçŽããŸãã reduxã®éåæã¢ã¯ã·ã§ã³ã¯ãããã«ãŠã§ã¢redux-thunkã䜿çšããŠå®è¡ãããŸãã éåžžïŒåžžã«ã§ã¯ãããŸããïŒã1ã€ã®éåæã¢ã¯ã·ã§ã³ã«ã¯ãSTARTãSUCCESS FAILUREã® 3ã€ã®ç¶æ ããããŸãã ãããã£ãŠãéåæã¢ã¯ã·ã§ã³ã決å®ããããã®ã³ãŒãã¯ïŒå°ãªããšãç§ã«ãšã£ãŠã¯ïŒè€éã«èŠããããšããããããŸãã redux-thunkã©ã€ãã©ãªãŒã®1ã€ã®åé¡ã§ã¯ãããã«ãŠã§ã¢ã®åçŽåãããããŒãžã§ã³ã«ã€ããŠèª¬æããŸãããããã«ããã3ã€ã®ç¶æ ãã¹ãŠã1è¡ã§å®çŸ©ã§ããŸãã æ®å¿µãªããããã®ãªãã·ã§ã³ã¯ã©ã€ãã©ãªã«çºè¡ãããããšããªããããã¢ãžã¥ãŒã«ãšããŠãããžã§ã¯ãã«å«ããŸãã
ã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒããã£ã¬ã¯ããªã«æ°ããreduxãã£ã¬ã¯ããªãäœæããŸãããã®äžã«redux / promisedMiddlewate.jsãã¡ã€ã«ããããŸãã
export default (...args) => ({ dispatch, getState }) => (next) => (action) => { const { promise, promised, types, ...rest } = action; if (!promised) { return next(action); } if (typeof promise !== 'undefined') { throw new Error('In promised middleware you mast not use "action"."promise"'); } if (typeof promised !== 'function') { throw new Error('In promised middleware type of "action"."promised" must be "function"'); } const [REQUEST, SUCCESS, FAILURE] = types; next({ ...rest, type: REQUEST }); action.promise = promised() .then( data => next({ ...rest, data, type: SUCCESS }), ).catch( error => next({ ...rest, error, type: FAILURE }) ); };
ãã®æ©èœã®åäœã«é¢ããããã€ãã®èª¬æã redux midlewareé¢æ°ã«ã¯ã眲åïŒstoreïŒ=>ïŒnextïŒ=>ïŒactionïŒããããŸãã ã¢ã¯ã·ã§ã³ãéåæã§ããããã®ç¹å®ã®é¢æ°ã«ãã£ãŠåŠçãããå¿ èŠãããããšã瀺ãã€ã³ãžã±ãŒã¿ãŒã¯ã çŽæãããããããã£ã§ãã ãã®ããããã£ãŒãå®çŸ©ãããŠããªãå ŽåãåŠçã¯å®äºããå¶åŸ¡ã¯æ¬¡ã®ããã«ãŠã§ã¢ã«è»¢éãããŸãïŒ return nextïŒactionïŒ ã Promiseãªããžã§ã¯ããžã®åç §ã¯action.promiseããããã£ã«ä¿åãããŸããããã«ãããéåæã¢ã¯ã·ã§ã³ãå®äºãããŸã§éçéåægetInitialPropsïŒ{reqãstore}ïŒéåæé¢æ°ããä¿æãã§ããŸãã
ããŒã¿ãŠã§ã¢ããŠã¹ã«æ¥ç¶ãããŠãããã®ã¯ãã¹ãŠredux / store.jsãã¡ã€ã«ã«é 眮ãããŸã ã
import { createStore, applyMiddleware } from 'redux'; import logger from 'redux-logger'; import axios from 'axios'; import promisedMiddleware from './promisedMiddleware'; const promised = promisedMiddleware(axios); export const initStore = (initialState = {}) => { const store = createStore(reducer, {...initialState}, applyMiddleware(promised, logger)); store.dispatchPromised = function(action) { this.dispatch(action); return action.promise; } return store; } export function getTime(){ return { promised: () => axios.get('http://time.jsontest.com/'), types: ['START', 'SUCCESS', 'FAILURE'], }; } export const reducer = (state = {}, action) => { switch (action.type) { case 'START': return state case 'SUCCESS': return {...state, ...action.data.data} case 'FAILURE': return Object.assign({}, state, {error: true} ) default: return state } }
getTimeïŒïŒã¢ã¯ã·ã§ã³ã¯promisedMiddlewareïŒïŒã«ãã£ãŠåŠçãããŸãã ãããè¡ãããã«ã promiseããããã£ãŒã«ã¯Promiseãè¿ãé¢æ°ãããã typesããããã£ãŒã«ã¯ãå®æ°'START'ã 'SUCCESS'ã 'FAILURE'ãå«ã3ã€ã®èŠçŽ ã®é åããããŸãã å®æ°ã®å€ã¯ä»»æã§ããããªã¹ãå ã§ã®é åºã¯éèŠã§ãã
ããã§ããããã®ã¢ã¯ã·ã§ã³ãpages / time.jsã³ã³ããŒãã³ãã«é©çšããããšãã§ããŸã ã
import React from 'react'; import {bindActionCreators} from 'redux'; import Link from 'next/link'; import { initStore, getTime } from '../redux/store'; import withRedux from 'next-redux-wrapper'; function mapStateToProps(state) { return state; } function mapDispatchToProps(dispatch) { return { getTime: bindActionCreators(getTime, dispatch), }; } class Page extends React.Component { static async getInitialProps({ req, store }) { await store.dispatchPromised(getTime()); return; } componentDidMount() { this.intervalHandle = setInterval(() => this.props.getTime(), 3000); } componentWillUnmount() { clearInterval(this.intervalHandle); } render() { return ( <div> <div>{this.props.time}</div> <div> <Link href="/"> <a>Return</a> </Link> </div> </div> ) } } export default withRedux(initStore, mapStateToProps, mapDispatchToProps)(Page);
ããã§ã¯ã next-redux-wrapperã©ã€ãã©ãªã®withReduxïŒïŒã¡ãœããã䜿çšããŠããããšã«æ³šç®ããŠãã ããã ä»ã®ãã¹ãŠã®ã©ã€ãã©ãªã¯ãreact.jsã«å ±éã§ãããNext.jsã«é©å¿ããå¿ èŠã¯ãããŸããã
Next.jsã©ã€ãã©ãªã«åããŠäŒã£ããšãã¯ãããªãåå§çãªããã«äœ¿çšã§ããã«ãŒãã£ã³ã°ã®ããã«ãç§ã¯æ¬åœã«æéãåããŸããã§ããã ãã®ã©ã€ãã©ãªã®é©çšå¯èœæ§ã¯ãååºãµã€ãã»ã©é«ããªãããã«æããŸããã ä»ã¯ããã¯æããªãã®ã§ãåãèšäºã§next-routesã©ã€ãã©ãªã«ã€ããŠè©±ãããšãèšç»ããŸãããããã«ãããã«ãŒãã£ã³ã°ã®å¯èœæ§ãå€§å¹ ã«åºãããŸãã ãããä»ãç§ã¯ãã®è³æãå¥ã®æçš¿ã«çœ®ãæ¹ãè¯ãããšãç解ããŠããŸãã ãŸãã react-i18nextã©ã€ãã©ãªã«ã€ããŠã話ãåãäºå®ã§ãã -Next.jsãšçŽæ¥çãªé¢ä¿ã¯ãããŸããããå ±å䜿çšã«ã¯éåžžã«é©ããŠããŸãã
apapacy@gmail.com
2018幎1æ14æ¥