
- TOP
- ã¿ã°äžèЧ
- Vue.js
Vue.js
ã€ãã³ã
該åœããã³ã³ãã³ããèŠã€ãããŸããã§ãã
ãã¬ãžã³
æè¡ããã°
ã¯ããã« NTTè¥¿æ¥æ¬ã®äžå·ã§ãã æ¬èšäºã§ã¯ããã©ãŠã¶ã®ã¡ã€ã³ã¹ã¬ãããå æããªããã Web Worker ã䜿ã£ãŠéãåŠçãããã¯ã°ã©ãŠã³ããžéããæ¹æ³ããå®éšã³ãŒãã€ãã§è§£èª¬ããŸããã·ã³ã°ã«ã¹ã¬ããã®JavaScriptã§ããUXãèœãšããã«èšç®åŠçãšæç»ãäž¡ç«ããããã®å®è£
ãã¿ãŒã³ããŸãšããŸããã æ¬èšäºã¯2026幎3ææç¹ã®æ
å ±ã«åºã¥ããŸãã 仿§æžãMDNãªã©ãèªãã§ãããWorkerã«éããããšå£ã§èšãã®ãšã ç»é¢äžã§åãã®å·®ãäžåºŠèŠã ã®ãšã§ã¯ãè
¹èœã¡ã®æ·±ããããªãéããŸããç§èªèº«ãæåã®é ã¯ã€ãã³ãã«ãŒãã®èª¬æãšäœæããªããªãçµã³ã€ãããå®éšçšã®çã for ãåããŠåããŠãå æãã®æå³ãèªåã®ãã®ã«ãªã£ãçµéšããããŸããåãããã«æãåãããªãã確èªãããæ¹ã«åãããã¢ãå€ãã«èŒããŠããŸãã®ã§ããã²è©ŠããŠã¿ãŠãã ããã èšèšææ³ããããã°ææ³ãªã©ãã³ãŒãã®å質ãé«ããæ¹æ³ã¯ããŸããŸã§ããããããã©ãã»ã©ããããªã³ãŒããæžããŠãããŠãŒã¶ãŒäœéšïŒUXïŒãæãªããç»é¢ã®ããªãŒãºããçºçããŠããŸããšãã¢ããªã±ãŒã·ã§ã³ã®äŸ¡å€ã¯å€§ããæãªãããŠããŸããŸãã JavaScriptã¯ã¡ã€ã³ã¹ã¬ããäžã§UIãšã¹ã¯ãªãããé çªã«åŠçããããããéãåŠçããã®ãŸãŸèµ°ããããšæç»ãæ¢ãŸããŸããä»åã¯ããã®éçãç·©åããæšæºæ©èœã§ãã Web Worker ã«çŠç¹ãåœãŠãŠã玹ä»ããŸãã 察象èªè
æ¬èšäºãæ³å®ãã察象èªè
ã¯ä»¥äžã®éãã§ãã JavaScriptã®ã€ãã³ãã«ãŒããå®è¡ã³ã³ããã¹ããªã©åºç€ç¥èããæã¡ã®æ¹ 倧éããŒã¿ã®å å·¥ãè€éãªèšç®ã§ãç»é¢ãäžç¬ã«ã¯ã€ãããæ¢ãŸã£ãããã課é¡ãæ±ããŠããæ¹ ãJavaScriptã¯ã·ã³ã°ã«ã¹ã¬ããã ããéãåŠçã¯é¿ããã¹ãããšããåæã®å
ã«ããã䞊è¡ã«è¿ãå®è¡ã¢ãã«ãç¥ãããæ¹ ç®æ¬¡ ã¯ãã㫠察象èªè
ç®æ¬¡ 1.èæ¯ã»ç®ç 2.ã¹ã¬ãããšã¯ 3.ãªããç»é¢ãæ¢ãŸããã®ãïŒã€ãã³ãã«ãŒãã®å¶çŽïŒ å®éšïŒã¡ã€ã³ã¹ã¬ããããããã¯ããŠã¿ã çµæ 4.Web Workerãšã¯äœã å®è£
æã®äž»ãªã«ãŒã« 5.ãå®è·µãWeb Workerãå°å
¥ããŠããªãŒãºãåããã ã¹ããã1ïŒworker.js ã¹ããã2ïŒindex.htmlïŒã¡ã€ã³ã¹ã¬ããåŽïŒ çµæ è£è¶³ïŒã¡ã€ã³ãšWorkerã®ããåãã®ã³ã¹ã 6.ãããããŠãŒã¹ã±ãŒã¹ãšç°¡æã³ãŒãïŒäœãèµ·ããããã»ããã§çè§£ããïŒ ã±ãŒã¹1ïŒå転ãããåãç¶ããUIããšéãåŠçïŒã«ãŒãïŒ çµæ ã±ãŒã¹2ïŒé²æã®é次éç¥ïŒéãåŠçã®ããã°ã¬ã¹ããŒïŒ çµæ 7.䜿ãåãïŒWorkerã䜿ãã¹ããšãã»é¿ããæ¹ããããšã æ€èšŒããŒã«ã§åŠçè² è·ãâæž¬å®âããŠå¯èŠåãã WorkerãåããŠããåŠçã®äŸ WorkerãåããªãããŸãã¯æ
éã«ãªãåŠçã®äŸ 8.ããã«é«åºŠãªæŽ»çšïŒè»¢éå¯èœãªããžã§ã¯ãïŒTransferableïŒ 9.ãŸãšã å·çè
åèè³æã»åºå
ž åæš 1.èæ¯ã»ç®ç ã¢ãã³ãªWebã¢ããªã±ãŒã·ã§ã³ã§ã¯ããã©ãŠã¶äžã§å®è¡ãããããžãã¯ãè¥å€§åãç¶ããŠããŸããäžæ¹ã§ããŠãŒã¶ãŒã¯æ»ãããªã¢ãã¡ãŒã·ã§ã³ãšå³åº§ã®ã¬ã¹ãã³ã¹ãæåŸ
ããŠããã±ãŒã¹ãå€ãã§ãã æ¬èšäºã®ç®çã¯ã ã¡ã€ã³ã¹ã¬ãããUIå¿çã«äœ¿ãç¶ãã€ã€ãéãèšç®ãWorkeråŽãžå§ãã ãšããæ§æããå®éã«ãã©ãŠã¶ã§åãããªããäœæããå®è£
ã®åã身ã«ã€ããŠããã ãããšã§ãã æ¥åã®ã³ãŒãã§ãããã£ããã¡ã€ã³ã«èŒããåŠçãæ±ã蟌ãã ãŸãŸé²ãã èšæž¬ã§é·ãã¿ã¹ã¯ãã¯ã£ããèŠããŠãã Workerãžåãåºãããšããé çªã«ãªããã¡ã§ããåŸããçŽãã°ããã®ã§ãããææ»ããçºçãããšã©ãã©ãæéçãªäœè£ããªããªã£ãŠããã±ãŒã¹ãå€ããšæããŸããã ããããèšèšã®æ©ã段éã§ãã¡ã€ã³ã¯UIãšçãå¿çã«å¯ããããšããåæãå
±æããŠãããšæ¥œã«ãªãå Žé¢ããç§ããããŸã§çµéšããŠããæ¡ä»¶ã§ãå°ãªããããŸããã§ãããæ¬èšäºã¯ããã®åæã¥ããã®ããã®åå°ãšããŠæŽçããŸããã 2.ã¹ã¬ãããšã¯ OSãCPUã®å³å¯ãªå®çŸ©ã«èžã¿èŸŒããšé·ããªãããã ãã®èšäºãèªãããã®æå°éã®ã€ã¡ãŒãž ã ãã解説ããŸãã ç°¡æãªèª¬æãšãªããŸãã®ã§ããããŸã§ã€ã¡ãŒãžãšæããŠãã ããã ã¹ã¬ããïŒthreadïŒ åŠçã®æµããéã¶ äœæ¥ã©ã€ã³ ã®ãããªãã®ã§ããã¬ã¹ãã©ã³ã§ããã°ã調çãæäŸãé²ããããã®ãéè·¯ãã«è¿ãã€ã¡ãŒãžã§ãã ã·ã³ã°ã«ã¹ã¬ãã åæã«äœ¿ããéè·¯ã1æ¬ã ã ã§ãããã«ä»äºãé çªã«äžŠã¶ç¶æ
ã§ããJavaScriptã® ã¡ã€ã³ã¹ã¬ãã ã¯ãåºæ¬ãã®ã1æ¬ã®éè·¯ãäžã§åããŸãã ã¡ã€ã³ã¹ã¬ãã ãã©ãŠã¶ã§ã¯ããã®1æ¬ã®éè·¯ã®ãã¡ã ç»é¢ã®è¡šç€ºããŠãŒã¶ãŒæäœïŒã¯ãªãã¯ã»å
¥åãªã©ïŒãžã®åå¿ãæ±ã䞻圹ã®ã©ã€ã³ ãæãããšãå€ãã§ããæ¬æã§ã¯ãã¡ã€ã³ããšç¥ããŸãã ãã«ãã¹ã¬ããïŒè€æ°ã¹ã¬ããïŒ è€æ°ã®éè·¯ã䞊è¡ããŠäœ¿ãã ã€ã¡ãŒãžã§ããWeb Workerã¯ãã¡ã€ã³ãšã¯å¥ã®ã¹ã¬ããäžã§ã¹ã¯ãªãããå®è¡ã§ããŸãããã ã Workerããã¯DOMïŒDocument Object ModelïŒãçŽæ¥æäœã§ããªã ãªã©ãå¶çŽããããŸãã ãã®èšäºã§ã¯ã éãèšç®ãã¡ã€ã³ã®éè·¯ã«ãã£ãšçœ®ããšãç»é¢ã®æŽæ°ãåŸåãã«ãªããã ããWorkerãšããå¥ã®éè·¯ã«éãã ããšããã€ã¡ãŒãžãæã£ãŠèªã¿é²ããŠããã ããšãåŸã®å
容ãçè§£ããå©ãã«ãªããŸãã â»çšèªã®å³å¯ãªå®çŸ©ãããã©ãŠã¶å®è£
ããšã®å·®ç°ã¯ãåèè³æã®MDNã仿§æžã§ç¢ºèªããŠãã ããã 3.ãªããç»é¢ãæ¢ãŸããã®ãïŒã€ãã³ãã«ãŒãã®å¶çŽïŒ JavaScriptã®å®è¡ç°å¢ïŒã¡ã€ã³ã¹ã¬ããïŒã¯ã UIã®æç»æŽæ°ãšã¹ã¯ãªããã®å®è¡ããã²ãšã€ã®ãã¥ãŒã«ä¹ã£ãã¿ã¹ã¯ãšããŠé çªã«åŠçãã ã¢ãã«ãåºæ¬ã§ãïŒã€ãã³ãã«ãŒãïŒã ã¡ã€ã³ã¹ã¬ãããšã€ãã³ãã«ãŒãã®åèã€ã¡ãŒãžïŒã¿ã¹ã¯ãã¥ãŒããå®è¡ã»éãåŠçæã®ãããã¯ïŒ â»å³å
ã®ãrAFããšã¯ requestAnimationFrame() ã®ç¥ã§ãã äžæ®µã¯ãé çªåŸ
ã¡ã®ã¢ãã«ããäžæ®µã¯ã éã1ä»¶ã®éãã»ãã®ä»äºãå
ã«é²ã¿ã«ãã ãããšãã€ã¡ãŒãžããå³ã§ãïŒå³å¯ãªãã©ãŠã¶å
éšã¢ãã«ã§ã¯ãªãã説æçšã®ç¥å³ã§ãïŒã äŸãã°ãæ°ç§ãããã«ãŒãåŠçãã¡ã€ã³ã¹ã¬ããã§å®è¡ãããšããã®éã¯ãæ¬¡ã®æç»ãã«åãåã«é·ãã¿ã¹ã¯å æãçºçããŸããçµæãšããŠãã¢ãã¡ãŒã·ã§ã³ãã¯ãªãã¯å¿çãæ¢ãŸã£ãããã«èŠããŸãããããããããã¡ã€ã³ã¹ã¬ããã®ãããã¯ã§ãã å®éšïŒã¡ã€ã³ã¹ã¬ããããããã¯ããŠã¿ã 以äžã index.html ãšããŠä¿åããããŒã«ã«ã§éããŠè©ŠããŠãã ããïŒ file:// ã§ã¯ãªã ç°¡æHTTPãµãŒã㌠ã§é
ä¿¡ããæ¹ãæåãå®å®ããŸãïŒã <!doctype html> < html lang = "ja" > < head > < meta charset = "utf-8" /> < meta name = "viewport" content = "width=device-width,initial-scale=1" /> < title > ã¡ã€ã³ã¹ã¬ããããããã¯ããå®éš </ title > </ head > < body > < h2 > ã¡ã€ã³ã¹ã¬ããããããã¯ããå®éš </ h2 > < p id = "status" > åŸ
æ©äžã§ãããã¿ã³ã§éãåŠçãéå§ããŸãã </ p > < pre id = "log" style = "background:#f5f5f5;padding:8px;border-radius:4px;font-size:13px;" ></ pre > < div id = "box" style = "width:50px; height:50px; background:red; position:relative;" ></ div > < div > < small > ãã®ãã¿ã³ã§ã¯ããããšãéãåŠçããèµ°ãããŠãç»é¢ïŒã¡ã€ã³ã¹ã¬ããïŒãæ¢ãŸãæããäœæããŸãã < br /> èµ°ãèšç®ã¯2ã€ã§ãã < br /> < br /> 1) < b > 环ç©åïŒèšç®çµæã®è¡šç€ºïŒ </ b >< br /> 0ãn-1 ã®åèšïŒçޝç©åïŒã衚瀺ããŸãã < br /> < br /> 2) < b > è² è·ããããã«ãŒãïŒããªãŒãºäœæçšïŒ </ b >< br /> ãã¡ãã¯nåã«ãŒãããŠCPUã䜿ããã¡ã€ã³ã¹ã¬ãããå æãããããã®åŠçã§ãã < br /> < code > dummy </ code > ã¯ã«ãŒãäžã«æŽæ°ããäœæ¥çšã®å€æ°ã§ãå€ãã®ãã®ã«æå³ã¯ãããŸããã < br /> ãªãå
éšçã«ã¯32bitæŽæ°ãšããŠæŽæ°ããŠããããã衚瀺ã¯ç¬Šå·ãªãïŒ0ã4,294,967,295ïŒã«å€æããŠããŸãã < br /> < br /> </ small > </ div > < button id = "runBtn" type = "button" > éãåŠçãå®è¡ïŒããªãŒãºããŸãïŒ </ button > < script > const statusEl = document . getElementById ( "status" ) ; const logEl = document . getElementById ( "log" ) ; const runBtn = document . getElementById ( "runBtn" ) ; let pos = 0 ; function animate () { pos = ( pos + 2 ) % 300 ; document . getElementById ( "box" ) . style . left = pos + "px" ; requestAnimationFrame ( animate ) ; } animate () ; function fmtTime ( d ) { return ( d . toLocaleTimeString ( "ja-JP" , { hour12 : false }) + "." + String ( d . getMilliseconds ()) . padStart ( 3 , "0" ) ) ; } function heavyTask () { logEl . textContent = "" ; runBtn . disabled = true ; statusEl . textContent = "æ¬¡ã®æç»ãã¬ãŒã ã®ããšãéãåŠçãéå§ããŸãâŠ" ; requestAnimationFrame (() => { requestAnimationFrame (() => { const wallStart = new Date () ; statusEl . textContent = "å®è¡äžã§ãïŒã¡ã€ã³ã¹ã¬ããå æäžïŒãèµ€ãããã¯ã¹ã®åããšããã®æãæŽæ°ãããªãæéã«æ³šç®ããŠãã ããã" ; const t0 = performance . now () ; const n = 1_000_000_000 ; let dummy = 0 ; for ( let i = 0 ; i < n ; i ++ ) { dummy = ( dummy + ( i & 7 )) | 0 ; } const dummyU32 = dummy >>> 0 ; const result = ( BigInt ( n - 1 ) * BigInt ( n )) / 2 n ; const elapsed = Math . round ( performance . now () - t0 ) ; const wallEnd = new Date () ; statusEl . textContent = "éãåŠçãçµãããŸãããã¡ã€ã³ã¹ã¬ãããè§£æŸãããããã¯ã¹ãåã³åãåºããŸãã" ; logEl . textContent = "ãç»é¢ãã°ã\n" + "éå§æå»: " + fmtTime ( wallStart ) + "\n" + "çµäºæå»: " + fmtTime ( wallEnd ) + "\n" + "æèŠæé: " + elapsed + " ms\n" + "环ç©åã: " + result . toString () + "\n" + "ãããŒå€ïŒç¬Šå·ãªã32bitïŒ: " + dummyU32 ; runBtn . disabled = false ; }) ; }) ; } runBtn . addEventListener ( "click" , heavyTask ) ; </ script > </ body > </ html > çµæ ã¡ã€ã³ã¹ã¬ããããããã¯ããŠã¿ãã®åèã€ã¡ãŒãž ãã¿ã³ãæŒããšãèµ€ãããã¯ã¹ã®åããæ¢ãŸããŸãããããã¡ã€ã³ã¹ã¬ãããé·æéå æãããŠããç¶æ
ã§ããããããŠã å®è¡äžã¯ç»é¢äžéšã®ç¶æ
ã¡ãã»ãŒãžãæŽæ°ãããªã ïŒããªãŒãºããŠããïŒããšã çµäºåŸã«ãã°æ¬ãžéå§ã»çµäºæå»ãšæèŠæéããŸãšããŠè¡šç€ºããã ããšã確èªã§ããŸããã«ãŒãåæ°ãç«¯æ«æ§èœãªã©ããããæéã¯ç°å¢ããšã«ç°ãªããŸãã æèŠæéã«è¡šç€ºãããæéåã ããã¡ã€ã³ã¹ã¬ãããå æãããŠãããšããããšã«ãªããŸãã 4.Web Workerãšã¯äœã Web Workerã¯ãWebã¢ããªã±ãŒã·ã§ã³ã® ã¡ã€ã³å®è¡ã¹ã¬ãããšã¯å¥ã®ããã¯ã°ã©ãŠã³ãäžã§ã¹ã¯ãªãããåããä»çµã¿ ã§ãïŒå®è£
ã¯ãã©ãŠã¶äŸåã§ããããã¡ã€ã³ãšã¯å¥ã®äžŠè¡ã®å®è¡ã³ã³ããã¹ãããšããçè§£ã§åé¡ãããŸããïŒãéãèšç®ãWorkerã«éãããšãã¡ã€ã³åŽã¯ãããã¯ããã«ãããªãããŠãŒã¶ãŒã®æäœãç»é¢ã®åæç»ãé ã«é²ãããããªããŸããããããã¡ã€ã³ãšWorkerã®éã®ã¡ãã»ãŒãžåŠçãã®ãã®ãã¡ã€ã³ã¹ã¬ããã§æ±ããããéä¿¡ã®ããããã¯å¥ã®ããã«ããã¯ã«ãªãå¯èœæ§ããããæ³šæãå¿
èŠã§ãã å®è£
æã®äž»ãªã«ãŒã« ã¹ã¯ãªããã¯URLãšããŠæž¡ããŠèµ·åãã ïŒå¥ãã¡ã€ã«ã® .js ãæãã®ãäžè¬çã§ãããBlobããçæããURLã®ããã«ããã¡ã€ã«ãåããã«æž¡ãæ¹æ³ããããŸããèªã¿èŸŒãWorkerã¹ã¯ãªãã㯠åŒã³åºãå
ãšåäžãªãªãžã³ ã§ããããšãåºæ¬ã§ãã¯ãã¹ãªãªãžã³ã§èªã¿èŸŒãå Žåã¯è¿œå ã®æ¡ä»¶ïŒCORSãªã©ïŒãå¿
èŠã§ãã DOMæäœã¯äžå¯ ïŒWorkerã®å®è¡ç°å¢ã«ã¯ window ã document ã¯ãªããããŒãžã®DOMãçŽæ¥è§ŠããŸããïŒä»æ§äžãDedicated Workerã®ã°ããŒãã«ã¯ WorkerGlobalScope ç³»ã§ãïŒã ã¡ãã»ãŒãžã§ããåããã ïŒ postMessage ãš message ã€ãã³ãïŒãŸã㯠addEventListener('message',âŠ) ïŒã§ããŒã¿ãåãæž¡ãããŸãã äžèŠã«ãªã£ããçµäºãã ïŒéœåºŠWorkerãæ°èŠäœæããå Žåã¯ãåŠçå®äºåŸã« terminate() ãããã 1ã€ã®Workerã䜿ãåã èšèšã«ããŸãïŒæŸçœ®ãããšãªãœãŒã¹ãé£ãç¶ããŸãïŒã 5.ãå®è·µãWeb Workerãå°å
¥ããŠããªãŒãºãåããã å
ã»ã©ã®å®éšããWeb Workerã§æžãçŽããŸããåããã©ã«ãã« index.html ãš worker.js ã眮ããŠãã ããã ããã§è¡šãããã®ã¯ããéåžžã«éãCPUèšç®ïŒ= ã¡ã€ã³ã¹ã¬ãããå æããã¡ãªã«ãŒãïŒããWorkerãžéããããšã§ãã¡ã€ã³åŽã®ã¢ãã¡ãŒã·ã§ã³ïŒèµ€ãããã¯ã¹ïŒãæ¢ãŸããªãããšãã广ã§ãã ãã®äŸã§ç»é¢ã«åºããŠããæ°å€ïŒçޝç©åïŒã¯ã ãåŠçãæåŸãŸã§å®äºãããããšã確èªããããã®ç®å° ã§ãã çµéæéã§ã¯ãªãããšã«æ³šæããŠãã ããã Workerçšã®ã¹ã¯ãªããã¯ã HTMLã« <script src="worker.js"> ãšæžããŠèªã¿èŸŒã¿ãŸãã ãã¡ã€ã³åŽã® new Worker('worker.js') ã®ãšãã«ããã©ãŠã¶ãå¥ã¹ã¬ããçšãšã㊠worker.js ãååŸã»å®è¡ããŸãïŒã¡ã€ã³çšã® <script> ã§èªããšãWorkeråãã³ãŒããã¡ã€ã³ã¹ã¬ããã§åããŠããŸãæå³ãšãããŸãïŒã ã¹ããã1ïŒ worker.js // éãã«ãŒããæåŸãŸã§åãåã£ããå®äºã®èšŒæ ããšããŠå€ãã¡ã€ã³ãžè¿ãã self .onmessage = function () { const n = 1_000_000_000 ; // ãããŒèšç®ïŒCPUã䜿ãïŒ32bitã§åãç¶ããŠâèµ°ã£ãçè·¡âãæ®ãïŒ let dummy = 0 ; for ( let i = 0 ; i < n ; i ++ ) { dummy = ( dummy + ( i & 7 )) | 0 ; } const dummyU32 = dummy >>> 0 ; // çµæã®ç®å°ïŒ0ãn-1 ã®åèšã BigInt ã§å³å¯ã«ïŒ const sum = ( BigInt ( n - 1 ) * BigInt ( n )) / 2 n ; self . postMessage ({ n , sum : sum . toString () , dummy : dummyU32 }) ; } ; ã¡ã€ã³ã«å±ãå€ïŒ äžèšã® postMessage(result) ã®åŒæ°ããã¡ã€ã³åŽã® message ãã³ãã©ã§ã¯ e.data ãšããŠåãåããŸãã ã¹ããã2ïŒ index.html ïŒã¡ã€ã³ã¹ã¬ããåŽïŒ å
ã»ã©ã®å®éšã³ãŒãã®ãã¡ã ãã¿ã³ãæŒãããšãã®åŠçïŒéãã«ãŒãéšåïŒã ã ãWorkeråŒã³åºãã«å·®ãæ¿ããäŸã§ãããã¿ã³é£æã§Workerã墿®ããªãããã ååã®Workerã¯çµäºããŠãã æ°ããèµ·åããŠããŸãããã°æ¬ã«åºã e.data ã¯ã ã¹ããã1ã® result ãšåãå€ ã§ãã <!doctype html> < html lang = "ja" > < head > < meta charset = "utf-8" /> < meta name = "viewport" content = "width=device-width,initial-scale=1" /> < title > Web Workerã§èšç®ãéãã </ title > </ head > < body > < h2 > Web Workerã§èšç®ãéãã </ h2 > < p id = "status" > ãã¿ã³ã§Workerã«èšç®ãäŸé Œã§ããŸãã </ p > < pre id = "log" style = "background:#f5f5f5;padding:8px;border-radius:4px;font-size:13px;min-height:3em;" > ïŒçµæã¯ããã«è¡šç€ºãããŸãïŒ </ pre > < div > < small > ãã®ãã¿ã³ã§ã¯ãéãèšç®ãWorkerã«ä»»ããŠãç»é¢ïŒã¡ã€ã³ã¹ã¬ããïŒã®æç»ãæ¢ãŸãã«ãããªãããšãäœæããŸãã < br /> Workerãè¿ãå€ã¯2ã€ã§ãã < br /> < br /> 1) < b > 环ç©åïŒèšç®çµæã®è¡šç€ºïŒ </ b >< br /> 0ãn-1 ã®åèšïŒçޝç©åïŒã衚瀺ããŸãã < br /> < br /> 2) < b > ãããŒå€ïŒç¬Šå·ãªã32bitïŒ </ b >< br /> WorkeråŽã§è² è·ããããã«ãŒãã®äžã§æŽæ°ããŠããäœæ¥çšã®å€ã§ãïŒå€ãã®ãã®ã«æå³ã¯ãããŸããïŒã < br /> </ small > </ div > < div id = "box" style = "width:50px; height:50px; background:red; position:relative;" ></ div > < br /> < button type = "button" id = "runBtn" > éãåŠçãWorkerãžïŒæç»ã¯åãç¶ããæ³å®ïŒ </ button > < script > const statusEl = document . getElementById ( "status" ) ; const logEl = document . getElementById ( "log" ) ; const runBtn = document . getElementById ( "runBtn" ) ; let pos = 0 ; function animate () { pos = ( pos + 2 ) % 300 ; document . getElementById ( "box" ) . style . left = pos + "px" ; requestAnimationFrame ( animate ) ; } animate () ; let myWorker = null ; function heavyTask () { logEl . textContent = "" ; runBtn . disabled = true ; statusEl . textContent = "WorkerãžåŠçãéããŸãããèšç®äžã¯ç»é¢ã®æç€ºã«åŸããèµ€ãããã¯ã¹ã®åããèŠãŠãã ããã" ; if ( myWorker ) { myWorker . terminate () ; } try { myWorker = new Worker ( "worker.js" ) ; } catch ( err ) { statusEl . textContent = "Workerãèµ·åã§ããŸããã§ããã" ; logEl . textContent = "èµ·åãšã©ãŒ: " + ( err && err . message ? err . message : String ( err )) + "\n" + "ïŒworker.js ã®ãã¹ãhttp:// ã§éããŠãããããã©ãŠã¶èšå®ãªã©ã確èªããŠãã ããïŒ" ; myWorker = null ; runBtn . disabled = false ; return; } myWorker . onmessage = function ( e ) { // worker.js 㯠{ sum, dummy } ã®åœ¢ã§è¿ãæ³å®ã§ãããã³ããã®ãºã¬çã§åœ¢ãéãå ŽåãããåŸãã®ã§ // 衚瀺ã¯é²åŸ¡çã«æ±ããŸãã const data = e . data ; const sum = data && typeof data === "object" ? ( data . sum ?? data . result ) : data ; const dummy = data && typeof data === "object" ? data . dummy : undefined ; const endTime = new Date () . toLocaleTimeString ( "ja-JP" , { hour12 : false , }) ; statusEl . textContent = "WorkerããçµæãåãåããŸããïŒ" + endTime + "ïŒã" ; logEl . textContent = "环ç©åïŒ0ã999,999,999 ã®åèšïŒ: " + sum + "\n" + "ãããŒå€ïŒç¬Šå·ãªã32bitïŒ: " + ( dummy ?? "ïŒæªååŸïŒ" ) ; myWorker . terminate () ; myWorker = null ; runBtn . disabled = false ; } ; myWorker . onerror = function ( e ) { statusEl . textContent = "Workerã®èªã¿èŸŒã¿ããŸãã¯å®è¡ã§ãšã©ãŒãçºçããŸããã" ; logEl . textContent = "ãšã©ãŒ: " + ( e && e . message ? e . message : "ïŒè©³çŽ°äžæïŒ" ) + "\n" + "ïŒworker.js ãååšããªãããã¹ãéããhttp:// ã§éããŠããªããåäžãªãªãžã³ã§ãªããªã©ã®å¯èœæ§ããããŸãïŒ" ; myWorker . terminate () ; myWorker = null ; runBtn . disabled = false ; } ; myWorker . onmessageerror = function () { statusEl . textContent = "Workerãšã®ã¡ãã»ãŒãžã®åãæž¡ãã«å€±æããŸããã" ; logEl . textContent = "messageerror: Workerããåãåã£ãããŒã¿ã埩å
ã§ããŸããã§ããã" ; myWorker . terminate () ; myWorker = null ; runBtn . disabled = false ; } ; myWorker . postMessage ( null ) ; } runBtn . addEventListener ( "click" , heavyTask ) ; </ script > </ body > </ html > çµæ Web Workerãå°å
¥ããŠããªãŒãºãåãããã®åèã€ã¡ãŒãž å
ã»ã©ãšã¯ç°ãªãããã¿ã³æŒäžäžãèµ€ãããã¯ã¹ã®ã¢ãã¡ãŒã·ã§ã³ãåãç¶ããæ°ç§åŸã« ãã°æ¬ãžçޝç©åïŒ0ã999,999,999ã®åèšïŒ ã衚瀺ãããŸããç¶æ
ã¡ãã»ãŒãžã§ãéä¿¡äžã»åä¿¡æžã¿ã®æµãã远ããŸããæåã¯ãã©ãŠã¶å®è£
ã»CPUè² è·ã»ä»ã¿ãã®ç¶æ³ã«ããå€ããããã å¯èœã§ããã°æå
ã§ç¢ºèª ããŠãã ããã è£è¶³ïŒã¡ã€ã³ãšWorkerã®ããåãã®ã³ã¹ã ã¡ã€ã³ããWorkerãžããŒã¿ãæž¡ãåŠçã§ã¯ãååãšã㊠ããŒã¿ã®è€è£œ ãçºçããŸãã巚倧ãªãªããžã§ã¯ããé »ç¹ã«åŸåŸ©ããããšãéä¿¡ãã®ãã®ãããã«ããã¯ã«ãªãããšããããããæ³šæããŠãã ãããã³ããŒãé¿ããé«åºŠãªææ®µã¯æ¬èšäºã®åŸåã§ç޹ä»ããŸãã 6.ãããããŠãŒã¹ã±ãŒã¹ãšç°¡æã³ãŒãïŒäœãèµ·ããããã»ããã§çè§£ããïŒ ãããã㯠1ãã¡ã€ã«ã§è©Šãã äŸã§ãã new Worker(URL.createObjectURL(blob)) ã«ãããå¥ãã¡ã€ã«ã眮ããã«Workerã¹ã¯ãªãããæž¡ããŠããŸãïŒæ¬çªã§ã¯ãã¡ã€ã«åå²ããã³ãã©é£æºãäžè¬çã§ãïŒã åã³ãŒãã®çŽåŸã«ã ãã©ãŠã¶äžã§ã©ãèŠãããã»äœãåŸãããã ããŸãšããŠããŸãã ãã¡ã€ã«ãå¢ãããããªããšãã« Blob ããWorkerãèµ·åããã®ã¯ãå人çã«ãæç¿ãåãã§éå®ããŠããŸããæ¬çªãšã¯èšèšãç°ãªãç¹ã¯åŸè¿°ã®éãã§ãããããŸãæåãæŽããã«ã¯åããŠããŸãã ã±ãŒã¹1ïŒå転ãããåãç¶ããUIããšéãåŠçïŒã«ãŒãïŒ éãCPUã«ãŒãã¯æ¬æ¥ã¡ã€ã³ãå æããããããšã¯ãããŸã§ã®å
容ã§ãäŒãããŠããŸããããããã§ã¯ å転ããèµ€ãåè§ ã眮ãã ãæ¢ãŸããªãïŒã¡ã€ã³ã®æç»åŠçãçããŠããã ããšãäžç®ã§ç¢ºèªã§ããããã«ç»é¢äžã®ãçµéæéïŒã¡ã€ã³ïŒãã¯ãã¡ã€ã³ãåããŠããéã ãå¢ãç¶ããããã«ããŠããŸãã WorkeråŠçå®äºæã«åºã å·šå€§ãªæ°å€ïŒçޝèšïŒ ã¯ãã«ãŒããæåŸãŸã§åãåã£ã å®äºã®ç®å° ã§ãã <!doctype html> < html lang = "ja" > < head > < meta charset = "utf-8" /> < meta name = "viewport" content = "width=device-width,initial-scale=1" /> < title > ã±ãŒã¹1ïŒå転UIãšéãåŠçïŒWorkerïŒ </ title > </ head > < body > < h3 > åè»¢ãæ¢ãŸããªãããæ³šç®ããŠã¿ãŠãã ãã </ h3 > < p > èµ€ãåè§ã¯ < code > requestAnimationFrame </ code > ã§å転ããŠããŸãã </ p > < div > < small > ãã®äŸã¯ãéãèšç®ãWorkerã«ä»»ããŠããã¡ã€ã³åŽã®æç»ïŒå転ïŒããæ¢ãŸãã«ããããšãäœæããããã®ãã®ã§ãã < br /> < br /> - 確èªãããã€ã³ã: < b > èµ€ãåè§ã®å転 </ b > ãš < b > çµéæé </ b > ãæ¢ãŸããªãã < br /> - Workerãè¿ãå€: < b > 环ç©åïŒèšç®çµæïŒ </ b > ãš < b > ãããŒå€ïŒç¬Šå·ãªã32bitïŒ </ b >< br /> â»ãããŒå€ã¯è² è·ããããã«ãŒãäžã«æŽæ°ããŠããäœæ¥çšã®å€ã§ãå€ãã®ãã®ã«æå³ã¯ãããŸããã < br /> </ small > </ div > < div id = "spin" style = "width:48px;height:48px;background:#d33;margin:12px 0;transform-origin:center center;" ></ div > < p > çµéæéïŒã¡ã€ã³ïŒ: < span id = "tick" > 0 </ span > msïŒãã¬ãŒã ãé²ãã»ã©å¢ããŸãïŒ </ p > < p id = "st" > åŸ
æ©äž </ p > < button type = "button" id = "run" > Workerã§éãã«ãŒãïŒçŽ2åã¹ãããïŒ </ button > < script > const spinEl = document . getElementById ( "spin" ) ; const tickEl = document . getElementById ( "tick" ) ; const st = document . getElementById ( "st" ) ; const runBtn = document . getElementById ( "run" ) ; let deg = 0 ; ( function spinLoop () { deg = ( deg + 4 ) % 360 ; spinEl . style . transform = "rotate(" + deg + "deg)" ; requestAnimationFrame ( spinLoop ) ; })() ; let t0 = performance . now () ; ( function tickLoop () { tickEl . textContent = String ( Math . round ( performance . now () - t0 )) ; requestAnimationFrame ( tickLoop ) ; })() ; runBtn . onclick = () => { runBtn . disabled = true ; st . textContent = "Workerã§èšç®äžâŠïŒãã®éãå転ãšçµéè¡šç€ºãæ¢ãŸããªãã¯ãïŒ" ; const src = [ "self.onmessage = () => {" , " const n = 200000000;" , " let dummy = 0;" , " for (let i = 0; i < n; i++) dummy = (dummy + (i & 7)) | 0;" , " const dummyU32 = dummy >>> 0;" , " const sum = (BigInt(n - 1) * BigInt(n)) / 2n;" , " self.postMessage({ steps: n, sum: sum.toString(), dummy: dummyU32 });" , "};" , ] . join ( "\n" ) ; const w = new Worker ( URL . createObjectURL ( new Blob ([ src ] , { type : "application/javascript" }) , ) , ) ; w . onmessage = ( e ) => { st . textContent = "å®äºïŒWorkerïŒ: ã¹ãããæ° " + e . data . steps + " ã®çޝç©å = " + e . data . sum + "ïŒãããŒå€ã»ç¬Šå·ãªã32bit: " + e . data . dummy + "ïŒ" ; runBtn . disabled = false ; w . terminate () ; } ; w . onerror = ( e ) => { st . textContent = "Workerãšã©ãŒ: " + e . message ; runBtn . disabled = false ; w . terminate () ; } ; w . postMessage ( null ) ; } ; </ script > </ body > </ html > çµæ ã±ãŒã¹1ïŒå転ãããåãç¶ããUIããšéãåŠçïŒã«ãŒãïŒã®åèã€ã¡ãŒãž ãã®ã±ãŒã¹ã§ã¯ããã¿ã³æŒäžåŸã èµ€ãåè§ã®å転ãéåããªã ã®ã§ããéãåŠçããWorkerãžéããããšãã®äœæãæŽã¿ãããã§ãã ãçµéæéïŒã¡ã€ã³ïŒã ãæ¢ãŸããå¢ãç¶ããã®ã¯ãã¡ã€ã³ãã€ãã³ãã«ãŒããšæç»ãé²ãç¶ããŠãã蚌æ ãšãªããŸãã æåŸã«è¡šç€ºããã 巚倧ãªçŽ¯èš ã¯ãçŽ2åã¹ãããåã®ã«ãŒããçµããçµæã® å®äºã®ç®å° ã§ããç«¯æ«æ§èœã«ããåŸ
ã¡æéã¯å€ãããŸããé·ãããå Žåã¯Workerå
ã® n ãå°ãã調æŽããŠãã ããã ã±ãŒã¹2ïŒé²æã®é次éç¥ïŒéãåŠçã®ããã°ã¬ã¹ããŒïŒ Workerå
ã§ã«ãŒããåºåãã äœïŒ
é²ãã ã ãäœåºŠãã¡ã€ã³ãžéããç»é¢äžã®ããã°ã¬ã¹ããŒã ããæŽæ°ããŠã¿ãŸãã <!doctype html> < html lang = "ja" > < head > < meta charset = "utf-8" /> < meta name = "viewport" content = "width=device-width,initial-scale=1" /> < title > ã±ãŒã¹2ïŒé²æã®é次éç¥ïŒWorkerïŒ </ title > </ head > < body > < div > < small > ãã®äŸã¯ãWorkerãããããŸäœ%ãŸã§é²ãã ãããäœåãåãåããããã°ã¬ã¹ããŒã ããæŽæ°ãããµã³ãã«ã§ãã < br /> èŠã©ããã¯ãéãèšç®äžã§ã < b > ããŒã段éçã«äŒžã³ã </ b > ç¹ã§ãã < br /> â»æåŸã«è¿ã£ãŠãã < code > work </ code > ã¯ãWorkeråŽã®éãã«ãŒãã§äœã£ããæçµçãªèšç®å€ãã§ãã < br /> åŠçæéã§ã¯ãªãããããŸã§ãæåŸãŸã§èšç®ãèµ°ãåã£ããããšã確èªããããã«è¡šç€ºããŠããŸãïŒäžèº«ãè§£éããå¿
èŠã¯ãããŸããïŒã < br /> </ small > </ div > < div id = "bar" style = "height:12px;width:0;background:#06c;" ></ div > < p id = "pct" > 0% </ p > < button type = "button" id = "run" > Workerã§é²æä»ãåŠç </ button > < script > const runBtn = document . getElementById ( "run" ) ; runBtn . onclick = () => { if ( runBtn . disabled ) return; runBtn . disabled = true ; document . getElementById ( "bar" ) . style . width = "0%" ; document . getElementById ( "pct" ) . textContent = "0%" ; const src = ` self.onmessage = () => { const steps = 5; let work = 0; for (let s = 1; s <= steps; s++) { let x = 0; for (let i = 0; i < 80000000; i++) x += i % 7; work = x; self.postMessage({ progress: Math.round((s / steps) * 100) }); } self.postMessage({ done: true, work }); }; ` ; const w = new Worker ( URL . createObjectURL ( new Blob ([ src ] , { type : "application/javascript" }) , ) , ) ; w . onmessage = ( e ) => { if ( "progress" in e . data ) { const p = e . data . progress ; document . getElementById ( "bar" ) . style . width = p + "%" ; document . getElementById ( "pct" ) . textContent = p + "%" ; } if ( e . data . done ) { document . getElementById ( "pct" ) . textContent += " ïŒå®äº / work=" + e . data . work + "ïŒ" ; runBtn . disabled = false ; w . terminate () ; } } ; w . onerror = function () { document . getElementById ( "pct" ) . textContent += " ïŒWorkerãšã©ãŒïŒ" ; runBtn . disabled = false ; w . terminate () ; } ; w . postMessage ( null ) ; } ; </ script > </ body > </ html > çµæ ã±ãŒã¹2ïŒé²æã®é次éç¥ïŒéãåŠçã®ããã°ã¬ã¹ããŒïŒã®åèã€ã¡ãŒãž éãããŒã®å¹
ã 20% â 40% â ⊠â 100% ã®ããã«æ®µéçã«äŒžã³ãïŒWorkerãã鲿ã¡ãã»ãŒãžãå±ããã³ã«æŽæ°ïŒã å®äºåŸã«ãïŒå®äºïŒããä»ããå
åŽã®ã«ãŒãåæ°ã¯ç«¯æ«ã«åãããŠèª¿æŽããŠãã ããïŒè»œããããšäžç¬ã§çµãããéããããšåŸ
ã¡æéãé·ããªããŸãïŒã å®è¡äžã¯ãã¿ã³ãç¡å¹åããã飿ã§Workerãè€æ°èµ·åãã«ããããã«ããŠããŸãã è£è¶³ïŒ 鲿éç¥ã现ãããããããšãã¡ã€ã³ãšWorkerã®éã®ããåãã®åæ°ãå¢ããããã£ãŠãªãŒããŒãããã«ãªãããšããããŸããå®åã§ã¯äžå®ééã»äžå®ãã£ã³ã¯ããšã«éãã®ãç¡é£ã§ãã 7.䜿ãåãïŒWorkerã䜿ãã¹ããšãã»é¿ããæ¹ããããšã æ€èšŒããŒã«ã§åŠçè² è·ãâæž¬å®âããŠå¯èŠåãã ãã©ãŠã¶ã®æ€èšŒããŒã«ã䜿ããšåŠçè² è·ãå¯èŠåããããšãã§ããäžå±€ã€ã¡ãŒãžãæã¡ãããã§ãã DevToolsãéã â Performance DevToolsãéã â Performance èšé²éå§ïŒRecordïŒâ ãµã³ãã«ã®ãã¿ã³ãæŒããŠéãåŠçãèµ°ããã â 忢 èšé²éå§ïŒRecordïŒâ ãµã³ãã«ã®ãã¿ã³ãæŒããŠéãåŠçãèµ°ããã â 忢 ã¿ã€ã ã©ã€ã³äžã§ãã¡ã€ã³ã¹ã¬ããã® Long TaskïŒé·ãã¿ã¹ã¯ïŒ ããæç»ïŒFramesïŒã®è©°ãŸãæ¹ã確èªãã ã¿ã€ã ã©ã€ã³äžã§ãWorkeråŠçã確èªã§ãã ãã¡ã€ã³ã§å®è¡ããå ŽåããšãWorkerã«éãããå Žåãã§ãã¡ã€ã³ã¹ã¬ããäžã®é·ãå¡ã®åºæ¹ãå€ããã®ããã€ã³ãã§ãã ãããŸã§ã§Workerã®äŸ¿å©ãªåãã«ã€ããŠç޹ä»ããŠããŸãããã ãäœã§ãWorkerã«æããã°ãããããã§ã¯ãããŸããã ã©ããªæ©èœã«ãåãäžåãããããWorkerãäŸå€ã§ã¯ãããŸããã ããããäžéšã玹ä»ããŸãã WorkerãåããŠããåŠçã®äŸ æ°åäžä»¶ä»¥äžã®é
åã®ãã£ã«ã¿ãªã³ã°ã»éèšã»å€æ ç»åããã€ããªã®å å·¥ãæå·åŠçãªã©ãDOMã«è§Šããªãéãèšç® ã€ã³ã¿ã©ã¯ãã£ããªUIã®å¿çæ§ãåªå
ããã¡ã€ã³ã¹ã¬ããã®å ææéãçãä¿ã¡ããå Žé¢ WorkerãåããªãããŸãã¯æ
éã«ãªãåŠçã®äŸ æ°ããªç§ã§çµãã軜ãèšç®ïŒèµ·åãšã¡ãã»ãŒãžã®ãªãŒããŒãããã®æ¹ã倧ãããªãããšãããïŒ DOMãé »ç¹ã«æŽæ°ããåŠçïŒWorkerããã¯çŽæ¥æäœã§ããªããããçµæãã¡ã€ã³ãžæ»ããŠåæ ãå¿
èŠïŒ 巚倧ãªããŒã¿ãé«é »åºŠã§åŸåŸ©ãããåŠçïŒã³ããŒãŸãã¯è»¢éæŠç¥ã®èšèšãå¿
é ïŒ 8.ããã«é«åºŠãªæŽ»çšïŒè»¢éå¯èœãªããžã§ã¯ãïŒTransferableïŒ å·šå€§ãªãã€ããªããŒã¿ïŒåä»ãé
åã®è£åŽã®ãããã¡ãªã©ïŒãWorkerãžéãå Žåãããã©ã«ãã®è€è£œã§ã¯ã¡ã¢ãªãšæéãæ¶è²»ããŸããã¡ãã»ãŒãžãéãAPIã®ãªãã·ã§ã³ã§è»¢éãªã¹ããæž¡ããšããããã¡ã®æææš©ãWorkeråŽãžç§»ããã³ããŒãé¿ããããå ŽåããããŸãïŒè»¢éåŸãã¡ã€ã³ã¹ã¬ããåŽã§ã¯ãã®ãããã¡ã¯å©çšã§ããªããªããŸãïŒã é«åºŠãªæ©èœãšãªããããããã§ã¯ã»ãã®å°ãã ããäžéšã玹ä»ããŸãã // ã¡ã€ã³åŽïŒäŸïŒ100MBã®ãããã¡ã転éïŒ const buffer = new Uint8Array ( 1024 * 1024 * 100 ) . buffer ; myWorker . postMessage ({ type : 'binary' , payload : buffer } , [ buffer ]) ; // 転éåŸãã¡ã€ã³ã¹ã¬ããåŽã§ã¯ buffer ã¯ãã¿ãããããè§Šããªãæ³å®ã«ãªã WorkeråŽã§ã¯ãã¡ã€ã³ãéã£ãããŒã¿ã®äžèº«ãšããŠåãåããŸããçšéã«å¿ããŠè€æ°ã¹ã¬ããã§åãã¡ã¢ãªãå
±æããä»çµã¿ãæ€èšããéããããŸããã ãµã€ãå
šäœã®ã»ãã¥ãªãã£èšå®ïŒã¯ãã¹ãªãªãžã³éé¢ãªã©ïŒãå¿
èŠã«ãªã£ãŠãã ããããŸãã¯åäžãªãªãžã³ã§ããŸããŸãªäœ¿ãæ¹ã暡玢ããŠã¿ãã®ãè¯ããšæããŸãã 9.ãŸãšã Web Workerã䜿ããšãJavaScriptã®ã·ã³ã°ã«ã¹ã¬ãããšããå¶çŽã®ããšã§ããã¡ã€ã³ã¹ã¬ããã®å ææéãæžãããUXãšéãèšç®ã®äž¡ç«ãçãããããªããŸãã ããã«ããã¯ã®ç¹å® ïŒãã©ãŠã¶ã®éçºè
ããŒã«ã§ãé·ãã¿ã¹ã¯ãã©ãã§çºçããŠããããææ¡ããïŒæ§èœåæã®ç»é¢ããèšæž¬çšã®APIãäœ¿ãæ¹æ³ããããŸãïŒã çŽç²ãªèšç®ã®åé¢ ïŒç»é¢ã®èŠçŽ ãçŽæ¥ããããªãåŠçãWorkerãžåãåºãã ã¡ãã»ãŒãžèšèš ïŒããåãããããŒã¿ã®ãµã€ãºãšé »åºŠãæããå¿
èŠãªãåŸè¿°ã®ã転éãã«ããæé©åã§è»¢éã³ã¹ããäžããã ããã©ãŠã¶åãJavaScriptã¯éãåŠçã«åããªãããšèšãããã¡ã§ãããWeb Workerã®ãããªæšæºæ©èœãé©åã«çµã¿åãããã°ãããã³ããšã³ãã§ãå®çšçãªã¢ããªã±ãŒã·ã§ã³ãæ§ç¯ã§ããŸãã ã«ãŒãåæ°ã¯ç«¯æ«ã®æ§èœãªã©ã§äœæãå€ãããŸããåãããŠã¿ãŠãå·®ãåããã«ããããšæããããæ¬èšäºã®3ç¯ç®ã®ãããã¯å®éšã ãã«ãŒããååã«ããŠã¿ããã5ç¯ç®ã®ãµã³ãã«ã«ãŠWorkeråŽã¯ãã®ãŸãŸããšãã£ã çåŽã ãç·šéããŠã¿ããªã©ã®æ¯èŒ ã詊ããŠã¿ãŠãã ãããç§ãèšäºãæŽãããšãã¯ãäœåºŠããã®æ¯èŒã«ç«ã¡è¿ã£ãŠæèšãçŽããŸãããéçºè
ããŒã«ã®æ§èœããã«ãéãããŸãŸèªã¿è¿ããšãé·ãã¿ã¹ã¯ã®èŠãæ¹ãã€ã¡ãŒãžãããããªãã¯ãã§ããæ¯é詊ããŠã¿ãŠãã ããã å·çè
äžå· æåïŒNTTè¥¿æ¥æ¬ ããžã¿ã«é©æ°æ¬éš ããžã¿ã«æ¹é©æšé²éšæå±ïŒ NTTè¥¿æ¥æ¬ã®Webã¢ããªã±ãŒã·ã§ã³ã®éçºã»éå¶ã«åŸäºã 奜ããªæè¡ã¹ã¿ãã¯ïŒTypeScript, Vue.js, GraphQL, Laravel åèè³æã»åºå
ž æ¬èšäºãå·çããã«ãããã以äžã®ãµã€ãã»è³æãåèã«ããŸããã MDN Web Docs â Web Workers API MDN Web Docs â Worker MDN Web Docs â postMessage HTML Living Standard â postMessage with transfer WHATWG HTML â Safe passing of structured data åæš ãJavaScriptãã¯ãOracle Corporation ããã³ãã®åäŒç€Ÿã®ç±³åœããã³ãã®ä»ã®åœã«ãããåæšãŸãã¯ç»é²åæšã§ãã ãGoogle Chromeãã¯ãGoogle LLC ã®åæšã§ãã èšèŒã®ãã®ä»ã®äŒç€Ÿåã»è£œååã¯ãããããå瀟ã®åæšãããã¯ç»é²åæšã§ãã
ããã«ã¡ã¯ãé§
ã¡ã¢ïŒéçºããŒã ãšã³ãžãã¢ã® id:hayayanai ã§ãïŒ æè¿ã VoidZero ãã Vite+ ããªãªãŒã¹ãããŸããã Vite+ 㯠Vite 8ãVitestãOxlintãOxfmt ãªã©ãçµ±åãããWeb ã®ããã®çµ±åããŒã«ãã§ãŒã³ãã§ãã é§
ã¡ã¢ïŒã¯çŸåš Vue + Vite 7 + Vitest + ESLintïŒããŒã ç¬èªã«ãŒã«æãïŒ+ Prettier + Stylelint ã§éçºãããŠãããVite+ ã®ããŒã«ã¯ãŸã å°å
¥ããŠããŸããã AI ã§éçºãé«éåããçŸä»£ãæ°ååéããšè¬³ã Vite+ ã®ããŒã«ãã§ãŒã³ã¯æ°ã«ãªããŸãã ãã ãããããåããŒã«ãã©ãããã Vue 察å¿ããŠããã®ããã©ãèšå®ããã°è¯ãã®ããããããªãã£ãã®ã§ããã³ãã¬ã䜿ã£ãŠç¢ºèªããããšã«ããŸããã Vite+ çµç±ã® vp create vue ãšåŸæ¥ã® pnpm create vue@latest ã§çæããããããžã§ã¯ãèšå®ãæ¯èŒããVue ãããžã§ã¯ãç¹æã®æ³šæç¹ãæŽçããŸãã æ€èšŒç°å¢ ãããžã§ã¯ãã®äœæ Vite+ çµç± åŸæ¥ã® create-vue çæãããèšå®ãã¡ã€ã«ã®æ¯èŒ Vite+ ãããžã§ã¯ãã®æ§æ åŸæ¥ã® create-vue ãããžã§ã¯ãã®æ§æ å
±é: eslint.config.ts å
±é: Lint å®è¡é Linter æ¯èŒ: Oxlint vs ESLint æ€èšŒçšã³ã³ããŒãã³ã Oxlint ã®çµæ ESLint ã®çµæ CSS/Style Lint ã«ã€ã㊠åãã§ãã¯ã®éã ãã¹ã Formatter æ¯èŒ: Oxfmt vs Prettier Vue SFC ã®ãã©ãŒãããå¯Ÿå¿ å
šäœæ¯èŒè¡š ãŸãšã Linter åãã§ã㯠Formatter CSS Lint æ€èšŒç°å¢ vp v0.1.16 (Vite+) create-vue v3.22.2 (pnpm create vue@latest) Node.js v24.14.1 pnpm v10.33.0 ãããžã§ã¯ãã®äœæ Vite+ çµç± vp create vue vue-viteplus â Which package manager would you like to use? pnpm â pnpm@10.33.0 installed â Which agents are you using? Claude Code â Which editor are you using? VSCode â Set up pre-commit hooks to run formatting, linting, and type checking with auto-fixes? Yes Generating project⊠Running: pnpm dlx create-vue â Vue.js - The Progressive JavaScript Framework â â Project name (target directory): â vue-viteplus â â Use TypeScript? â Yes â â Select features to include in your project: â Vitest (unit testing), Linter (error prevention), Prettier (code formatting) â â Select experimental features to include in your project: â Replace Prettier with Oxfmt â â Skip all example code and start with a blank Vue project? â No Scaffolding project in /Users/yanai/project/vue-viteplus... â â Done. â Merged vue-viteplus/.oxlintrc.json into vue-viteplus/vite.config.ts â Merged vue-viteplus/.oxfmtrc.json into vue-viteplus/vite.config.ts Wrote agent instructions to CLAUDE.md Rewrote imports in 4 files â Merged staged config into vue-viteplus/vite.config.ts â Dependencies installed â Code formatted â Scaffolded vue-viteplus åºåãèŠããš Running: pnpm dlx create-vue ãšãããå
éšã§ create-vue ãåŒãã§ããããšãåãããŸããcreate-vue ã§ãããžã§ã¯ããçæããåŸã«ãVite+ ã以äžã®å€æããããŠããŸãã .oxlintrc.json â vite.config.ts ã® lint ãããã¯ã«ããŒãž .oxfmtrc.json â vite.config.ts ã® fmt ãããã¯ã«ããŒãž vite / vitest ã® import ãã¹ã vite-plus ã«æžãæã pre-commit ããã¯ïŒ vp staged ïŒã®èšå®ãçµ±å ã€ãŸã vp create vue 㯠create-vue ã®ã©ãããŒã§ãçæç©ã Vite+ åãã«å€æããŠããã ãã®ããã§ãã åŸæ¥ã® create-vue pnpm create vue@latest vue-create-vue â Vue.js - The Progressive JavaScript Framework â â Use TypeScript? â Yes â â Select features to include in your project: â Vitest (unit testing), Linter (error prevention), Prettier (code formatting) â â Select experimental features to include in your project: â none â â Skip all example code and start with a blank Vue project? â No Scaffolding project in /Users/yanai/project/vue-create-vue... â â Done. ãã¡ãã¯åŸæ¥éãã®ã·ã³ãã«ãª Scaffold ã§ããcreate-vue åŽã§ããReplace Prettier with Oxfmtãã®éžæè¢ãåºãŸãããä»å㯠Oxfmt ãšã®æ¯èŒã®ãã Prettier ãéžã³ãŸããã çæãããèšå®ãã¡ã€ã«ã®æ¯èŒ 以éã®ã³ãŒããããã¯ã¯äž»èŠéšåã®æç²ã§ãã Vite+ ãããžã§ã¯ãã®æ§æ package.json { " scripts ": { " dev ": " vp dev ", " build ": " run-p type-check \" build-only {@} \" -- ", " build-only ": " vp build ", " type-check ": " vue-tsc --build ", " test:unit ": " vp test ", " lint ": " run-s lint:* ", " lint:oxlint ": " vp lint . --fix ", " lint:eslint ": " eslint . --fix --cache ", " format ": " vp fmt src/ " } , " devDependencies ": { " eslint ": " ^10.1.0 ", " eslint-plugin-vue ": " ~10.8.0 ", " eslint-plugin-oxlint ": " ~1.57.0 ", " eslint-config-prettier ": " ^10.1.8 ", " vite ": " catalog: ", " vite-plus ": " catalog: ", " vitest ": " catalog: " } } vite.config.ts: import { defineConfig } from "vite-plus" import vue from "@vitejs/plugin-vue" export default defineConfig( { staged : { "*" : "vp check --fix" , } , fmt : { semi : false , singleQuote : true , } , lint : { plugins : [ "eslint" , "typescript" , "unicorn" , "oxc" , "vue" , "vitest" ] , env : { browser : true } , categories : { correctness : "error" } , options : { typeAware : true , typeCheck : true } , } , plugins : [ vue() ] , } ) defineConfig ã 'vite-plus' ããã€ã³ããŒãããŠããŠãVite ã®èšå®ã«å ã lint ïŒOxlintïŒã fmt ïŒOxfmtïŒã staged ïŒpre-commit ããã¯ïŒã®èšå®ã1ã€ã®ãã¡ã€ã«ã«ãŸãšãŸã£ãŠããŸãã vite ãš vitest ã¯ã pnpm-workspace.yaml ã® catalog: ã«ãã @voidzero-dev ã®ãã®ã«è§£æ±ºãããŠããŸãã åŸæ¥ã® create-vue ãããžã§ã¯ãã®æ§æ package.json { " scripts ": { " dev ": " vite ", " build ": " run-p type-check \" build-only {@} \" -- ", " build-only ": " vite build ", " type-check ": " vue-tsc --build ", " test:unit ": " vitest ", " lint ": " run-s lint:* ", " lint:oxlint ": " oxlint . --fix ", " lint:eslint ": " eslint . --fix --cache ", " format ": " prettier --write --experimental-cli src/ " } , " devDependencies ": { " eslint ": " ^10.1.0 ", " eslint-plugin-vue ": " ~10.8.0 ", " eslint-plugin-oxlint ": " ~1.57.0 ", " eslint-config-prettier ": " ^10.1.8 ", " oxlint ": " ~1.57.0 ", " prettier ": " 3.8.1 ", " vite ": " ^8.0.3 ", " vitest ": " ^4.1.2 " } } .oxlintrc.json: { " plugins ": [ " eslint ", " typescript ", " unicorn ", " oxc ", " vue ", " vitest " ] , " env ": { " browser ": true } , " categories ": { " correctness ": " error " } } .prettierrc.json: { " $schema ": " https://json.schemastore.org/prettierrc ", " semi ": false , " singleQuote ": true , " printWidth ": 100 } å
±é: eslint.config.ts åè¿°ã®éã vp create vue ã¯å
éšã§ create-vue ãå®è¡ããŠãããããeslint.config.ts ã¯äž¡ãããžã§ã¯ãã§åäžã§ãã import { defineConfigWithVueTs, vueTsConfigs, } from "@vue/eslint-config-typescript" import pluginVue from "eslint-plugin-vue" import pluginVitest from "@vitest/eslint-plugin" import pluginOxlint from "eslint-plugin-oxlint" import skipFormatting from "eslint-config-prettier/flat" export default defineConfigWithVueTs( { name : "app/files-to-lint" , files : [ "**/*.{vue,ts,mts,tsx}" ] } , ...pluginVue.configs[ "flat/essential" ], vueTsConfigs.recommended, { ...pluginVitest.configs.recommended, files : [ "src/**/__tests__/*" ] } , ...pluginOxlint.buildFromOxlintConfigFile( ".oxlintrc.json" ), skipFormatting ) ãã ããVite+ ãããžã§ã¯ãã§ã¯ãã® eslint.config.ts ã«èœãšã穎ããããŸãã Vite+ ã®å
¬åŒã¬ã€ã ã§ã¯ .oxlintrc.json ã®äœ¿çšã¯æšå¥šãããŠãããã vite.config.ts ã® lint ãããã¯ãžèšå®ãéçŽããæ¹éã§ããå®éã vp create vue ã§ .oxlintrc.json 㯠vite.config.ts ãžããŒãžãããåŸã«åé€ãããŠããŸãã ããã eslint.config.ts ã® buildFromOxlintConfigFile(".oxlintrc.json") ã¯ãã®ãŸãŸæ®ã£ãŠããŸããååšããªããã¡ã€ã«ãåç
§ãããš eslint-plugin-oxlint: could not find oxlint config file: .oxlintrc.json ãšèŠåãåºãŠç©ºé
åãè¿ããããã«ãŒã«éè€ã®ç¡å¹åãå¹ããŸããã ã€ãŸããOxlint ãš ESLint ã§åãéåãéè€å ±åãããç¶æ
ã«ãªããŸãã åé¿çã¯2ã€ãããŸãã ïŒã€ç®ã¯ vite.config.ts ãã lint ãããã¯ãçŽæ¥ã€ã³ããŒãããæ¹æ³ã§ãã eslint.config.ts 㯠TypeScript ã§ãããã vite.config.ts ã® default export ãã .lint ãåãåºã㊠buildFromOxlintConfig ã«æž¡ããŸãã // eslint.config.ts import viteConfig from './vite.config' // 倿Žå: ãã¡ã€ã«ãååšããªãããæ©èœããªã ...pluginOxlint.buildFromOxlintConfigFile( ".oxlintrc.json" ), // 倿ŽåŸ: vite.config.ts ã® lint ãããã¯ããã®ãŸãŸæž¡ã ...pluginOxlint.buildFromOxlintConfig(viteConfig.lint), ïŒã€ç®ã¯ vite.config.ts ã® lint ãããã¯ãåé€ãã .oxlintrc.json ã«èšå®ãäžæ¬åããæ¹æ³ã§ãã vite-plus ã® issue ã«ãããšãçŸç¶ã®å®è£
ã§ã¯ .oxlintrc.json çã®å°çšèšå®ãã¡ã€ã«ãåªå
ããã vite.config.ts ã¯ãã©ãŒã«ããã¯ãšããŠäœ¿ãããŸãã .oxlintrc.json ãããã°ãã¡ããèªã¿èŸŒãŸããŸãã { " plugins ": [ " eslint ", " typescript ", " unicorn ", " oxc ", " vue ", " vitest " ] , " env ": { " browser ": true } , " categories ": { " correctness ": " error " } , " options ": { " typeAware ": true , " typeCheck ": true } } eslint.config.ts ã®ä¿®æ£ãäžèŠã§æžã¿ãŸãããVite+ ã®ã vite.config.ts ã«éçŽãããæ¹éãšã¯å€ããŸãã å
±é: Lint å®è¡é 2026幎4ææç¹ã§ãcreate-vue 㯠Oxlint ãããã©ã«ãã§å梱ããŠããŸããåè¿°ã® package.json ã«ããéãã pnpm lint ïŒ run-s lint:* ïŒã§ lint:oxlint â lint:eslint ã®é ã«çŽåå®è¡ãããŸãã create-vue åŽã§ã¯ eslint-plugin-oxlint ã .oxlintrc.json ãèªã¿åããOxlint ãšéè€ãã ESLint ã«ãŒã«ãèªåã§ç¡å¹åããŠãããŸãã # Vite+ vp run lint # â vp lint . --fix ... OxlintïŒvpçµç±ïŒ # â eslint . --fix --cache ... ESLintïŒçŽæ¥åŒã³åºãïŒ # create-vue pnpm lint # â oxlint . --fix ... OxlintïŒçŽæ¥åŒã³åºãïŒ # â eslint . --fix --cache ... ESLintïŒçŽæ¥åŒã³åºãïŒ vp lint 㯠Oxlint ã ããå®è¡ããçµã¿èŸŒã¿ã³ãã³ãã§ãESLint 㯠Vite+ ã«çµ±åãããŠããŸããã ãã®ããããã³ãã¬ãŒãã§ã¯ ESLint ã eslint ã³ãã³ãã§çŽæ¥åŒã¶æ§æã«ãªã£ãŠããŸãã Vite+ ã®ã¿ã¹ã¯ã©ã³ããŒã掻çšãããå Žåã¯ã vite.config.ts ã® run.tasks ã«å®çŸ©ãç§»è¡ãããšè¯ãããã§ãã run.tasks ã§å®çŸ©ããã¿ã¹ã¯ã¯ããã©ã«ãã§ãã£ãã·ã¥ãæå¹ãªãããå
¥åãã¡ã€ã«ã«å€æŽããªããã°åå®è¡ãã¹ããããããŸãã ãªãã run.tasks ã®ã¿ã¹ã¯å㯠package.json ã® scripts ãšéè€ã§ããªããããç§»è¡ããå Žå㯠package.json åŽã® lint ã¹ã¯ãªãããåé€ããŸãã // package.json ã® lint é¢é£ã¹ã¯ãªããã run.tasks ã«ç§»è¡ããäŸ run: { tasks: { lint: { command: 'vp lint . --fix && eslint . --fix --cache' , input: [{ auto : true } , '!.eslintcache' ] , } , } , } , eslint ã® --cache ã䜿ããš .eslintcache ãæžãåºããã vp run ããããå
¥åã®å€æŽãšèŠãªããŠã¿ã¹ã¯ãã£ãã·ã¥ããããããŸããã input ã§ '!.eslintcache' ãæå®ãããã£ãã·ã¥ãã¡ã€ã«ã倿޿€ç¥ã®å¯Ÿè±¡å€ã«ããããšã§äœµçšã§ããŸãã ãã£ãã·ã¥æ©èœã«ã€ããŠã¯ ESLint ã§ã¯ãªãã¿ã¹ã¯ã©ã³ããŒåŽã®ãã®ã§ååãããããŸãããã --cache ã®æç¡ã«ããå·®ç°ã¯ä»åæªæ€èšŒã§ãã Linter æ¯èŒ: Oxlint vs ESLint æ€èšŒçšã³ã³ããŒãã³ã æ€èšŒçšã«ãæå³çã« Lint éåãä»èŸŒãã Vue ã³ã³ããŒãã³ããçšæããŸããã < script setup lang = "ts" > import { ref } from "vue" // unused expression (correctness) const x = 1 x // prefer-as-const (typescript) let y = "hello" as "hello" const items = ref ([ { id : 1 , name : "Apple" } , { id : 2 , name : "Banana" } , ]) </ script > < template > <!-- v-for without :key --> < li v- for = "item in items" > {{ item.name }} </ li > <!-- v-if and v-for on same element --> < div v- for = "item in items" v-if= "item.id > 0" :key= "item.id" > {{ item.name }} </ div > </ template > < style scoped> .unused-class { color : redd; } </ style > Oxlint ã®çµæ # Vite+ vp lint src/components/LintTest.vue x eslint(no-unused-expressions): Expected expression to be used , - [src/components/LintTest.vue: 6 : 1 ] 5 | const x = 1 6 | x : ^ `---- x typescript-eslint(prefer-as-const): Expected a ` const ` assertion instead of a literal type annotation. , - [src/components/LintTest.vue: 9 : 20 ] 8 | // prefer-as-const (typescript) 9 | let y = 'hello' as 'hello' : ^^^^^^^ ` ---- Found 0 warnings and 2 errors. Finished in 369ms on 1 file with 132 rules using 10 threads. # create-vue pnpm exec oxlint -c .oxlintrc.json src/components/LintTest.vue ...ïŒåäžã® 2 ä»¶ïŒ Found 0 warnings and 2 errors. Finished in 24ms on 1 file with 116 rules using 10 threads. Oxlint 㯠<script> å
ã®éåãæ€åºããŸãããã <template> / <style> ã®åé¡ã¯ã¹ã«ãŒãããŠããŸããOxlint 㯠.vue ãã¡ã€ã«ã® <script> ãããã¯ãã Lint ããªãããã§ãã oxc ã®äºææ§ããŒãž ã«ãããéããVue/Svelte/Astro çã®ãã¬ãŒã ã¯ãŒã¯ã§ã¯ script ãããã¯ã®ã¿ã察象ã§ãã vue ãã©ã°ã€ã³ãæå¹ã«ããŠããscript ãããã¯å
ã® Vue é¢é£ã«ãŒã«ïŒref ã®äœ¿ãæ¹ãªã©ïŒããåããŸããã SFC ãã³ãã¬ãŒãã® Lint 察å¿ã¯ oxc#15761 ã§è¿œè·¡ãããŠããŸããããŸã å®è£
ãããŠããŸããã ãŸããOxlint ã«ã¯ ESLint ã® JS ãã©ã°ã€ã³ãèªã¿èŸŒã JS plugins æ©èœããããŸãããeslint-plugin-vue ã¯åããŸããã JS plugins ã® å¶éäºé
ã«ãCustom file formats and parsers (e.g. Svelte, Vue, Angular)ãã¯æªå¯Ÿå¿ãšæèšãããŠããŸãã eslint-plugin-vue ã¯ã«ã¹ã¿ã ããŒãµãŒïŒ vue-eslint-parser ïŒã§ .vue ãã¡ã€ã«å
šäœãããŒã¹ããŠãã³ãã¬ãŒãã® AST ãã«ãŒã«ã«æž¡ãä»çµã¿ã®ããããã®å¶éã«è©²åœããŠããŸãã ã«ãŒã«æ°ã®å·®ïŒ132 vs 116ïŒã¯ã typeAware: true ã§åæ
å ±ã䜿ã£ããã§ãã¯ïŒfloating promise ã®æ€åºçïŒã远å ãããããã§ãã ãªããVite+ ãã³ãã¬ãŒãã® typeCheck: true 㯠Vue ãããžã§ã¯ãã§ã¯å®è³ªçã«äœ¿ããªãããã§ãã vp lint src/ ã®ããã«ãã£ã¬ã¯ããªãæå®ãããš .ts ãã¡ã€ã«ããã§ãã¯å¯Ÿè±¡ã«ãªããŸãã ãããã .ts ãã .vue ãã€ã³ããŒãããŠããç®æã§ tsgo ãã¢ãžã¥ãŒã«è§£æ±ºã«å€±æã TS2307: Cannot find module ãšã©ãŒãåºãŸãã äžã®æ€èšŒã§ãã¡ã€ã«ãçŽæ¥æå®ããŠããã®ã¯ãã®åé¡ãåé¿ããããã§ãã ESLint ã®çµæ # Vite+ïŒeslint-plugin-oxlint ãæ©èœããŠããªãïŒ vp exec eslint src/components/LintTest.vue src/components/LintTest.vue 6 : 1 error Expected an assignment or function call and instead saw an expression @typescript-eslint/no-unused-expressions 9 : 5 error 'y' is never reassigned. Use 'const' instead prefer-const 9 : 5 error 'y' is assigned a value but never used @typescript-eslint/no-unused-vars 9 : 20 error Expected a `const` instead of a literal type assertion @typescript-eslint/prefer-as-const 19 : 3 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key 22 : 30 error The 'items' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if' vue/no-use-v-if-with-v-for â 6 problems ( 6 errors, 0 warnings) # create-vueïŒeslint-plugin-oxlint ãæ£åžžåäœïŒ pnpm exec eslint src/components/LintTest.vue src/components/LintTest.vue 9 : 5 error 'y' is never reassigned. Use 'const' instead prefer-const 9 : 5 error 'y' is assigned a value but never used @typescript-eslint/no-unused-vars 19 : 3 error Elements in iteration expect to have 'v-bind:key' directives vue/require-v-for-key 22 : 30 error The 'items' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if' vue/no-use-v-if-with-v-for â 4 problems ( 4 errors, 0 warnings) Vite+ åŽã¯ Oxlint ã§æ€åºãããŠãã no-unused-expressions ãš prefer-as-const ã ESLint ããå ±åãããŠ6ä»¶ãåè¿°ã®éãã«ãŒã«éè€ã®ç¡å¹åãå¹ããŠããŸããã create-vue åŽã¯ eslint-plugin-oxlint ãæ£åžžåäœããOxlint ãšã®éè€ã«ãŒã«ã ESLint åŽã§ç¡å¹åããããã4ä»¶ã ã©ã¡ããã eslint-plugin-vue ã«ãã <template> å
ã® Vue åºæã®åé¡ãæ€åºãããŠããŸãã CSS/Style Lint ã«ã€ã㊠æ€èšŒçšã³ã³ããŒãã³ãã® <style> ã« color: redd; ãšããã¿ã€ããä»èŸŒã¿ãŸããããOxlint ã§ã ESLint ã§ãåŒã£ããããŸããã§ããã ã©ã¡ãã®ãã³ãã¬ãŒãã CSS ã® Lint ã¯å¯Ÿè±¡å€ã®ããã§ãã Vue å
¬åŒã®ããŒãªã³ã°ã¬ã€ãã® Linting ã»ã¯ã·ã§ã³ ã§ãæ¡å
ãããŠããã®ã¯ eslint-plugin-vue ã«ãã JavaScript/ãã³ãã¬ãŒãã® Lint ã ãã§ãCSS/Style ã® Lint ã«ã¯è§ŠããŠããŸããã CSS ã® Lint ãå¿
èŠãªãããããŸã§åæ§ Stylelint ãš Vue ãã©ã°ã€ã³ãå¥éå
¥ããããšã«ãªãããã§ãã åãã§ãã¯ã®éã pnpm type-check ã¯ã©ã¡ãã vue-tsc --build ã§åãã§ãã Vite+ åŽã¯ vite.config.ts ã« typeAware: true ïŒåèªè Lint ã«ãŒã«ã®æå¹åïŒãš typeCheck: true ïŒtsgo çµç±ã®åãã§ãã¯åæå®è¡ïŒã®èšå®ããããŸãã ãã ãåè¿°ã®éã tsgo 㯠.vue ãèªããªãããã .vue ã®åãã§ãã¯ã«ã¯åŒãç¶ã vue-tsc ãå¿
èŠã§ãã ãã¹ã ã©ã¡ãã Vitest ã§ãã Vite+ ã§ã¯ã€ã³ããŒããã¹ã 'vitest' ãã 'vite-plus/test' ã«ãã³ãã³ãã vitest ãã vp test ã«å€ãããŸãããèšå®å
容ããã¹ãã®æžãæ¹ã¯åãã§ãã Formatter æ¯èŒ: Oxfmt vs Prettier Oxfmt 㯠Prettier ãšã®åºåäºæã謳ã£ãŠãããJavaScript/TypeScript ã® conformance test ã 100% ãã¹ããŠããŸãã Vue SFC ã®ãã©ãŒãããå¯Ÿå¿ <template> ãš <style> ããã©ãŒãããã§ããã®ãæ°ã«ãªã£ãããããããšåŽ©ãã Vue ãã¡ã€ã«ã§è©ŠããŸããã <!-- ãã©ãŒãããå --> < template >< div class = "foo" >< p v-if= "true" > hello </ p ></ div ></ template > < style scoped>.foo{ color : red ; font-size : 16px ; display : flex ; justify-content : center }</ style > <!-- ãã©ãŒãããåŸïŒOxfmt / Prettier ã©ã¡ããåäžã®çµæïŒ --> < template > < div class = "foo" >< p v-if= "true" > hello </ p ></ div > </ template > < style scoped> .foo { color : red ; font-size : 16px ; display : flex ; justify-content : center ; } </ style > Oxfmt ã§ã Prettier ã§ã <template> ãš <style> ããã©ãŒãããã§ããåºåçµæã¯åäžã§ãããä¹ãæããŠåé¡ãªãããã§ãã å
¬åŒããã¥ã¡ã³ã ã«ãããš Prettier ã®çŽ30åã®é床ãšã®ããšãå°èŠæš¡ãããžã§ã¯ãã ãšäœæå·®ã¯ãããŸããããå€§èŠæš¡ãããžã§ã¯ãã§ã¯å·®ãåºããã§ãã å
šäœæ¯èŒè¡š é
ç® Vite+ ( vp create vue ) create-vue ( pnpm create vue@latest ) Linter Oxlint ( vp lint ) + ESLint Oxlint + ESLint ESLint èšå® åäž ïŒãã ã eslint-plugin-oxlint ã®ä¿®æ£ãå¿
èŠïŒ åäž Vue template lint ESLint çµç±ã§å¯Ÿå¿ ESLint çµç±ã§å¯Ÿå¿ CSS lint ãªã ãªã typeCheck tsgo ã .vue ãèªããå®è³ªäœ¿ããªã ãªã ãã¹ã Vitest ( vp test ) Vitest Formatter Oxfmt ( vp fmt ) Prettier (Oxfmtãæ¡å
ããã) ãã«ã Vite ( vp build ) Vite ( vite build ) èšå®ã®çµ±å vite.config.ts ã«éçŽ åå¥ãã¡ã€ã« ( .oxlintrc.json , .prettierrc.json ) Pre-commit ãã㯠.vite-hooks/pre-commit â vp staged ãªã (èŠå¥éèšå®) ãŸãšã vp create vue ãš pnpm create vue@latest ã§çæããããããžã§ã¯ããæ¯èŒããçµæããŸãšããŸãã Linter Oxlint 㯠.vue ã® <script> ãããã¯ãã Lint ã§ããªã <template> ã <style> ã¯å¯Ÿè±¡å€ Vue template ã® Lint ã«ã¯åŒãç¶ã ESLintïŒeslint-plugin-vueïŒãå¿
èŠ ãã㯠Vite+ ã§ã create-vue ã§ãåã create-vue 㯠Oxlint ãããã©ã«ãã§å梱ããŠãã ESLint 飿ºã®èœãšã穎 Vite+ ãã³ãã¬ãŒãã§ã¯ .oxlintrc.json ãããŒãžåŸã«åé€ãããããšãžã®å¯Ÿå¿ãç¡ããã«ãŒã«éè€ã®ç¡å¹åãå£ãã vite.config.ts ã® lint ãããã¯ã import ãããã .oxlintrc.json ã«äžæ¬åããããšã§å¯ŸåŠã§ãã Lint å®è¡ ã©ã¡ãã Oxlint â ESLint ã®çŽåå®è¡ åãã§ã㯠typeCheck: true 㯠Vue ãããžã§ã¯ãã§ã¯å®è³ªäœ¿ããªã tsgo ã .vue ãã€ã³ããŒããã .ts ãã¡ã€ã«ã§ TS2307 ãšã©ãŒãåºããã .vue ã®åãã§ãã¯ã«ã¯åŒãç¶ã vue-tsc ãå¿
èŠ Formatter Oxfmt 㯠Prettier ãšåäžã®åºå <template> / <style> ããã©ãŒãããã§ãã Prettier ããã®ä¹ãæãã§å°ãããšã¯ãªããã CSS Lint ã©ã¡ãã®ãã³ãã¬ãŒããå¯Ÿè±¡å€ å¿
èŠãªã Stylelint ãå¥éå
¥ããããšã«ãªã Vite+ ãéžã¶ã¡ãªãã㯠Linter/Formatter åäœã®å·®åãããã vite.config.ts ãžã®èšå®äžå
åãš vp ã³ãã³ãã«ããçµ±åã«ããããã§ããã Vue åºæã® Lint ãåãã§ãã¯ã«ã€ããŠã¯ãŸã ESLint + vue-tsc é ŒããªãããOxlint ã® Vue ãã³ãã¬ãŒã察å¿ã tsgo ã® .vue ãµããŒããæŽãã°ãèšå®ã楜ã«ãªãããã§ãã ä»åã¯ãã³ãã¬ãŒãã®èšå®æ¯èŒã ãã§ããããæ°ã«ãªãã®ã¯ãã¯ãå®éã®ãããžã§ã¯ãã§ã®é床差ã§ãã æ¬¡å㯠Vue ãã¡ã€ã«ãçŽ2000åååšããé§
ã¡ã¢ïŒã®ããã³ããšã³ãã§ãLint/Format/ãã«ããã©ããããéããªãã宿ž¬ããŠã¿ãŸãããæ¥œãã¿ã«ïŒ
ãŒãããã®éçºã§æ¬ ãããªããå€éšã©ã€ãã©ãªããšããã¡ã€ã«æ§é ãã®çè§£ã«çŠç¹ãåœãŠãVue.jsãããžã§ã¯ãäœæã®æé ã«æ²¿ã£ãŠè§£èª¬ããŸããVue.jsãšNode.jsã®åœ¹å²ã®éããnpmãViteãVue CLIãšãã£ãäž»èŠãªããŒã«ã«ã€ããŠèª¬æããViteã§äœæããããããžã§ã¯ãã®åºæ¬çãªãã¡ã€ã«æ§æãšãã®åœ¹å²ãå
·äœçã«ç€ºããŸããéçºã®åå°ãšãªãç¥èãåºããããšã®éèŠæ§ã匷調ããŸãã
åç»
該åœããã³ã³ãã³ããèŠã€ãããŸããã§ãã














