ãã®è¨äºã¯ãCYBOZU SUMMER BLOG FES '24 (Garoon Stage) DAY 7ã®è¨äºã§ãã
Nozomiãã¼ã ã®ã±ãã¨ã¾ã§ãã
ããæ°ã¶æããµã¤ãããã¸ã§ã¯ãã¨ãã¦éå»ã®ä»æ§æ¸ããã¬ãã¸ãConfluenceããDocusaurusã«ããããã¥ã¡ã³ããµã¤ãã«ç§»è¡ãã¦ãã¾ããã
ãã®è¨äºã§ã¯ããã®ããã¥ã¡ã³ããµã¤ãã§Elasticsearchã«ããå ¨ææ¤ç´¢ãå®ç¾ããææ³ãç´¹ä»ãã¾ãã
èæ¯
ç¾å¨ãGaroonãã¼ã ã§ã¯ä»æ§æ¸ããã¬ãã¸ãConfluence Cloudã§ç®¡çãã¦ãã¾ãã
ãã®Confluence Cloudã¯2代ç®ã®ããã¥ã¡ã³ã管çç°å¢ã§ã2016å¹´ããã¾ã§ã¯ãªã³ãã¬ãã¹çConfluenceãå©ç¨ãã¦ãã¾ããã
ç¾å¨ã¯ãªã³ãã¬ãã¹çConfluenceã¯å©ç¨ããã¦ãã¾ããããèªã¿åãå°ç¨ãªç¶æ ã§ç¤¾å ã§ç¶æããã¦ãã¾ãããã ãæ°è¦ã¢ã«ã¦ã³ãã®è¿½å ãåæ¢ããã¦ãããã社å ã®åæ°ä»¥ä¸ã®ã¦ã¼ã¶ã¼ãé²è¦§æ¨©éããªããªã©ãå»æ¢ã«åãããã¼ãããããé²ãã§ãã¾ãã
Garoonãã¼ã ãããå©ç¨ããè³æã¯Confluence Cloudã«ç§»è¡ãã¦ãããã®ã®ãæ®æ®µä½¿ããªãè³æã«ã¤ãã¦ã¯ç§»è¡ãæ»ã£ã¦ãã¾ããããããããªã³ãã¬ãã¹çConfluenceã®ã¢ã«ã¦ã³ããæã¤ã¡ã³ãã¼ãæ¸ã£ã¦ãã¦ãããããå ¨ã¦ã®è³æãDocusaurusã§ããã¥ã¡ã³ããµã¤ãã«ã¢ã¼ã«ã¤ããããã¨ã«ãã¾ããã
Docusaurus
Docusaurusã¯ãããã¥ã¡ã³ããµã¤ããç°¡åã«ä½æã§ããReactãã¼ã¹ã®éçãµã¤ãã¸ã§ãã¬ã¼ã¿ï¼SSGï¼ã§ãã
ããã¥ã¡ã³ãã®ãã¼ã¸ã§ãã³ã°ãè¤æ°è¨èªã®ç¿»è¨³ãªã©ãä»æ§æ¸ã»APIããã¥ã¡ã³ãã»ãã«ããµã¤ããªã©ã«å¿ è¦ãªæ©è½ãæã£ãWebãµã¤ãããMDXã¨ããJSXãå å ã§ããMarkdownæ¹è¨ã«ãã£ã¦ä½æã§ãã¾ãã
Docusaurusã®ç¹å¾´ã¯ãããã³ãã¨ã³ããReactã³ã³ãã¼ãã³ãã«ãªã£ã¦ããããã«ã¹ã¿ãã¤ãºãããããã¨ã§ãããã ããInfimaã¨ããç¬èªã®CSSãã¬ã¼ã ã¯ã¼ã¯ãæ¡ç¨ãã¦ããããSwizzlingã¨ããç¬ç¹ãªã³ã³ãã¼ãã³ãã®ç®¡çããã¦ãããããã®ã§æ±ç¨ã®Reactãã¬ã¼ã ã¯ã¼ã¯ããã¯å°ãçãããã¾ãã
ã¾ããã«ã¹ã¿ãã¤ãºã容æã§ç»é¢ã®ãã¶ã¤ã³ã綺éºãªã®ã§ãããHugoãªã©ä»ã®SSGã¨æ¯ã¹ã¦ãã«ããé
ããã¨ãæ¬ ç¹ã§ããä»å移è¡ãããã¼ã¸ã¯4000件ã»ã©ã§ããããnpm run build
ã«10åã»ã©ãããã¾ããã
å ¨ææ¤ç´¢æ©è½ã«ã¤ãã¦ã¯ãAlgoliaã®ã¿ãå ¬å¼ã§ãµãã¼ããã¦ãã¾ããä»ã«ã¯ã³ãã¥ããã£ãµãã¼ãã¨ãã¦TypesenseãLunr.jsãPagefindãããã¾ããAlgoliaã¯ãµã¤ãã¦ãºç¤¾å ã®ã»ãã¥ãªãã£è¦ä»¶ããæ¡ç¨ãé£ãããTypesenseãLunr.jsãPagefindã¯æ¥æ¬èªæ¤ç´¢ã«é£ãããã¾ããã¾ããLunr.jsã¨Pagefindã¯ã¯ã©ã¤ã¢ã³ããµã¤ãã«æ¤ç´¢ã¤ã³ããã¯ã¹ãæã¤ã¨ã³ã¸ã³ãªã®ã§ããã¼ã¸æ°ãæ°å件ã«ãªãã¨æ§è½ã«ä¸å®ãããã¾ããã
Docusaurusã®æ¤ç´¢ã³ã³ãã¼ãã³ã
Docusaurusã§ã¯æ¤ç´¢æ©è½ãã³ã³ãã¼ãã³ãã¨ãªã£ã¦ãã¦ãSwizzlingã¨ããä»çµã¿ã§ç·¨éãããã¨ãã§ãã¾ãã
Algoliaãã¼ã¹ã®æ¤ç´¢
ããã¥ã¡ã³ãã§ç´¹ä»ããã¦ããéããå ¬å¼ãµãã¼ãã®ã³ã³ãã¼ãã³ãã§ãã
npm run swizzle @docusaurus/theme-search-algolia SearchBar
ã¨ããã³ãã³ãã«ãããsrc/theme/SearchBar
ãã£ã¬ã¯ããªã«å®è£
ãã³ãã¼ãããç·¨éã§ãã¾ãã
å³ã®ããã«ãå ¬å¼ããã¥ã¡ã³ãã®æ¤ç´¢æ©è½ãAlgoliaãã¼ã¹ã®ãã®ã§ããå³ã®ã°ã¬ã¼ã¢ã¦ãé åã®å³ä¸ã«ããæ¤ç´¢æ¬ããããã®ã¯åãªããã¿ã³ã§ãããã¯ãªãã¯ããã¨æ¤ç´¢ããã¯ã¹ãåºç¾ãã¾ãã
æ¤ç´¢æ©è½ã®å®ä½ã¯ãã®æ¤ç´¢ããã¯ã¹ãªã®ã§ãããããªãDocusaurusããã³Algoliaã¨å¯çµåããä½ãã«ãªã£ã¦ãã¦ãçè ãããã³ãã¨ã³ãã«çããã¨ãå·®ãå¼ãã¦ãæ¹å¤ã¯é£ããããã«æãã¾ããã
æ¨æºãã¼ãã®æ¤ç´¢ã³ã³ãã¼ãã³ã
ãã¡ãã¯ç©ºã®ã³ã³ãã¼ãã³ãã§ããããã¥ã¡ã³ãã«ããã¨ããã®å®è£ ãå¤æ´ãã¦èªç±ã«æ¤ç´¢æ©è½ãä½ã£ã¦ããã¨ããæå³ã®ããã§ãã
npm run swizzle @docusaurus/theme-classic SearchBar
ã¨ããã³ãã³ãã«ãããsrc/theme/SearchBar
ãã£ã¬ã¯ããªã«å®è£
ãã³ãã¼ãããç·¨éã§ãã¾ããä¸èº«ã¯ç©ºã®index.tsxã¨custom.cssã§ãã
å®è£ æ¹é
å½åã¯Algoliaãã¼ã¹ã®æ¤ç´¢ãã¼ãæ¹å¤ãã¦Elasticsearchã«å¯¾å¿ããããã¨èãã¦ãã¾ãããããããåè¿°ã®æ¹å¤ã®é£ããã«å ãã¦æ¤ç´¢ããã¯ã¹åã®æ¤ç´¢æ©è½ãèªåã®å¥½ã¿ã«åããªãã£ããããç¬èªã«æ¤ç´¢æ©è½ãå®è£ ãããã¨ã«ãã¾ãããå®è£ ããæ¤ç´¢æ©è½ã¯ãæ¤ç´¢ãã¼ã«æåãå ¥åããã¨ç¬ç«ããæ¤ç´¢ãã¼ã¸ã«ã¸ã£ã³ããããããªå½¢å¼ã§ãã
æ¤ç´¢ãã¼ã¸ã¯Docusauruså´ã§ä½æãããã¨ãåºæ¥ãã®ã§ãããDocusaurusã®CSSãã¬ã¼ã ã¯ã¼ã¯ã§ããInfimaã«æ å ±ãã»ã¨ãã©ãªããã¨ããã調æ»ãé£èªãããã¨ãäºæ³ããã¾ãããã¾ããDocusaurusã¯SSGå°éã®ãã¬ã¼ã ã¯ã¼ã¯ã§ãããããæ¤ç´¢ãªã¯ã¨ã¹ããElasticsearchã«ä¸ç¶ãããããªããã¯ã¨ã³ãã®ãµã¼ãã¼ã¯ç¨æããã¦ãã¾ãããElasticsearchã¯REST APIãæ¡ç¨ãã¦ããã®ã§ã¯ã©ã¤ã¢ã³ãããç´æ¥å¼ã³åºããã¨ãã§ãã¾ãããã»ãã¥ãªãã£ãªã¹ã¯ã¨ãªãæãããã*1ããããã¯ã¨ã³ãããå¼ã³åºãå¿ è¦ãããã¾ãããããã®çç±ãããæ¤ç´¢ãã¼ã¸ã®å®è£ ã¯å¥ã®ãã¬ã¼ã ã¯ã¼ã¯ãå©ç¨ãããã¨ã«ãã¾ããã
ä½æãããã¼ã¸æ°ãå°ãªãããµã¤ãããã¸ã§ã¯ããªã®ã§å·¥æ°ããªãã¹ãå°ãªããããã£ãããã軽éãªãã¬ã¼ã ã¯ã¼ã¯ã§ããã¯ã¨ã³ãã¨ã®çµ±åãåªãã¦ããRemixãå©ç¨ãã¾ããã
Remix
Remixã¯Reactãã¼ã¹ã®Webãã¬ã¼ã ã¯ã¼ã¯ã§ãããã·ã³ãã«ãã¨Webæ¨æºã¸ã®æºæ ã謳ã£ã¦ãã¾ãã
Remixã¯ã³ã³ãã¯ããªãã¬ã¼ã ã¯ã¼ã¯ã§ãããSSGããµãã¼ããã¦ãã¾ãããä»åã®ã¦ã¼ã¹ã±ã¼ã¹ã§ã¯SSGãå¿ è¦ãªè¦ç´ ã¯Docusaurusã«å ¨ã¦ä»»ãã¦ããããããã®ç¹ã¯ããããã¦ãã¾ããã
ã¾ããRemixã®ããµã¼ãã¼ã§åä½ããã³ã¼ãã¨ã¯ã©ã¤ã¢ã³ãã§åä½ããã³ã¼ããæ確ã«åããã¦ãããã¨ããç¹ããä»åã®è¦ä»¶ã¨ããããã¦ãã¾ãããElasticsearchã®REST APIã§å©ç¨ããèªè¨¼ãã¼ãªã©ã®ãã¼ã¿ã¯ãã»ãã¥ãªãã£ä¸ãµã¼ãã¼ãµã¤ãã«éããå¿ è¦ãããã¾ãããRemixã§ã¯ãã®ãããªè¨è¿°ãèªç¶ã«æ¸ããã¨ãã§ãã¾ããã
ã·ã¹ãã ã®æ§æ
ä»åæ§ç¯ããã·ã¹ãã ã¯ãä¸ã®å³ã®ãããªæ§æã«ãªã£ã¦ãã¾ãã
/search
ã¸ã®ãªã¯ã¨ã¹ãã¯nginxã«ãã£ã¦æ¤ç´¢ãã¼ã¸ã«æ¯ãåãããã¾ããæ¤ç´¢ãã¼ã¸ã¯Docker Composeä¸ã®Remix App Serverã§åä½ãã¦ãããåããDocker Composeä¸ã®Elasticsearchã®APIã«ã¢ã¯ã»ã¹ãã¦æ¤ç´¢ãã¾ãã
/search
以å¤ã¸ã®ãªã¯ã¨ã¹ãã¯é常ã®ããã¥ã¡ã³ããµã¤ãã¨ãã¦ãDocusaurusã§çæãããéçãã¡ã¤ã«ãnginxããé
ä¿¡ããã¾ãã
æ¸ãæããçºçããªãã¢ã¼ã«ã¤ããµã¤ãã¨ããæ§è³ªä¸ãéçãã¡ã¤ã«ã®ãã«ããElasticsearchã¸ã®ããã¥ã¡ã³ã追å ã«ãã¤ãã©ã¤ã³ã¯çµãã§ããããä¸åããã®å®æ½ã«ãªã£ã¦ãã¾ãã
Remixã«ããæ¤ç´¢ãã¼ã¸ã®å®è£
ããããããã¨ã«ãRemixã®ãã¥ã¼ããªã¢ã«ã«æ¤ç´¢ããã¯ã¹ã®åèå®è£ ãããã¾ãã
ãã¥ã¼ããªã¢ã«ã«å¾ã£ã¦æåå
¥åã®ãã³ã«fetch
ããæ¤ç´¢ãã¼ãä½æããloader
ã§Elasticsearchããæ¤ç´¢çµæãåå¾ãããã¨ã§ã¤ã³ã¯ãªã¡ã³ã¿ã«ãµã¼ããå®è£
ã§ãã¾ããã
ãã¥ã¼ããªã¢ã«ä»¥å¤ã®è¦ç´ ã¨ãã¦ã¯ãIMEã®ON/OFFãInputEvent.isComposingããã³CompositionEventããæ¤ç¥ãããã¨ã§ããªæ¼¢åå¤æä¸ã«æ¤ç´¢ãããªãããã«ãã¾ãããå®è£
ããã³ã¼ãã®ä¸é¨ã以ä¸ã«ç¤ºãã¾ãããªããSafari以å¤ã§ã¯å¤æåè£ã®ç¢ºå®ï¼Enteræ¼ä¸ï¼æã«event.nativeEvent.isComposing
ãtrue
ã«ãªã*2ãããonCompositionEnd
ã¤ãã³ãã§ãsubmit()
ãå¼ã³åºãã¦ãã¾ãã
return ( <Form onChange={(event) => { if (! event.nativeEvent.isComposing) { return; } submit(event.currentTarget, { replace: true }); }} > <input onCompositionEnd={(event) => { submit(event.currentTarget.parentElement, { replace: true }); }} /> </Form> );
ãµã¼ãã¼ãµã¤ãã§ã¯ãElasticsearch Node.js clientãç¨ãã¦Elasticsearchã«æ¤ç´¢çµæãåãåãããçµæã«åããã¦ãã³ãããªã¹ããçæãã¦ãã¾ãã
ã¯ã©ã¤ã¢ã³ãã»ãµã¼ãã¼ã®ã©ã¡ããã·ã³ãã«ãªå®è£ ã¨ãªã£ããããã©ã¡ããã¨ããã¨Tailwind CSSã使ã£ã¦æ¤ç´¢ãã¼ã¸ã¨Docusaurusã®ãã¶ã¤ã³ãåãããæ¹ã大å¤ã§ããã
Docusaurusã¸ã®æ¤ç´¢ãã¼ã®å®è£
ãã¡ãã¯æ¨æºãã¼ãã®æ¤ç´¢ã³ã³ãã¼ãã³ããç·¨éããå½¢ã§å®è£
ãã¾ããã<input>
ã¿ã°ã«æ¤ç´¢ã¯ã¼ããå
¥åãã¦Enterãã¼ãæ¼ãã¨ãå
¥åå
容ãã¯ã¨ãªã¨ãã¦æ¤ç´¢ãã¼ã¸ã«ã¸ã£ã³ãããReactã³ã³ãã¼ãã³ãã§ãã
æ¤ç´¢æ©è½ãæ¤ç´¢ãã¼ã¸ã«éç´ãããããã¨ã¦ãåç´ãªå®è£ ã«ãªãã¾ããã
ã¾ã¨ã
æ¤ç´¢ãã¼ã¸ãRemixã§å®è£ ãããã¨ã§ãDocusaurus製ã®ããã¥ã¡ã³ããµã¤ãã§Elasticsearchã«ããå ¨ææ¤ç´¢ãå®ç¾ãã¾ãããçè ã¯Reactããã³ãã¨ã³ãã¯æªçµé¨ã ã£ãã®ã§ãããElasticsearchã«ã¯ããç¨åº¦æ £ãã¦ãããã¨ããã£ã¦åè¨ä¸é±éã»ã©ã§ä½æã§ãã¾ããã
Docusaurusã®ä»ã«ãããã¥ã¡ã³ããµã¤ãåãã®SSGã¯ããã¤ãããã¾ãããå ¨ææ¤ç´¢ã¨ã³ã¸ã³ã®é¸æè¢ã¯éããã¦ãããæ¥æ¬èªæ¤ç´¢ãå¯è½ãªã®ã¯Algoliaã ãã¨ããå ´åãå¤ãã§ããAlgoliaã¯ã¯ã©ã¦ããµã¼ãã¹ãªã®ã§ãæ©å¯ãã¼ã¿ãè²»ç¨ãå¤é¨ã¢ã¯ã»ã¹ãªã©ã®äºæ ã§å©ç¨ã§ããªããã¨ãå¤ãã¨æãã¾ãããã®éã¯ãå·¥æ°ãæãåãã°æ¤ç´¢ãã¼ã¸ãèªåã§å®è£ ããé¸æè¢ãæ¤è¨ããã¨è¯ãããããã¾ããã
*1:https://github.com/elastic/elasticsearch-js?tab=readme-ov-file#browser
*2:https://webfrontend.ninja/js-input-ime-enter/ ãªã©ãåèã«ãã¾ãã