æè¿ã§ã¯ãVue.jsããµãŒããŒã¬ã³ããªã³ã°ã®æ¬æ ŒçãªãµããŒããååŸããŸããã ã€ã³ã¿ãŒãããã«ã¯é©åã«èª¿çããæ¹æ³ã«é¢ããæ å ±ãããªããããããVue.jsã§SSRã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãéçºããããã«å¿ èŠãªç°å¢ãäœæããããã»ã¹ã詳现ã«èª¬æããããšã«ããŸããã
è°è«ããããã¹ãŠã®ãã®ã¯githubã®ãªããžããªã«å®è£ ãããŸã ã ç§ã¯é »ç¹ã«ãã®ãœãŒã¹ãåç §ããå®éã«äœãèµ·ãã£ãŠããã®ãããªããããå¿ èŠãªã®ãã説æããããšããŸã:)
ãã®èšäºã§ã¯ãSSRã®ããªãäžè¬çãªã¢ãããŒãã«ã€ããŠèª¬æããŸã ïŒ äœ¿çšããæºåãå¿ èŠãªå Žåã¯ã Nuxt.jsãåç §ã§ããŸã ïŒããããã£ãŠãäžèšã®äžéšãŸãã¯ãã¹ãŠãä»ã®ãã¬ãŒã ã¯ãŒã¯ã«é©çšã§ããå¯èœæ§ããããŸã/ AngularãReactãªã©ã®ã©ã€ãã©ãªã
ç§ã¯å ¬åŒææžãç¡æã§æ¹åãããšããç®æšãèšå®ããŠããŸããã§ããã®ã§ãããã»ã¹ãå®å šã«ç解ããããã«ã¯ãå°ãªããšããããèŠãããšããå§ãããŸãã
ã¯ããã«
SSRã䜿çšããã¢ããªã±ãŒã·ã§ã³ã®äž»ãªã¢ã€ãã¢ã¯ããµãŒããŒãšã¯ã©ã€ã¢ã³ãã§å®è¡ããããšãã«åãHTMLããŒã¯ã¢ãããçæããããšã§ãã
HTMLã§çœ®æãããããŒã¿ã¯ãåããŸãã¯å¥ã®ãµãŒããŒ/ãã¡ã€ã³ã«ããAPIã«ãã£ãŠãã«ãããå¿ èŠããããŸãã APIãµãŒããŒã®ã»ããã¢ãããšéçºã¯ãã®èšäºã®ç¯å²å€ã§ããã axiosãŸãã¯ä»ã®å圢ã®httpã¯ã©ã€ã¢ã³ããã¯ã©ã€ã¢ã³ããšããŠäœ¿çšã§ããŸãã
ãŸãããµãŒããŒã«DOMããªãããšãèŠããŠããå¿ èŠããããŸãããã®ãããããã¥ã¡ã³ãããŠã£ã³ããŠããã®ä»ã®ããã²ãŒã¿ãŒã§ã®ãã¹ãŠã®æäœã¯ããŸã£ãã䜿çšããªãããã¯ã©ã€ã¢ã³ããã€ãŸãbeforeMountãmountedãªã©ã®ããã¯ã§ã®ã¿å®è¡ããå¿ èŠããããŸãã
以äžã«ãã³ãŒãã§äœãèµ·ãã£ãŠããã®ããæ確ã«ããããšããå€ãã®æçŽããããŸãã ãããã£ãŠãæåãèªã¿ã«ãããšæãããå Žåã¯ãããã«ã³ãŒãã調ã¹ãããšããå§ãããŸã:)ãªããžããªã®å¯Ÿå¿ããéšåãžã®ãªã³ã¯ã¯ãåã»ã¯ã·ã§ã³ã§æäŸãããŸãã
Webpackã®æ§æ
ãã«ãã¯ã3ã€ã®äž»èŠãªWebããã¯æ§æ-äžè¬ããµãŒããŒçšã®ãã«ããã¯ã©ã€ã¢ã³ãçšã®ãã«ãã«åãããŠããŸãã ã¢ã»ã³ããªåŸãã¯ã©ã€ã¢ã³ãçšã®ãã¡ã€ã«ã»ãããšãµãŒããŒçšã®jsãã¡ã€ã«ã1ã€ã ãã®2ã€ã®ç¬ç«ãããã³ãã«ãåãåãå¿ èŠããããŸãã
ãã³ãã«ããšã«ãæããã«ãåå¥ã®ãšã³ããªãäœæããå¿ èŠããããŸãããããã«ã€ããŠã¯åŸã§è©³ãã説æããŸãã
äžè¬ã¢ã»ã³ããªïŒbase.jsïŒã«ã¯ããã¹ãŠã®éçããã³ãã¬ãŒããJavaScriptãœãŒã¹ãããã³vueã³ã³ããŒãã³ãã®ããŒããŒãå«ãŸããŠããŸãã çè«çã«ã¯ã¹ã¿ã€ã«ãããã«å«ããããšãã§ããŸãããæãããªçç±ã«ãããã¹ã¿ã€ã«ã¯ãµãŒããŒäžã§å¿ èŠãªããããã¯ã©ã€ã¢ã³ãã«å¯ŸããŠã®ã¿ç»é²ãããŸãã
ã¯ã©ã€ã¢ã³ãã¢ã»ã³ããªïŒclient.jsïŒã¯ããã©ãŠã¶ãŒã§å¿
èŠãªãã®å
šäœã«è¿œå ããŸã ã ã«ãŒã«ã¯ãcssãã¹ã¿ã€ã©ã¹ãsassãpostcssãªã©ã®ããŒãããŒããŒãæå®ããŸãã
ããã«åºåãè¿œå ããŠããã³ãã«ãè€æ°ã®ãã¡ã€ã«ã«åå²ããããCSSãæœåºããããuglifyãªã©ãå®è¡ããããšãã§ããŸãã äžè¬çã«ããã¹ãŠã¯ãã€ãã®ããã«:)
ããã§ã¯ãhtml-webpack-pluginã䜿çšããŠäžè¬çãªHTMLãã³ãã¬ãŒãã®çæãè¿œå ããŸãã ç§ã¯ãããããå°ãäœãã«èª¬æããŸãã
SSRã®ã¢ã»ã³ããªïŒserver.jsïŒã¯ããµãŒããŒã§åŠçããåäžã®jsãã¡ã€ã«ãäœæããå¿
èŠããããŸãã 誰ãhttpçµç±ã§ã¢ããããŒãããªãããããã¡ã€ã«ãµã€ãºã«ã€ããŠã¯å¿é
ããŠããŸããããããã£ãŠãéåžžãæé©åã®ããã«configsã«èšè¿°ãããŠãããã®ã¯ãã¹ãŠããã§ã¯æå³ããããŸããã
target: node
ãã¹ã¿ã€ã«ããã³å€éšçšã®nullããŒããŒãæå®ããå¿
èŠããããŸãã å€éšã¯package.jsonãããã¹ãŠã®ããã±ãŒãžãæå®ããwebpackã¯ãµãŒããŒäžã®node_modulesããæ¥ç¶ããããããã€ã³ã¹ããŒã«ãããããã±ãŒãžãã¢ã»ã³ããªã«å«ãŸããªãããã«ããŸãã
{ target: 'node', externals: Object.keys(require('../../package.json').dependencies) }
äžè¬çãªã¢ããªã±ãŒã·ã§ã³ãã³ãã¬ãŒã
äžè¬çãªãã³ãã¬ãŒãã¯ãã¬ã³ããªã³ã°ãããVueã¢ããªã±ãŒã·ã§ã³ã³ãŒããæ¿å
¥ãããäžè¬çãªHTMLããŒã¯ã¢ããã§ãã ç¹å¥ã«èšç·Žãããã©ã€ãã©ãªã®ãªããµãŒããŒã¯DOMã«ã€ããŠäœãç¥ããªãããšãç解ããããšãéèŠã§ãã ãããã£ãŠããã³ãã¬ãŒãã«ç¹å®ã®æååãå
¥åããå¿
èŠããããŸããããã¯ãéšåæååãã¢ããªã±ãŒã·ã§ã³ã®ããŒã¯ã¢ããã«çœ®ãæããã ãã®åçŽãªçœ®æã«ãªããŸãã äŸã§ã¯ãããã¯åãªã<!--APP-->
ïŒãŸãã¯//APP
ïŒã§ãããä»ã®ãã®ã§ãæ§ããŸããã
é ã®äžã®ã¹ã¯ãªãããã¹ã¿ã€ã«ãã¿ã°ã¯å°ãç°¡åã§ã-åã眮æã䜿çšããŠã </body>
/ </head>
åã«æ¿å
¥ããŸãã
ã¢ã»ã³ããªãšãµãŒããŒ
SSRãæ©èœãããã«ã¯ãNode.jsäžã®ãµãŒããŒïŒãã®äŸã§ã¯ExpressïŒãå¿ èŠã§ããããã¯ãéçºäžã«ãã®å Žã§ãããžã§ã¯ãããã«ãããŸãã ããã«ã¯å€ãã®ã³ãŒããããã®ã§ãéçºçšã® ãµãŒããŒèµ·åãã€ã³ããšãµãŒããŒæ§æã®äŸãç°¡åã«ç¢ºèªã§ããŸã ã
ããã€ãã®åŸ®åŠãªç¹ïŒ
- ã¯ã©ã€ã¢ã³ãã®vue-metaãã©ã°ã€ã³ãããŒã¯ã¢ããã®æºåãã§ããŠãããã¡ã¿ã¿ã°ãè€è£œããªãããšãç解ã§ããããã«ãäžè¬çãªãã³ãã¬ãŒããæºåããå¿
èŠããããŸãã ãããè¡ãã«ã¯ã
<html>
å€ã®ãªãç¹å¥ãªå±æ§data-vue-meta-server-rendered
ãæ¿å ¥ããã ãã§ãã å±æ§åã¯ã«ã¹ã¿ãã€ãºå¯èœã§ããããããããžã§ã¯ãã§ç°ãªãå ŽåããããŸãïŒããšãã°ãããã¯çãã®ã§data-meta-ssr
ã«çœ®ãæããããšã«ããŸããïŒã - ãŸãããã³ãã¬ãŒãã§ã¯ãvue-metaãã©ã°ã€ã³ããå¿ èŠãªãã®ãã¹ãŠã眮ãæããå¿ èŠããããŸããhtmlããã³bodyã®å±æ§ãã¡ã¿ã¿ã°ããªã³ã¯ãnoscriptãªã©ã§ããæãåçŽãªããŒãžã§ã³ã§ã¯ãããã¯æ¬¡ã®ããã«ãªããŸã ã
// ... const { title, htmlAttrs, bodyAttrs, link, style, script, noscript, meta } = context.meta.inject() res.write(` <!doctype html> <html data-vue-meta-server-rendered ${htmlAttrs.text()}> <head> ${meta.text()} ${title.text()} ${link.text()} ${style.text()} ${script.text()} ${noscript.text()} </head> <body ${bodyAttrs.text()}> ... `) // ...
- ãµãŒããŒãã³ãã«ïŒä»¥åã¯webpackã䜿çšããŠã³ã³ãã€ã«ãããŠããïŒãæ£ããåŠçããã«ã¯ãvue-server-rendererã䜿çšããå¿ èŠããããŸããvue-server-rendererã¯ããã³ãã«ãšãã®ãšã³ã³ãŒãã£ã³ã°ã§ãã¡ã€ã«ãæå®ããå¿ èŠããããŸã ãã©ã¡ãŒã¿ã®è©³çŽ°ã«ã€ããŠã¯ãå ¬åŒããã¥ã¡ã³ããã芧ãã ããã å°ãªããšã1ã€ã®èå³æ·±ããã©ã¡ãŒã¿ãŒrunInNewContextããããŸããããã«ãããã¬ã³ããªã³ã°ã®æé©ãªæé©åãå¯èœã«ãªããŸãããç¹å®ã®ã«ãŒã«ãé©çšãããŸãïŒããã«ã€ããŠã¯ããšã³ããªãŒãã€ã³ãã®ã»ã¯ã·ã§ã³ã§åŸè¿°ããŸãïŒã
- APIããã®ãã¹ãŠã®ããŒã¿ã¯ã¬ã³ããªã³ã°äžã«ããŒãããããããã¯ã©ã€ã¢ã³ãã«å床ããŠã³ããŒãããå¿
èŠã¯ãããŸããã ããããã¯ã©ã€ã¢ã³ãã¯æããã«ããŒã¯ã¢ããããããããåãåºãããšã¯ã§ããªããããããŒã¯ã¢ãããšãšãã«ããŒã¿ãæž¡ãå¿
èŠããããŸãã ãã®ã¿ã¹ã¯ã¯ã§ããã ãç°¡åã«è§£æ±ºãããŸããå¿
èŠãªãã¹ãŠã®ããŒã¿ãå€æ°ã«æžã蟌ãŸããã¹ã¯ãªãããããŒã¯ã¢ããã«è¿œå ãããŸãã ããŒã¿èªäœã¯
JSON.stringify
ã§åŠçãããããã«è¯ãããšã«serialize-javascriptã䜿çšããŠåŠçããJSON.stringify
ã
const serialize = require('serialize-javascript') // ... res.write(`<script> window.__INITIAL_VUEX_STATE__=${serialize(context.initialVuexState)} </script>`); res.write(`<script> window.__INITIAL_COMP_STATE__=${serialize(context.initialComponentStates)} </script>`);
éçºã¢ãŒã
ãµãŒããŒãéçºã¢ãŒãã§èµ·åããå ŽåããµãŒããŒèªäœã¯ã»ãŒåãæ¹æ³ã§åäœããŸãã éãã¯2ç¹ã®ã¿ã§ããã¬ã³ããªã³ã°äžã«çºçãããšã©ãŒã¯ç°ãªãæ¹æ³ã§åŠçãããŸãããŸããã¢ããªã±ãŒã·ã§ã³ã³ãŒããå€æŽãããšãäžè¬çãªãã³ãã¬ãŒãã®ã¬ã³ãã©ãŒãšããŒã¯ã¢ãããæ°ãããã®ã«çœ®ãæããããŸãã
ãµãŒããŒèªäœã«å ããŠããœãŒã¹ãå€æŽãããšãã«webpack(clientConfig).watch
ãå®è¡ããŠããã®å Žã§ã¢ã»ã³ããªãçæããå¿
èŠããããŸãã ãã®åã«ãwebpackã¯ãHotModuleReplacementPluginãªã©ãéçºã«å¿
èŠãªãã¹ãŠã®ãã©ã°ã€ã³ã§åæåãããŸãã
ãŸããæ°ãããã³ãã«ã¢ã»ã³ããªã«ã€ããŠã¯ã©ã€ã¢ã³ãã«éç¥ããå¿ èŠããããŸãã ããã«ã¯webpack-dev-middlewareãšwebpack-hot-middlewareãå¿ èŠã§ãã æ°ããã¢ã»ã³ããªã衚瀺ããããšãïŒã€ãŸããã¢ããªã±ãŒã·ã§ã³ã®ãœãŒã¹ã³ãŒããå€æŽããããã³ã«ïŒãå€æŽãããã³ãŒããã¯ã©ã€ã¢ã³ãã«é ä¿¡ããå¿ èŠããããŸãã
webpack(serverConfig).watch
ãããµãŒããŒãã³ãã«ã¯å€æŽããããšæ°ãããã®ã«çœ®ãæããããŸãã ç§ã®å ŽåãåçŽãªã³ãŒã«ããã¯ïŒ build/setup-dev-server.js
50è¡ç®ã index.js
73è¡ç®ïŒã䜿çšããŠå€æŽãããããšãå ±åãbuild/setup-dev-server.js
ã
ã¢ããªã±ãŒã·ã§ã³ã®ãšã³ããªãã€ã³ã
äžã§è¿°ã¹ãããã«ãSSRãšã¯ã©ã€ã¢ã³ãçšã®ã¢ããªã±ãŒã·ã§ã³ã®2ã€ã®åå¥ã®ãšã³ããªãã€ã³ãïŒwebpackã®ãšã³ããªïŒãäœæããå¿ èŠããããŸãã å®éãããã§ã¯ãwebpackã®èšå®ãšåæ§ã«ããµãŒããŒãã¯ã©ã€ã¢ã³ãã®å ±éã³ãŒããæã€3ã€ã®ãã¡ã€ã«ããããŸãã
å ±éã³ãŒãïŒapp.jsïŒã«ã¯ãã¢ããªã±ãŒã·ã§ã³ã®äžè¬çãªåæåãå«ãŸããŠããŸããã€ãŸããVueãã©ã°ã€ã³ãæ¥ç¶ããvuexã¹ãã¢ãã«ãŒã¿ãŒãããã³æ°ããã«ãŒãã³ã³ããŒãã³ããäœæããŸãã ãŸããã°ããŒãã«ã³ã³ããŒãã³ãããã£ã«ã¿ãŒãããã³ãã£ã¬ã¯ãã£ããç»é²ããŸãã
ããã§ã¯ãã¢ããªã±ãŒã·ã§ã³ã®ã¡ã€ã³ã³ã³ããŒãã³ããšã«ãŒãã³ã³ããŒãã³ãã1ã€ã«ãªãããã«ãã«ãŒãã³ã³ããŒãã³ããã¢ããªã±ãŒã·ã§ã³èªäœã®ãã³ãã¬ãŒããšããžãã¯ãæã€vueãã¡ã€ã«ãšæ··åããå¿
èŠããããŸãã
vue-server-rendererã«ã¯ãrunInNewContextãªãã·ã§ã³ããããããã¯ç¡å¹ã«ã§ããŸãããããã©ãŒãã³ã¹ã倧å¹
ã«åäžããããšãéèŠã§ãã ããããããã䜿çšããã«ã¯ãã¢ããªã±ãŒã·ã§ã³ãæ¯ååæåããå¿
èŠããããããapp.jsã§ã¯ãVueã³ã³ããŒãã³ãã®æ¢è£œã®ãªããžã§ã¯ãã§ã¯ãªããåæåããé¢æ°ãè¿ããŸãã ãã®ãã¡ã€ã«ã§çŽæ¥å®è¡ãããã³ãŒãã¯ããµãŒããŒã®èµ·åæã«äžåºŠã ãå®è¡ããããããèŠããŠããå¿
èŠããããŸãã ããã§ã¯ãã©ã³ã¿ã€ã ã§åä¿¡ããããŒã¿ã«äŸåããªãäžè¬çãªç¬éãç»é²ã§ããŸã-ã³ã³ããŒãã³ãããã£ã«ã¿ãŒããã£ã¬ã¯ãã£ãã®ç»é²ãç°å¢å€æ°ã®æœåºãªã©ã ãªã©
ã¯ã©ã€ã¢ã³ãïŒclient.jsïŒã®ãšã³ããªãã€ã³ã ã ããã§ã¯ãapp.jsã®é¢æ°ã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãäœæããããããèªã¿èŸŒãŸãããã©ãŠã¶ãŒã§ã®æ£ããæäœã«å¿
èŠãªãã¹ãŠãèªã¿èŸŒãŸããŸãã
ãŸãããã®ããŒãžã«è¡šç€ºãããã³ã³ããŒãã³ãã®ããŒã¿ãªããžã§ã¯ããšvuexã¹ãã¢ã®ç¶æ
ã眮ãæããŸãã
if (window.__INITIAL_VUEX_STATE__) { // state app.$store.replaceState(window.__INITIAL_VUEX_STATE__); delete window.__INITIAL_VUEX_STATE__; } if (window.__INITIAL_COMP_STATE__) { app.$router.onReady(() => { // , // ( , )... const comps = app.$router.getMatchedComponents() // ... , .filter(comp => typeof comp.prefetch === 'function'); for (let i in comps) if (window.__INITIAL_COMP_STATE__[i]) // , data // ( $data , ) comps[i].prefetchedData = window.__INITIAL_COMP_STATE__[i]; delete window.__INITIAL_COMP_STATE__; }); }
ã«ãŒãã³ã³ããŒãã³ããååŸããã¢ããªã±ãŒã·ã§ã³ã®ã«ãŒãèŠçŽ ã§$mount
ãåŒã³åºãããšã§ãã³ãŒããçµäºããŸãã ãã®èŠçŽ ã«ã¯data-server-rendered
ãèªåçã«äžããããããããããè¡ãããšãã§ããŸãïŒ app.$mount(document.body.querySelector('[data-server-rendered]'))
ã
SSRïŒserver.jsïŒã®ãšã³ããªãã€ã³ã ã èŠæ±ã³ã³ããã¹ãïŒã€ãŸããExpressããã®èŠæ±ãªããžã§ã¯ãïŒãåãåããã¢ããªã±ãŒã·ã§ã³ãåæåããé¢æ°ãäœæããã ãã§ãã é¢æ°ã¯ãããã¹ãè¿ãå¿
èŠããããŸããããã¯ãå¿
èŠãªããŒã¿ããã¹ãŠAPIããããŠã³ããŒããããæç¹ã§æºããããã¢ããªã±ãŒã·ã§ã³ãã¯ã©ã€ã¢ã³ãã«éä¿¡ããæºåãæŽããŸãã
ãã®é¢æ°ã®æé ã¯æ¬¡ã®ãšããã§ãïŒ ã³ãŒã ïŒïŒ
- app.jsããã¢ããªã±ãŒã·ã§ã³ãäœæããŸãã
- APIãµãŒããŒã«ããŒã«ã«ã§ã¢ã¯ã»ã¹ã§ããããã«ãaxiosã§baseUrlãæ§æããŸãïŒå¿ èŠãªå ŽåïŒã ããã§ã¯ããã©ãŠã¶ãååšããªããããå°ãªããšããã¡ã€ã³ãšãããã³ã«ãååŸã§ããå Žæãªããžã§ã¯ãã¯ååšããªããããæåã§ç»é²ããå¿ èŠããããŸãã
- ã³ã³ããŒãã³ããšURLãèŠã€ãã£ããšãã«å®è¡ãããvue-router readyïŒ
app.$router.onReady(...)
ïŒã®ãã³ãã©ãŒãèšå®ããŸãapp.$router.onReady(...)
- ãã®ããŒãžã®ãã¹ãŠã®éåæã³ã³ããŒãã³ããååŸãããããã®æ©èœãå®è¡ããŠéåæããŒã¿ããã«ããŸãã è¿ãããçŽæãé åã«åéããŸãã
-
Promise.all
ãã¹ãŠã®çŽæãå®äºããããšãPromise.all
ãŸãã - vue-metaãvuexç¶æ ããã³ã³ããã¹ãæ å ±ã«è¿œå ããããšã§è§£æ±ºããéåææäœã®çµæãšããŠååŸãããããŒã¿ãã³ã³ããŒãã³ããšã³ã³ããã¹ãã«æžã蟌ã¿ãŸãã
- ã³ã³ããã¹ãïŒ
app.$router.push(context.url)
ïŒããURLãåŠçããæéã§ããããšãã«ãŒã¿ãŒã«äŒããŸãã
ããã«ãåä¿¡ããããŒã¿ã¯ãã¹ãŠhttpãµãŒããŒã«ãã£ãŠåŠçãããã³ã³ããŒãã³ãã¯ããŒã¯ã¢ãããæäŸããããŒã¯ã¢ããããŒã¿ã¯ãã³ãã¬ãŒãã«æžã蟌ãŸããçµæã®HTMLã¯ã¯ã©ã€ã¢ã³ãã«éä¿¡ãããŸãã
ã³ã³ããŒãã³ããšã«ãŒãã£ã³ã°
ã«ãŒã¿ãŒãšãã®ã³ã³ããŒãã³ããç»é²ããããã®ã³ãŒã ã
SSRã䜿çšããŠã¢ããªã±ãŒã·ã§ã³ãéçºããã«ã¯ãã«ãŒãã³ã³ããŒãã³ãã«é¢é£ä»ããããŠããã«ãŒãã³ã³ããŒãã³ãã®ã¿ããã¬ã³ããªã³ã°åã«ããŒã¿ãéåæã«ããŒãã§ãããšããäºå®ããé²ããå¿ èŠããããŸãã ãããã®ã³ã³ããŒãã³ãã«ã€ããŠã¯ãç¹å¥ãªæ¹æ³ã§ãã«ãŒããžã®å€æŽãåŠçããã¬ã³ããªã³ã°åŸã«ãµãŒããŒãè¿ããããŒã¿ãèšé²ããå¿ èŠããããŸãã ãããã®ç®çã®ããã®è¯ã解決çã¯ãã«ãŒã¿ãŒãåæåããããšãã«åã³ã³ããŒãã³ãã«èªåçã«æ¥ç¶ããããã¯ã¹ã€ã³ãäœæããããšã§ãã åæ§ã®ããã¯ã¹ã€ã³ã®ãµã³ãã«ã³ãŒã ã
prefetch-mixinã§ã¯ã次ã®ãããªãã®ãè¿œå ããå¿ èŠããããŸãã
- created-hookã¯ãprefetchDataãã£ãŒã«ããååŸãïŒã¢ããªã±ãŒã·ã§ã³ã®åæåäžãã³ã³ããŒãã³ãããŒã¿ã¯ã¬ã³ããªã³ã°åŸã«ãµãŒããŒããååŸãããã®ãã£ãŒã«ãã«æžã蟌ãŸãããããµãŒããŒã§ã®ã¬ã³ããªã³ã°äžã«çŽæ¥èšé²ãããŸãïŒã
this.$data
å€ãå®å šã«çœ®ãæããŸãthis.$data
fields fromthis.constructor.extendOptions.prefetchData
ããã ããã¢ããªã±ãŒã·ã§ã³ãå®å šã«åæåãããåã«ã®ã¿ãããããäœãèŠã€ããããšãã§ããŸããthis.$root._isMounted
ã - beforeMountããã¯ã¯ãå¥ã®ã«ãŒããžã®ç§»è¡ãããå Žåã«ãããŒãžã®ããŒãåŸã«ã®ã¿ã¯ã©ã€ã¢ã³ãã§ããªãã§ãããåŒã³åºããŸãã
- beforeRouteUpdateããã¯ã¯ãã«ãŒããã©ã¡ãŒã¿ãå€æŽãããšãã«ã¯ã©ã€ã¢ã³ãã§ã®ã¿ããªãã§ãããåŒã³åºããŸãã
function update(vm, next, route) { if (!route) route = vm.$route; const promise = vm.$options.prefetch({ store: vm.$store, props: route.params, route }); if (!promise) return next ? next() : undefined; promise .then(data => { Object.assign(vm.$data, data); if (next) next(); }) .catch(err => next && next(err)); } const mixin = { // created() { if (this.$root._isMounted || !this.constructor.extendOptions.prefetchedData) return; Object.assign(this.$data, this.constructor.extendOptions.prefetchedData); }, // prefetch ( , created) beforeMount() { if (this.$root._isMounted && this.$options.prefetch) update(this); } // prefetch, // , beforeMount beforeRouteUpdate(to, from, next) { if (this.$options.prefetch && to.path !== from.path) update(this, next, to); else next(); }, };
ãããªãéçº
SSRã¯ãã¢ããªã±ãŒã·ã§ã³éçºã«ã»ãšãã©å¶éã課ããŸããã ãµãŒããŒäžã§ã³ãŒããå®è¡ããããã©ãŠã¶APIã¯äœ¿çšã§ããªãããšãèŠããŠããã ãã§ååã§ããä»ã®å Žåã¯ãããŠã³ã/ããŠã³ãã®åã«ã¯ã©ã€ã¢ã³ãããã¯ã«ã³ãŒããé 眮ããŸãã
ãŸããSSRã§åäœããããã«èšèšãããã¢ããªã±ãŒã·ã§ã³ã¯SSRãªãã§ãæ£åžžã«åäœãããããåŸæ¥ã®SPAã§ãåæ§ã®ã¢ãããŒãã䜿çšããŠãSEOèŠä»¶ãçªç¶çŸããå Žåã«ãé ãæ©ãŸããã«ãµã€ããæé©åããããã«æŸèæãæžãå¿ èŠã¯ãããŸããã
ãã£ã¬ã¯ãã£ãã«åé¡ãããå¯èœæ§ãããããã®åœ¹å²ã¯ãã°ãã°DOMã®æäœã«èŠçŽãããŸããããµãŒããŒèªäœã®ãã£ã¬ã¯ãã£ãã®ä»£ããã«ä»£æ¿å®è£ ïŒç©ºïŒïŒãäžããããšã§ç°¡åã«è§£æ±ºã§ããŸãïŒ docs ïŒã
äžè¬ã«ãã¢ããªã±ãŒã·ã§ã³èªäœã®éçºãéå§ããåã«èæ ®ããå¿ èŠãããã®ã¯ããã ãã§ãã 次ã«ãã³ã³ããŒãã³ããäœæããããŒãžã³ã³ããŒãã³ãã察å¿ããã«ãŒãã«æ¥ç¶ããŸãããã¹ãŠãæ£ããè¡ããããšããµãŒããŒããã¬ã³ããªã³ã°ãããããŒãžãåãåããã¯ã©ã€ã¢ã³ãã§ã¢ããªã±ãŒã·ã§ã³ãæ£ããåäœããŸãã