[{"data":1,"prerenderedAt":1129},["ShallowReactive",2],{"navigation_docs":3,"-nuxt-frontend-build":352,"-nuxt-frontend-build-surround":1124},[4,54,83,116,125,161,179,200],{"title":5,"path":6,"stem":7,"children":8},"Ai","/ai","ai",[9,12,42,46,50],{"title":10,"path":6,"stem":11},"AI 技術探索","ai/index",{"title":13,"path":14,"stem":15,"children":16,"page":41},"Rag","/ai/rag","ai/RAG",[17,21,25,29,33,37],{"title":18,"path":19,"stem":20},"BM25 演算法深入解析：從 TF-IDF 到現代搜尋引擎的核心技術","/ai/rag/bm25-deep-dive-from-tf-idf-to-rag","ai/RAG/bm25-deep-dive-from-tf-idf-to-rag",{"title":22,"path":23,"stem":24},"Dense Retrieval（向量檢索）深入解析","/ai/rag/dense-retrieval-deep-dive","ai/RAG/dense-retrieval-deep-dive",{"title":26,"path":27,"stem":28},"RAG（Retrieval-Augmented Generation）原理與實作入門","/ai/rag/rag-intro-principles-and-implementation","ai/RAG/rag-intro-principles-and-implementation",{"title":30,"path":31,"stem":32},"RAG Retrieval Strategy 深入解析","/ai/rag/rag-retrieval-strategy-deep-dive","ai/RAG/rag-retrieval-strategy-deep-dive",{"title":34,"path":35,"stem":36},"Reciprocal Rank Fusion（RRF）教學：打造更穩定的檢索融合策略","/ai/rag/rrf-reciprocal-rank-fusion-guide","ai/RAG/rrf-reciprocal-rank-fusion-guide",{"title":38,"path":39,"stem":40},"TF-IDF（Term Frequency–Inverse Document Frequency）深入解析","/ai/rag/tf-idf-deep-dive","ai/RAG/tf-idf-deep-dive",false,{"title":43,"path":44,"stem":45},"Docus AI 功能完整實作指南","/ai/docus-ai-implementation","ai/docus-ai-implementation",{"title":47,"path":48,"stem":49},"llms.txt 是什麼？在 Nuxt 中控制 AI 與搜尋引擎爬蟲的新方式","/ai/llms-txt","ai/llms-txt",{"title":51,"path":52,"stem":53},"MCP（Model Context Protocol）是什麼？用「AI 的 USB-C」理解模型如何安全連接工具與資料","/ai/mcp_concept","ai/mcp_concept",{"title":55,"path":56,"stem":57,"children":58,"page":41},"Data Analysis","/data-analysis","data-analysis",[59,63,67,71,75,79],{"title":60,"path":61,"stem":62},"Exploratory Data Analysis（EDA）資料探索分析入門","/data-analysis/exploratory-data-analysis-eda","data-analysis/exploratory-data-analysis-eda",{"title":64,"path":65,"stem":66},"PR-AUC 深入解析：不平衡分類問題的重要評估指標","/data-analysis/pr-auc-for-imbalanced-classification","data-analysis/pr-auc-for-imbalanced-classification",{"title":68,"path":69,"stem":70},"ROC-AUC 深入解析：理解分類模型的判斷能力","/data-analysis/roc-auc-complete-guide","data-analysis/roc-auc-complete-guide",{"title":72,"path":73,"stem":74},"SHAP（SHapley Additive exPlanations）模型解釋方法深入解析","/data-analysis/shap-model-interpretation-complete-guide","data-analysis/shap-model-interpretation-complete-guide",{"title":76,"path":77,"stem":78},"Social Network Analysis（SNA）深入解析","/data-analysis/social-network-analysis-sna","data-analysis/social-network-analysis-sna",{"title":80,"path":81,"stem":82},"Time-based Split：為什麼時間序列資料不能使用 Random Split？","/data-analysis/time-based-split-vs-random-split","data-analysis/time-based-split-vs-random-split",{"title":84,"path":85,"stem":86,"children":87,"page":41},"MachineLearning","/machine_learning","machine_learning",[88,92,96,100,104,108,112],{"title":89,"path":90,"stem":91},"Confusion Matrix（混淆矩陣）完整解析","/machine_learning/confusion-matrix","machine_learning/confusion-matrix",{"title":93,"path":94,"stem":95},"Decision Tree 模型完整教學：從原理到 Python 實作","/machine_learning/decision-tree-complete-guide","machine_learning/decision-tree-complete-guide",{"title":97,"path":98,"stem":99},"為什麼 Decision Tree 在 Tabular Data 上常常勝過 Deep Learning？","/machine_learning/decision-tree-vs-deep-learning-on-tabular-data","machine_learning/decision-tree-vs-deep-learning-on-tabular-data",{"title":101,"path":102,"stem":103},"LightGBM 模型入門：理解高效能的 Gradient Boosting 演算法","/machine_learning/lightgbm-intro-for-tabular-data","machine_learning/lightgbm-intro-for-tabular-data",{"title":105,"path":106,"stem":107},"Logistic Regression（Logit 回歸）完整教學","/machine_learning/logistic-regression-complete-guide","machine_learning/logistic-regression-complete-guide",{"title":109,"path":110,"stem":111},"為什麼模型訓練需要 Train / Validation / Test Dataset？","/machine_learning/train-validation-test-dataset","machine_learning/train-validation-test-dataset",{"title":113,"path":114,"stem":115},"XGBoost 原理與實務教學","/machine_learning/xgboost-complete-guide","machine_learning/xgboost-complete-guide",{"title":117,"path":118,"stem":119,"children":120,"page":41},"Network","/network","network",[121],{"title":122,"path":123,"stem":124},"DNS 設定入門：CNAME vs A Record 完整解析","/network/dns-cname-vs-a-record-guide","network/dns-cname-vs-a-record-guide",{"title":126,"path":127,"stem":128,"children":129},"Nuxt","/nuxt","nuxt",[130,133,137,141,145,149,153,157],{"title":131,"path":127,"stem":132},"Nuxt 實戰指南","nuxt/index",{"title":134,"path":135,"stem":136},"Abstraction Layer 與 Adapter 的差別，一次搞懂設計角色","/nuxt/adapter_abstraction_layer","nuxt/adapter_abstraction_layer",{"title":138,"path":139,"stem":140},"Nuxt 4 全面理解 — 專案檔案結構解析","/nuxt/directory_structure","nuxt/directory_structure",{"title":142,"path":143,"stem":144},"Nuxt 前端 build 流程完整解析","/nuxt/frontend_build","nuxt/frontend_build",{"title":146,"path":147,"stem":148},"Nitro 是什麼？從 Nuxt 專案到 Server 與 Edge 的關鍵引擎","/nuxt/nitro","nuxt/nitro",{"title":150,"path":151,"stem":152},"深入理解 Nuxt 的 .nuxt 與 .output：為什麼部署時一定要分清楚？","/nuxt/nuxt_and_output","nuxt/nuxt_and_output",{"title":154,"path":155,"stem":156},"Nuxt 中 dev、build、preview 的差異一次搞懂","/nuxt/nuxt_dev_build_preview","nuxt/nuxt_dev_build_preview",{"title":158,"path":159,"stem":160},"Nuxt Image vs \u003Cimg>：為什麼 Nuxt 3 專案幾乎都該用 \u003CNuxtImg>？","/nuxt/nuxt_image","nuxt/nuxt_image",{"title":162,"path":163,"stem":164,"children":165},"Python 程式開發","/python","python/index",[166,167,171,175],{"title":162,"path":163,"stem":164},{"title":168,"path":169,"stem":170},"如何在 FastAPI 中調用記憶體 Buffer 回傳圖片 (附實例)","/python/memory_buffer","python/memory_buffer",{"title":172,"path":173,"stem":174},"Python 單元測試教學：如何為你的程式撰寫 Test","/python/python-unit-testing-unittest-pytest","python/python-unit-testing-unittest-pytest",{"title":176,"path":177,"stem":178},"如何使用 uv 取代 pip：改善 Python 專案的開發流程","/python/uv","python/uv",{"title":180,"path":181,"stem":182,"children":183,"page":41},"Statistic","/statistic","statistic",[184,188,192,196],{"title":185,"path":186,"stem":187},"卡方檢定（Chi-Square Test）入門教學","/statistic/chi-square-test-intro","statistic/chi-square-test-intro",{"title":189,"path":190,"stem":191},"常見抽樣方法（Sampling Methods）教學：Stratified、Quota、Convenience、Systematic、Simple Random","/statistic/common-sampling-methods-guide","statistic/common-sampling-methods-guide",{"title":193,"path":194,"stem":195},"Cramér’s V 指標介紹：如何衡量兩個類別變數之間的關聯","/statistic/cramers-v-for-categorical-association","statistic/cramers-v-for-categorical-association",{"title":197,"path":198,"stem":199},"Mann–Whitney U 與 Kolmogorov–Smirnov（KS）檢定：非參數統計檢定的入門指南","/statistic/mann-whitney-u-and-ks-test-intro","statistic/mann-whitney-u-and-ks-test-intro",{"title":201,"path":202,"stem":203,"children":204},"WebDev","/web_dev","web_dev",[205,208,234,248,282,312,334],{"title":206,"path":202,"stem":207},"Web 前端開發","web_dev/index",{"title":209,"path":210,"stem":211,"children":212},"瀏覽器與渲染","/web_dev/browser","web_dev/browser/index",[213,214,218,222,226,230],{"title":209,"path":210,"stem":211},{"title":215,"path":216,"stem":217},"瀏覽器儲存空間完整解析：Cookie、localStorage、IndexedDB 到 Cache Storage","/web_dev/browser/browser-storage-comprehensive-guide","web_dev/browser/browser-storage-comprehensive-guide",{"title":219,"path":220,"stem":221},"DOM (Document Object Model) 深入解析","/web_dev/browser/dom","web_dev/browser/dom",{"title":223,"path":224,"stem":225},"Service Worker Request Flow 深入解析","/web_dev/browser/service-worker-request-flow","web_dev/browser/service-worker-request-flow",{"title":227,"path":228,"stem":229},"CSR、SSR 與 SSG 是什麼？前端渲染策略完整比較","/web_dev/browser/ssr_csr_ssg","web_dev/browser/ssr_csr_ssg",{"title":231,"path":232,"stem":233},"Virtual DOM 深入解析：為什麼它能優化前端效能？","/web_dev/browser/virtual_dom","web_dev/browser/virtual_dom",{"title":235,"path":236,"stem":237,"children":238},"圖形技術","/web_dev/graphics","web_dev/graphics/index",[239,240,244],{"title":235,"path":236,"stem":237},{"title":241,"path":242,"stem":243},"為什麼 Three.js 專案幾乎都選擇 CSR？從 SSR 問題談起","/web_dev/graphics/threejs_csr","web_dev/graphics/threejs_csr",{"title":245,"path":246,"stem":247},"WebGL 是什麼？為什麼前端 3D 幾乎都靠它？","/web_dev/graphics/webgl","web_dev/graphics/webGL",{"title":249,"path":250,"stem":251,"children":252},"架構與配置","/web_dev/infrastructure","web_dev/infrastructure/index",[253,254,258,262,266,270,274,278],{"title":249,"path":250,"stem":251},{"title":255,"path":256,"stem":257},"Zeabur + K3s + Nuxt 部署架構完整解析","/web_dev/infrastructure/k3s-zeabur","web_dev/infrastructure/K3s-zeabur",{"title":259,"path":260,"stem":261},"ECS vs Docker vs Kubernetes：從部署堆疊理解三層架構","/web_dev/infrastructure/ecs-docker-kubernetes-stack","web_dev/infrastructure/ecs-docker-kubernetes-stack",{"title":263,"path":264,"stem":265},"ECS vs VPS 是什麼？從部署網站的角度一次搞懂差別","/web_dev/infrastructure/ecs-vs-vps","web_dev/infrastructure/ecs-vs-vps",{"title":267,"path":268,"stem":269},"Zeabur 內網服務連線完整入門指南","/web_dev/infrastructure/k3s-internal-networking","web_dev/infrastructure/k3s-internal-networking",{"title":271,"path":272,"stem":273},"使用 Microservices 架構設計系統的優勢解析","/web_dev/infrastructure/microservices-architecture-advantages","web_dev/infrastructure/microservices-architecture-advantages",{"title":275,"path":276,"stem":277},"Nginx 入門教學：從反向代理到與 Kubernetes 的架構比較","/web_dev/infrastructure/nginx-intro","web_dev/infrastructure/nginx-intro",{"title":279,"path":280,"stem":281},"YAML 配置是什麼？為什麼現代開發都在用它","/web_dev/infrastructure/yaml-configuration","web_dev/infrastructure/yaml-configuration",{"title":283,"path":284,"stem":285,"children":286},"網絡與通訊","/web_dev/network","web_dev/network/index",[287,288,292,296,300,304,308],{"title":283,"path":284,"stem":285},{"title":289,"path":290,"stem":291},"HTTP Request 結構完整解析：從 Request Line 到 Header 一次看懂","/web_dev/network/http-request-structure","web_dev/network/http-request-structure",{"title":293,"path":294,"stem":295},"OSI 模型（Open Systems Interconnection Model）完整解析","/web_dev/network/osi-model","web_dev/network/osi-model",{"title":297,"path":298,"stem":299},"RESTful API 設計原則與實務解析","/web_dev/network/restful-api","web_dev/network/restful-api",{"title":301,"path":302,"stem":303},"RESTful API 五大設計原則深入解析","/web_dev/network/restful-api-principles","web_dev/network/restful-api-principles",{"title":305,"path":306,"stem":307},"Server-Sent Events (SSE) 深入解析與實作教學","/web_dev/network/sse-introduction","web_dev/network/sse-introduction",{"title":309,"path":310,"stem":311},"WebSocket 入門教學：從概念到 Node.js 實作","/web_dev/network/websocket-introduction","web_dev/network/websocket-introduction",{"title":313,"path":314,"stem":315,"children":316},"認證與安全","/web_dev/security","web_dev/security/index",[317,318,322,326,330],{"title":313,"path":314,"stem":315},{"title":319,"path":320,"stem":321},"使用 Cookie 與 Session 建立使用者驗證（完整新手教學）","/web_dev/security/cookie-session-authentication","web_dev/security/cookie-session-authentication",{"title":323,"path":324,"stem":325},"JWT 驗證機制完整解析：從登入流程到實務應用","/web_dev/security/jwt-authentication","web_dev/security/jwt-authentication",{"title":327,"path":328,"stem":329},"Secret Key 簽名是什麼？從零理解資料簽名的本質","/web_dev/security/secret-key-signing","web_dev/security/secret-key-signing",{"title":331,"path":332,"stem":333},"SSH（Secure Shell）是什麼？從遠端登入到安全通道的核心概念","/web_dev/security/ssh","web_dev/security/ssh",{"title":335,"path":336,"stem":337,"children":338},"SEO 與規範","/web_dev/seo","web_dev/seo/index",[339,340,344,348],{"title":335,"path":336,"stem":337},{"title":341,"path":342,"stem":343},"Canonical URL 是什麼？用生活化方式搞懂前端 SEO 的基本保命符","/web_dev/seo/canonical_link","web_dev/seo/canonical_link",{"title":345,"path":346,"stem":347},"robots.txt 是什麼？SEO 的第一道守門員","/web_dev/seo/robot_txt","web_dev/seo/robot_txt",{"title":349,"path":350,"stem":351},"Nuxt SEO 中的 Meta 與 SEO 工具是如何運作的？","/web_dev/seo/seo","web_dev/seo/seo",{"id":353,"title":142,"body":354,"description":1113,"extension":1114,"links":1115,"meta":1116,"navigation":530,"path":143,"seo":1122,"stem":144,"__hash__":1123},"docs/nuxt/frontend_build.md",{"type":355,"value":356,"toc":1095},"minimark",[357,367,370,375,378,401,404,407,415,418,420,424,431,437,440,446,453,455,463,476,479,571,574,617,623,630,632,636,639,664,667,682,688,690,694,697,728,731,738,744,750,752,756,762,765,771,774,780,786,788,792,795,801,804,810,816,818,822,825,831,834,840,846,848,852,855,899,902,936,942,944,951,954,960,963,969,972,974,978,981,987,989,992,995,1002,1005,1066,1068,1072,1075,1078,1080,1083,1086,1091],[358,359,360],"blockquote",{},[361,362,363],"p",{},[364,365,366],"strong",{},"前端 build 的本質，是把「給人看的程式碼」轉成「給瀏覽器執行的檔案」。",[368,369],"hr",{},[371,372,374],"h2",{"id":373},"nuxt-的前端建置到底在做什麼","Nuxt 的前端建置到底在做什麼？",[361,376,377],{},"當你在專案中執行：",[379,380,385],"pre",{"className":381,"code":382,"language":383,"meta":384,"style":384},"language-bash shiki shiki-themes github-dark","nuxi build\n","bash","",[386,387,388],"code",{"__ignoreMap":384},[389,390,393,397],"span",{"class":391,"line":392},"line",1,[389,394,396],{"class":395},"svObZ","nuxi",[389,398,400],{"class":399},"sU2Wk"," build\n",[361,402,403],{},"Nuxt 會啟動一個「正式環境的前端建置流程」，背後是由 Vite 的 production build 負責實作。這個流程不是單一步驟，而是一連串轉換與最佳化。",[361,405,406],{},"整體來看，可以先用下面這個流程理解：",[379,408,413],{"className":409,"code":411,"language":412},[410],"language-text",".vue / .ts / CSS / images\n        ↓\n編譯與最佳化\n        ↓\n瀏覽器可執行的 JS + CSS + assets\n        ↓\n.output/public/_nuxt\n","text",[386,414,411],{"__ignoreMap":384},[361,416,417],{},"接下來我們逐步拆解這條流水線。",[368,419],{},[371,421,423],{"id":422},"step-1掃描整個前端專案建立依賴關係","Step 1：掃描整個前端專案，建立依賴關係",[361,425,426,427,430],{},"建置一開始，Nuxt 並不是立刻「打包」，而是先理解你的前端世界長什麼樣子。它會掃描所有",[364,428,429],{},"有可能進入瀏覽器的程式碼與資源","，例如：",[379,432,435],{"className":433,"code":434,"language":412},[410],"app.vue\npages/*\ncomponents/*\ncomposables/*\nplugins/*\nassets/*\n",[386,436,434],{"__ignoreMap":384},[361,438,439],{},"如果你有像下面這樣的檔案結構：",[379,441,444],{"className":442,"code":443,"language":412},[410],"pages/index.vue\ncomponents/NavBar.vue\ncomposables/useUser.ts\n",[386,445,443],{"__ignoreMap":384},[361,447,448,449,452],{},"Nuxt 會依照「頁面 → 元件 → composable → 其他依賴」的方式，建立一棵完整的前端依賴樹。\n這一步的目的不是輸出檔案，而是",[364,450,451],{},"確認哪些程式碼會真的影響使用者畫面","。",[368,454],{},[371,456,458,459,462],{"id":457},"step-2把-vue-檔轉成瀏覽器能理解的-javascript","Step 2：把 ",[386,460,461],{},".vue"," 檔轉成瀏覽器能理解的 JavaScript",[361,464,465,467,468,471,472,475],{},[386,466,461],{}," 檔對開發者很友善，但瀏覽器其實完全不認得 ",[386,469,470],{},"\u003Ctemplate>","、",[386,473,474],{},"\u003Cscript setup>"," 這些語法。",[361,477,478],{},"例如你寫：",[379,480,484],{"className":481,"code":482,"language":483,"meta":384,"style":384},"language-vue shiki shiki-themes github-dark","\u003Ctemplate>\n  \u003Ch1>Hello\u003C/h1>\n\u003C/template>\n\n\u003Cscript setup>\nconst msg = \"Nuxt\"\n\u003C/script>\n","vue",[386,485,486,499,515,525,532,545,562],{"__ignoreMap":384},[389,487,488,492,496],{"class":391,"line":392},[389,489,491],{"class":490},"s95oV","\u003C",[389,493,495],{"class":494},"s4JwU","template",[389,497,498],{"class":490},">\n",[389,500,502,505,508,511,513],{"class":391,"line":501},2,[389,503,504],{"class":490},"  \u003C",[389,506,507],{"class":494},"h1",[389,509,510],{"class":490},">Hello\u003C/",[389,512,507],{"class":494},[389,514,498],{"class":490},[389,516,518,521,523],{"class":391,"line":517},3,[389,519,520],{"class":490},"\u003C/",[389,522,495],{"class":494},[389,524,498],{"class":490},[389,526,528],{"class":391,"line":527},4,[389,529,531],{"emptyLinePlaceholder":530},true,"\n",[389,533,535,537,540,543],{"class":391,"line":534},5,[389,536,491],{"class":490},[389,538,539],{"class":494},"script",[389,541,542],{"class":395}," setup",[389,544,498],{"class":490},[389,546,548,552,556,559],{"class":391,"line":547},6,[389,549,551],{"class":550},"snl16","const",[389,553,555],{"class":554},"sDLfK"," msg",[389,557,558],{"class":550}," =",[389,560,561],{"class":399}," \"Nuxt\"\n",[389,563,565,567,569],{"class":391,"line":564},7,[389,566,520],{"class":490},[389,568,539],{"class":494},[389,570,498],{"class":490},[361,572,573],{},"在 build 過程中，Vue compiler 會把 template 轉換成一個「渲染用的 JavaScript 函式」，概念上會接近：",[379,575,579],{"className":576,"code":577,"language":578,"meta":384,"style":384},"language-js shiki shiki-themes github-dark","render() {\n  return h(\"h1\", \"Hello\")\n}\n","js",[386,580,581,589,612],{"__ignoreMap":384},[389,582,583,586],{"class":391,"line":392},[389,584,585],{"class":395},"render",[389,587,588],{"class":490},"() {\n",[389,590,591,594,597,600,603,606,609],{"class":391,"line":501},[389,592,593],{"class":550},"  return",[389,595,596],{"class":395}," h",[389,598,599],{"class":490},"(",[389,601,602],{"class":399},"\"h1\"",[389,604,605],{"class":490},", ",[389,607,608],{"class":399},"\"Hello\"",[389,610,611],{"class":490},")\n",[389,613,614],{"class":391,"line":517},[389,615,616],{"class":490},"}\n",[361,618,619,620,452],{},"這一步的關鍵在於：\n",[364,621,622],{},"畫面不再是 HTML 描述，而是 JavaScript 在「產生 DOM 結構」",[361,624,625,626,629],{},"這個過程稱為 ",[364,627,628],{},"Single File Component（SFC）編譯","，也是 Vue 能高度動態化的核心原因。",[368,631],{},[371,633,635],{"id":634},"step-3typescript-只負責開發期build-時一定會被移除","Step 3：TypeScript 只負責開發期，build 時一定會被移除",[361,637,638],{},"如果你在專案中使用 TypeScript，例如：",[379,640,644],{"className":641,"code":642,"language":643,"meta":384,"style":384},"language-ts shiki shiki-themes github-dark","const user: string = \"Damien\"\n","ts",[386,645,646],{"__ignoreMap":384},[389,647,648,650,653,656,659,661],{"class":391,"line":392},[389,649,551],{"class":550},[389,651,652],{"class":554}," user",[389,654,655],{"class":550},":",[389,657,658],{"class":554}," string",[389,660,558],{"class":550},[389,662,663],{"class":399}," \"Damien\"\n",[361,665,666],{},"這段型別資訊對開發工具非常重要，但對瀏覽器來說毫無意義。\n因此在 build 階段，所有 TypeScript 都會被轉成純 JavaScript：",[379,668,670],{"className":576,"code":669,"language":578,"meta":384,"style":384},"const user = \"Damien\"\n",[386,671,672],{"__ignoreMap":384},[389,673,674,676,678,680],{"class":391,"line":392},[389,675,551],{"class":550},[389,677,652],{"class":554},[389,679,558],{"class":550},[389,681,663],{"class":399},[361,683,684,685],{},"這一步可以理解成：\n",[364,686,687],{},"TypeScript 是寫給你和編輯器看的，不是寫給瀏覽器看的。",[368,689],{},[371,691,693],{"id":692},"step-4把模組關係打包成實際可載入的檔案","Step 4：把模組關係打包成實際可載入的檔案",[361,695,696],{},"在開發模式中，你可能會寫很多 import：",[379,698,700],{"className":576,"code":699,"language":578,"meta":384,"style":384},"import { ref } from \"vue\"\nimport Chart from \"chart.js\"\n",[386,701,702,716],{"__ignoreMap":384},[389,703,704,707,710,713],{"class":391,"line":392},[389,705,706],{"class":550},"import",[389,708,709],{"class":490}," { ref } ",[389,711,712],{"class":550},"from",[389,714,715],{"class":399}," \"vue\"\n",[389,717,718,720,723,725],{"class":391,"line":501},[389,719,706],{"class":550},[389,721,722],{"class":490}," Chart ",[389,724,712],{"class":550},[389,726,727],{"class":399}," \"chart.js\"\n",[361,729,730],{},"在 dev mode 下，這些模組可以由瀏覽器動態請求。但在 production 環境，如果每一個模組都單獨請求，效能會非常差。",[361,732,733,734,737],{},"因此 build 時會進行 ",[364,735,736],{},"bundling","，把多個模組整理成較少、結構清楚的檔案，例如：",[379,739,742],{"className":740,"code":741,"language":412},[410],"app.js\nvendor.js\nchunk-xxx.js\n",[386,743,741],{"__ignoreMap":384},[361,745,746,747],{},"這樣做的目的很單純：\n",[364,748,749],{},"減少網路請求次數，讓第一次載入更快、更穩定。",[368,751],{},[371,753,755],{"id":754},"step-5自動進行-code-splitting-與-lazy-loading","Step 5：自動進行 Code Splitting 與 Lazy Loading",[361,757,758,759],{},"前端效能最佳化的一個核心概念是：\n",[364,760,761],{},"不要一次把整個網站的程式碼都送給使用者。",[361,763,764],{},"假設你有兩個頁面：",[379,766,769],{"className":767,"code":768,"language":412},[410],"pages/index.vue\npages/about.vue\n",[386,770,768],{"__ignoreMap":384},[361,772,773],{},"build 後，它們會被拆成不同的 chunk，例如：",[379,775,778],{"className":776,"code":777,"language":412},[410],"index.[hash].js\nabout.[hash].js\n",[386,779,777],{"__ignoreMap":384},[361,781,782,783,452],{},"使用者進首頁時只會下載 index 相關程式碼，真正進到 about 頁面時才載入 about 的 chunk。\n這種「用到才載」的策略，就是 ",[364,784,785],{},"lazy loading",[368,787],{},[371,789,791],{"id":790},"step-6css-也會被重新整理與最佳化","Step 6：CSS 也會被重新整理與最佳化",[361,793,794],{},"CSS 並不是原封不動地搬過去。像是：",[379,796,799],{"className":797,"code":798,"language":412},[410],"assets/main.css\n",[386,800,798],{"__ignoreMap":384},[361,802,803],{},"在 build 後會變成：",[379,805,808],{"className":806,"code":807,"language":412},[410],"style.[hash].css\n",[386,809,807],{"__ignoreMap":384},[361,811,812,813],{},"同時會進行多項處理，包括合併樣式、移除未使用的 CSS（tree-shaking），以及壓縮檔案大小。\n最終目的只有一個：",[364,814,815],{},"讓畫面樣式下載更快、體積更小。",[368,817],{},[371,819,821],{"id":820},"step-7靜態資源會被重新命名確保快取安全","Step 7：靜態資源會被重新命名，確保快取安全",[361,823,824],{},"如果你在專案中使用圖片：",[379,826,829],{"className":827,"code":828,"language":412},[410],"assets/logo.png\n",[386,830,828],{"__ignoreMap":384},[361,832,833],{},"build 後可能會變成：",[379,835,838],{"className":836,"code":837,"language":412},[410],"logo.a8sd9f.png\n",[386,839,837],{"__ignoreMap":384},[361,841,842,843,452],{},"這種帶 hash 的檔名不是亂取的，而是為了解決瀏覽器快取問題。\n只要內容改變，檔名就會改，瀏覽器就一定會重新下載，這個策略稱為 ",[364,844,845],{},"cache busting",[368,847],{},[371,849,851],{"id":850},"step-8程式碼壓縮minify","Step 8：程式碼壓縮（Minify）",[361,853,854],{},"在正式環境中，可讀性不再重要，檔案大小才是重點。\n例如：",[379,856,858],{"className":576,"code":857,"language":578,"meta":384,"style":384},"function add(a, b) {\n  return a + b\n}\n",[386,859,860,882,895],{"__ignoreMap":384},[389,861,862,865,868,870,874,876,879],{"class":391,"line":392},[389,863,864],{"class":550},"function",[389,866,867],{"class":395}," add",[389,869,599],{"class":490},[389,871,873],{"class":872},"s9osk","a",[389,875,605],{"class":490},[389,877,878],{"class":872},"b",[389,880,881],{"class":490},") {\n",[389,883,884,886,889,892],{"class":391,"line":501},[389,885,593],{"class":550},[389,887,888],{"class":490}," a ",[389,890,891],{"class":550},"+",[389,893,894],{"class":490}," b\n",[389,896,897],{"class":391,"line":517},[389,898,616],{"class":490},[361,900,901],{},"會被壓縮成：",[379,903,905],{"className":576,"code":904,"language":578,"meta":384,"style":384},"function add(a,b){return a+b}\n",[386,906,907],{"__ignoreMap":384},[389,908,909,911,913,915,917,920,922,925,928,931,933],{"class":391,"line":392},[389,910,864],{"class":550},[389,912,867],{"class":395},[389,914,599],{"class":490},[389,916,873],{"class":872},[389,918,919],{"class":490},",",[389,921,878],{"class":872},[389,923,924],{"class":490},"){",[389,926,927],{"class":550},"return",[389,929,930],{"class":490}," a",[389,932,891],{"class":550},[389,934,935],{"class":490},"b}\n",[361,937,938,939,452],{},"這一步不改變邏輯，只是",[364,940,941],{},"讓傳輸量更小、下載更快",[368,943],{},[371,945,947,948],{"id":946},"step-9所有前端產物輸出到-outputpublic_nuxt","Step 9：所有前端產物輸出到 ",[386,949,950],{},".output/public/_nuxt",[361,952,953],{},"完成以上所有步驟後，Nuxt 會把前端產物輸出到：",[379,955,958],{"className":956,"code":957,"language":412},[410],".output/public/_nuxt\n",[386,959,957],{"__ignoreMap":384},[361,961,962],{},"裡面會看到類似：",[379,964,967],{"className":965,"code":966,"language":412},[410],".output/public/_nuxt/\n ├── app.a83hd.js\n ├── vendor.9dd2.js\n ├── index.83j2.js\n └── style.css\n",[386,968,966],{"__ignoreMap":384},[361,970,971],{},"這些檔案，就是瀏覽器實際下載、執行的內容。",[368,973],{},[371,975,977],{"id":976},"把整個前端-build-流程再看一次","把整個前端 build 流程再看一次",[361,979,980],{},"如果用一條線來總結：",[379,982,985],{"className":983,"code":984,"language":412},[410],".vue / ts / css\n        ↓\nVue compiler\n        ↓\nTypeScript → JavaScript\n        ↓\nVite bundling\n        ↓\ncode splitting\n        ↓\nminify\n        ↓\n.output/public/_nuxt\n",[386,986,984],{"__ignoreMap":384},[368,988],{},[371,990,991],{"id":991},"一個一定要建立的核心理解",[361,993,994],{},"前端 build 做的事情，其實只有一件：",[358,996,997],{},[361,998,999],{},[364,1000,1001],{},"把「適合人類開發的程式碼」，轉成「適合瀏覽器執行的檔案」。",[361,1003,1004],{},"所以你會看到這樣的對照關係：",[1006,1007,1008,1021],"table",{},[1009,1010,1011],"thead",{},[1012,1013,1014,1018],"tr",{},[1015,1016,1017],"th",{},"開發時",[1015,1019,1020],{},"build 後",[1022,1023,1024,1034,1042,1050,1058],"tbody",{},[1012,1025,1026,1031],{},[1027,1028,1029],"td",{},[386,1030,461],{},[1027,1032,1033],{},"render function JS",[1012,1035,1036,1039],{},[1027,1037,1038],{},"TypeScript",[1027,1040,1041],{},"JavaScript",[1012,1043,1044,1047],{},[1027,1045,1046],{},"多個模組",[1027,1048,1049],{},"bundle / chunk",[1012,1051,1052,1055],{},[1027,1053,1054],{},"原始 CSS",[1027,1056,1057],{},"壓縮後 CSS",[1012,1059,1060,1063],{},[1027,1061,1062],{},"原始檔名",[1027,1064,1065],{},"hash 檔名",[368,1067],{},[371,1069,1071],{"id":1070},"為什麼這些事情不在-dev-mode-做","為什麼這些事情不在 dev mode 做？",[361,1073,1074],{},"因為目標不同。",[361,1076,1077],{},"開發模式追求的是「即時、好改、好除錯」，而 build 追求的是「效能、體積、穩定性」。\n因此 dev 使用的是即時編譯的開發伺服器，而 build 則產出一套不可變的正式檔案。",[368,1079],{},[371,1081,1082],{"id":1082},"用一個生活化的比喻收尾",[361,1084,1085],{},"開發模式就像在廚房備料、試味道、邊煮邊調整。\nbuild 則是把菜色固定下來，裝盒、封膜，準備送出去。",[361,1087,1088,1090],{},[386,1089,950],{},"，就是那個外送盒裡真正交到客人手上的食物。",[1092,1093,1094],"style",{},"html pre.shiki code .svObZ, html code.shiki .svObZ{--shiki-default:#B392F0}html pre.shiki code .sU2Wk, html code.shiki .sU2Wk{--shiki-default:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html pre.shiki code .s95oV, html code.shiki .s95oV{--shiki-default:#E1E4E8}html pre.shiki code .s4JwU, html code.shiki .s4JwU{--shiki-default:#85E89D}html pre.shiki code .snl16, html code.shiki .snl16{--shiki-default:#F97583}html pre.shiki code .sDLfK, html code.shiki .sDLfK{--shiki-default:#79B8FF}html pre.shiki code .s9osk, html code.shiki .s9osk{--shiki-default:#FFAB70}",{"title":384,"searchDepth":501,"depth":501,"links":1096},[1097,1098,1099,1101,1102,1103,1104,1105,1106,1107,1109,1110,1111,1112],{"id":373,"depth":501,"text":374},{"id":422,"depth":501,"text":423},{"id":457,"depth":501,"text":1100},"Step 2：把 .vue 檔轉成瀏覽器能理解的 JavaScript",{"id":634,"depth":501,"text":635},{"id":692,"depth":501,"text":693},{"id":754,"depth":501,"text":755},{"id":790,"depth":501,"text":791},{"id":820,"depth":501,"text":821},{"id":850,"depth":501,"text":851},{"id":946,"depth":501,"text":1108},"Step 9：所有前端產物輸出到 .output/public/_nuxt",{"id":976,"depth":501,"text":977},{"id":991,"depth":501,"text":991},{"id":1070,"depth":501,"text":1071},{"id":1082,"depth":501,"text":1082},"深入理解 Nuxt 在 build 階段如何將 Vue 與 TypeScript 程式碼轉換為瀏覽器可執行的前端資源，從掃描、編譯、打包到最佳化一次搞懂。","md",null,{"tags":1117,"category":203,"date":1121},[128,1118,1119,1120,483],"vite","frontend","build","2026-02-10",{"title":142,"description":1113},"xRGBzQVGnWY1ukks-L63gCoMJwhPh9FaKusDS9xoMmI",[1125,1127],{"title":138,"path":139,"stem":140,"description":1126,"children":-1},"了解 Nuxt 4 框架的核心目錄與檔案規劃，掌握專案結構的設計理念，提升開發效率與架構清晰度。",{"title":146,"path":147,"stem":148,"description":1128,"children":-1},"深入理解 Nitro 在 Nuxt 中的角色，為什麼它不是 Express，以及它如何讓同一份 Nuxt 專案同時支援 Node、Serverless 與 Edge。",1776690842807]