React+jQuery+Railsã®SPAããµã¼ããµã¤ãã¬ã³ããªã³ã°ã«ç§»è¡ãã件ï¼ãã®1ï¼æ¦è¦ç·¨ï¼
å
æ¥ãããã§ã³ã¯ããã¼ãã£ã¼ã·ãã¥ã¬ã¼ã¿ã¼ãï¼ä»¥ä¸ãccpsãï¼ãã¢ãããã¼ããã¾ãã¦ã
ãµã¼ããµã¤ãã¬ã³ããªã³ã°ï¼ãããããSSRãï¼ã«å¯¾å¿ãã¾ããã½(`ï½¥Ï・´)ã
éå»ã®çµç·¯ã¯ãã¡ããè¦ã¦ããã ãããã®ã§ããã»ã»ã»
ã»ã»ã»ãã§ã«ãReact+jQueryãã§åãã¦ããããTypeScriptãã§æ¸ãããSPAã§ãããã¾ã
ããããSPAã§ãããããã«ã大ããªåé¡ãæ±ãã¦ããã¾ãã¦ã
ããã¯ãã¨ã«ããåæ表示ãé
ããã¨ãããã¨ã§ã(´-Ï-)
ããã解決ããã®ãããµã¼ããµã¤ãã¬ã³ããªã³ã°ï¼SSRï¼ããªã®ã§ããã
ããããæ¤ç´¢ãã¦ã¿ãã¨ãããã¨å¦å®çãªæè¦ãå¤ãããã¾ã
ãã£ã¦ã¿ãä¸ã§ãç§ãã©ã¡ããã¨ããã°å¦å®çãªã®ã§ããã
è¦ã¯ãã©ãã§ä½¿ãã¹ããã®ãªã®ãï¼ããéè¦ã ã¨æãã®ã§ãã
SSRèªä½ãããã¨æéããããããããç¨ã®è¨è¨ãææ³ãå¿
è¦ã«ãªããã®ã§ããã
ç§ãããªãè¦å´ãããããã®ã§ããããããç´è§£ãã¦ããããã«ãã
ä»åã¯ããã¦ãå½ããåã®ãã¨ãããèãã¦ã¿ã¾ã...Ï(ï½¥Ïï½¥ï½)
ãªããããªãé·ããªãäºå®ãªã®ã§ãæ¦è¦ç·¨ã»å®æ¦ç·¨ã¨åããä¸ã§ã
å
¨é¨ã§æ°åã«ãªãäºå®ã§ã
ï¼ç¬¬2åï¼
parrot.hatenadiary.jp
ãããããµã¼ããµã¤ãã¬ã³ããªã³ã°ï¼SSRï¼ã¨ã¯ä½ãï¼
å·éã«èãã¦ãããããã®ã§ããã
ããããããµã¼ããµã¤ãã§HTMLãåºåããã¯ã©ã¤ã¢ã³ãã®JavaScriptã§å¶å¾¡ãããã¨ããã®ã¯ã
Webã·ã¹ãã ã¨ãã¦ã¯ãããæ®éãã®è©±ã§ã
ã«ããããããããããããSSRããªãã¦ä»°ã
ããè¨èãå®ç¾©ããããã§ãããã
ããµã¼ããµã¤ãã§HTMLãä½ããã¨ãã ãã§ã¯ãªãããã§ã
ãããããç¾ä»£çãªWebã·ã¹ãã ã«ããã¦ããµã¼ããµã¤ããAPIçãªãã®ãæä¾ãã
ã¯ã©ã¤ã¢ã³ããï¼æ§æ¥ã«æ¯ã¹ãã¨ãããªãããªï¼jsã§å¶å¾¡ããã»ã»ã»ã¨ããã¬ãã«ã®è¨è¨ã¯ã
ãã§ã«ä¸è¬çã¨ãã£ã¦ããã¬ãã«ã ã¨ï¼å°ãªãã¨ãç§ã¯ï¼æã£ã¦ã¾ã
ãã®ããªãããªjsããåãªããå¶å¾¡ããè¶
ãã¦ããç»é¢ã大å¹
ã«æ¸ãæãããã
ã¤ã¾ãã¯ãviewããç´ã«ãããã¬ãã«ã«ãªã£ã¦ããã¨ã
ã¯ã©ã¤ã¢ã³ãã®viewå¶å¾¡ã¨ããµã¼ããµã¤ãã®viewçæã§ããã¸ãã¯ããäºéåãããããã¨ã«ãªãã¾ã
ããã解æ¶ããããããviewã¯å
¨é¨ã¯ã©ã¤ã¢ã³ãã«å¯ããããã¨ãããä¸ã§ã
ãç»é¢ã®åãæ¿ãã®ã¬ãã«ã¾ã§å
¨é¨viewã®å¶å¾¡ã«å¯ãããã
ããµã¼ããµã¤ãã¯ç´ç²ãªAPIãã¨ããè¨è¨æ¹éãã¨ã£ãã®ããSPAãã¨ãããã¨ã§ãã
ãããããã¯ã©ã¤ã¢ã³ãã§viewãä½ããã¨ãããã¨ã¯ã
ãã¯ã©ã¤ã¢ã³ãã§jsã解éããªãéããç»é¢ãè¦ããªããã¨ããåé¡ãããã¾ã
ï¼ããããããã¡ã¼ã¹ããã¥ã¼ãé
ããåé¡ï¼
ãµã¼ãã§HTMLãä½ã£ã¦ããã°ãå°ãªãã¨ããã®ç¯å²ã§ã¯ãã表示ãããã®ã§ããã
SPAã®å ´åã¯jsã®éä¿¡é度ãã¯ã©ã¤ã¢ã³ãã®CPUé度ãªã©ã
æ§ã
ãªè¦å ã絡ãã®ã§ãç¸å¯¾çã«ã¯ãé
ããããã§ã(´-Ï-)
ä¸è¬çã«ãSPAã®åé¡ã¨ãã¦ãããããã®ã¯ãã®ãããã§ãããã
- ãã¡ã¼ã¹ããã¥ã¼ãé ã
- SEOçãªåé¡
- ã¯ãã¼ã©ã¼ãæ£ããSPAã解éã§ããã¨ã¯éããªã
- OGPãããªéçãªã¿ã°åºåã¯ãµã¼ããµã¤ãã§ããã§ããªã
ç§ã®ccptsã®å ´åã¯ããã¼ã«ããªã®ã§ãç·¨éã¢ã¼ãã§å¤å°å¾
ããããã®ã¯ã¨ãããã
å
±æãããURLããé£ãã§ãããPTé²è¦§ã¢ã¼ããã§ã
ç·¨éç¨ã®ã³ã¼ãã解éããæéã§å¾
ããããã»ã»ã»ã¨ããã®ã¯ãæ¬æ¥ããããããã¾ãã
åæ§ã«ãä¾ãã°Blogããã¥ã¼ã¹è¨äºã®ãããªã
ãã¦ã¼ã¶ã¼ãURLããé£ãã§ãã¦ããã è¦ããã ãã®ãµã¤ããã¯ã
åºæ¬çã«SPAã«åãã¦ã¾ãã(´・Ïï½¥`)
ãããã£ããµã¤ãã¯ãæ®éã«ãµã¼ããµã¤ãã§HTMLãåºåããã°ããããã§ã
ãããããSSRããæ¤è¨ãã以åã®åé¡ã§ã
è¨ããããã°ãã¾ãSPAã«ãã¹ããã®æ¤è¨ããã£ã¦ã
SPAãå¿
è¦ã ãã©ãããã§ã¯é
ãã¨ããå ´åã«ã
åãã¦SSRãæ¤è¨ãããã»ã»ã»ã¨ããã®ãæ¬çãã¨
ããããSPAã«ã§ããã°SSRã¯ç°¡åãªã®ãã¨ããã¨ã
ãããªãã¨ã¯ãªãããã§ããã£ã¡ãã³ã¹ãããããã¾ã
Webã§è¯ãè¦ããSSRä¸è¦è«ãã¯ã
ãçæ³çã§ã¯ãããã©ã移è¡ããã³ã¹ãã«è¦åããªããã¨ãããã¨ã ã¨æã£ã¦ã¾ã
SSRã®åé¡ç¹ã¯ãããªæããã¨
ï¼ãã¨ã§åºã¦ãã¾ããããã®ãSSRã®åé¡ç¹ãã¯ã
ããSSRã«ç§»è¡ããããã®æ®µåããã¨é¢é£ãã¦ãã¾ãï¼
- ï¼SPAã¨ãã¦å®æãã¦ããã¨ãã¦ãï¼å®è£
ã³ã¹ããããã
- ããã©ã¦ã¶ãã§åä½ãããã¨ãåæã«ãæé»çã«æ¸ãããä»æ§ãå
¨ã¦è¦ç´ãå¿
è¦ããã
- ä¾ï¼windowãªãã¸ã§ã¯ãã¸ã®åç §ã»æé»çãªã¤ãã³ãã¸ã®ä¾å
- ããã©ã¦ã¶ãã§åä½ãããã¨ãåæã«ãæé»çã«æ¸ãããä»æ§ãå
¨ã¦è¦ç´ãå¿
è¦ããã
- ã¯ã©ã¤ã¢ã³ãã¨ãµã¼ããµã¤ãã®æ
å½ç¯å²ãããã¾ãã«ãªã
- ã¯ã©ã¤ã¢ã³ãã ããç¥ã£ã¦ããã°ããã£ããã¨ãããµã¼ããµã¤ãã§ãèæ ®ããªãã¨ãããªã
- ï¼é常ã®HTMLåºåã«æ¯ã¹ã¦ï¼å¦çãéã
ãããã®ã¡ãªããã¨ãã¡ãªããããµã¾ããä¸ã§ã
ä»ä½ããã¨ãã¦ããã·ã¹ãã ã«å¯¾ãããæ®éã®HTMLåºåï¼jsããããã®ãã
ãSPAã®SSRãããã®ãããå¤æãå¿
è¦ã«ãªã£ã¦ãã¾ã
ï¼åèï¼
STEP0ï¼SPAãSSRã«ããããã®æ¦è¦è¨è¨
(1) SSRãé»å®³ããè¦å
ä»åã®SSR移è¡ã«é¢ãã¦ã¯ã以åãã使ã£ã¦ãããReact on Railsãã®æ©è½ãå©ç¨ãã¦ãã¾ã
以åã¯ãSPAãRailsã«çµ¡ãã¦ç°¡åã«ãããã¤ã§ãããã¼ã«ãçã«ä½¿ã£ã¦ããã®ã§ããã
å
ã
SSRã®æ©è½ãã¤ãã¦ã¾ãã¦ãSSRã試ãã ããªãprerenderãã©ã°ãtrueã«ããã ãã§ã *1
<%= react_component("HelloWorld", props: @some_props, prerender: true) %>
ãã¡ããããããã ããã§SSRãåãã¦ããããªãã
React on Railsãéçºãã¦ããä¼ç¤¾ã®ã³ã³ãµã«æ¥ã¯æãç«ããªãããã§ã
ãããªåç´ãªè©±ã§ã¯ããã¾ãã(´・Ïï½¥`)
ããµã¼ããµã¤ãã§jsãåãããã¨ããã®ã¯ã
Railsã®æèã«ããã¦ã¯ãexecjsãã®ãã¨ãæãã¾ã*2
ï¼ä¸è¬çã«ã¯Node.jsã®ãµã¼ããµã¤ãããã»ã¹ã»ã»ã»ã§ãããï¼
execjsã¯ãµã¼ããµã¤ãã§ã®jså®è¡ç³»ãªã®ã§ãããã©ã¦ã¶ãã®æ¦å¿µãããã¾ãã
SSRã試ãã¦ãããããæåã«ç®ã«ããã¨ã©ã¼ã¯ã
ãwindowãªãã¸ã§ã¯ãããªããã¨ãããã®ã§ããã
windowã¨æ¸ãã¦ãªãã¦ããä¾ãã°ãlocationãããconfirmãã®ããã«ã
æé»çã«windowãªãã¸ã§ã¯ããåç
§ãã¦ãããã®ã¯ããããããã¾ã
ãããã£ããã®ã¯å
¨ã¦ããµã¼ããµã¤ãjsã§ã¯åä½ããªããã¨ã«ãªãã¾ã
Reactä¸ä»£ã®ã©ã¤ãã©ãªã¯ã¨ãããã
æ§ä¸ä»£ã®ã©ã¤ãã©ãªã¯ã»ã¼ç¢ºå®ã«windowã触ã£ã¦ããã¯ãã§ã
ãã®ä»£è¡¨æ ¼ã¯ãã¡ããjQueryã¨ãããã¨ã«ãªãã¾ã
ç§ã®ccptsã«ããã¦ãjQueryã¯ä»æ§ä¸å¿
é ã§ã
ããããjQueryã«ä¾åãã¦ããéããå®è¡ç³»ãã¨ã©ã¼ãåãã¦ãã¾ãã¾ã
ããããä»åã®è¨è¨ã«ãããæ大ã®èã«ãªãã¾ã
(2) SSRã«ä½¿ãjsã®å¶ç´ã¨ããã®å¯¾å¦
ã¨ããã§ããReact on Railsãå®è¡ãã¦ããjsãã¡ã¤ã«ãã£ã¦ã©ããªãã§ãããï¼
configãè¦ãã¨ããããªè¨å®é
ç®ãããã¾ã
# config/initializers/react_on_rails.rb ããæç² ReactOnRails.configure do |config| # buildã«ä½¿ãã³ãã³ã config.build_production_command = 'RAILS_ENV=production bin/webpack' # SSRã§å®è¡ããjså config.server_bundle_js_file = 'ccpts.js' end
ããã§æå®ãã¦ãããccpts.jsããã©ãã«ãããã¨ããã¨ã
ã¨ã©ã¼ã¡ãã»ã¼ã¸ãã追ã£ãçµæããpublic/packs/ccpts.jsãã«ããã¾ããã
ããã¯ãapp/javascriptã以ä¸ã®jsãwebpackã§åºãããã¡ã¤ã«ã«ãªãã¾ã
React on Railsã«éãããSSRãããã¨ããå ´åã
webpackçã§åºããåä¸ã®jsããã¯ã©ã¤ã¢ã³ãã¨ãµã¼ãã§å
±æãã
ãµã¼ããµã¤ãã§ãå®è¡ããã»ã»ã»ã¨ããæµãã«ãªãã¾ã
ããã¦ã»ã»ã»ããããã¤ã³ããªã®ã§ããã»ã»ã»
è£ãè¿ãã°ãããµã¼ããµã¤ãã§å®è¡ããjsã«windowãªãã¸ã§ã¯ãçã¯å«ã¾ããã
ã¯ã©ã¤ã¢ã³ãã§å®è¡ããéã«ã¯å«ã¾ãããã¨ããç¶æ³ãä½ããã°è§£æ±ºããã¯ããªã®ã§ã
å®éãããã試ãããã¨ã§SSRã«æåããã®ã§ããã
æ¦è¦ãå³ã«ã¾ã¨ããã¨ãããªãã¾ã
解説ã«ã¤ãã¦ã¯æ¬¡å以éãã£ã¦ããã¾ããã
ç§ãç«ã¦ãSSRåã®æ®µåãã¯ä»¥ä¸ã®ããã«ãªãã¾ã
ï¼ã¾ãã«ãå
ã»ã©æãããSSRã®åé¡ç¹ãã¨å¯¾å¿ãã¦ããã¾ãï¼
- ãã©ã¦ã¶ç³»ãªãã¸ã§ã¯ãã®æé¤ï¼ã¨ããããå®è¡æã¨ã©ã¼ãæ¶ãï¼
- ãä»æ§ä¸ã®æ£ããåä½ãã«ãªãããã«ä¿®æ£
- ã¤ã³ãã©ã®èª¿æ´
次åã¯ãå®è·µç·¨ãã¨ãã¦ãå
ã»ã©ã®å³ã®è§£èª¬ãããªããã
ã©ã®ããã«å
ã»ã©ã®åé¡ã解決ããã®ãã»ã»ã»ãæ¸ãã¦ããã¾ã...Ï(ï½¥Ïï½¥ï½)
ï¼ç¶ãï¼
*1: ãããããµã¼ãã§åºåããReactã®HTMLã¨ãã¯ã©ã¤ã¢ã³ãã®Reactã管çããDOMã§ãããæãã«å¶å¾¡ãã¦ãããΣ(ã»Ïã»ã)ã
*2: å³å¯ã«ããã°ãexecjsã¯Rubyããã»ã¹ã§jsã®å®è¡ç³»ãåããããã®ã¤ã³ã¿ã¼ãã§ã¼ã¹ã§ãããå®éã®å®è¡ç³»ã¯ã¤ã³ã¹ãã¼ã«ãã¦ãããã®ããé¸æããã