亀éãå¢ããå¿
èŠã¯ãããŸããã
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
ãããžã§ã¯ãã®ã«ãŒããã£ã¬ã¯ããªã§ã
ããŒãžãã£ã¬ã¯ããªãäœæã
ãŸã ã ãã®ãã£ã¬ã¯ããªã«ã¯ãããŒãžã¿ã€ãã®ã³ã³ããŒãã³ããå«ãŸããŸãã
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æ¥