[{"data":1,"prerenderedAt":510},["ShallowReactive",2],{"docs:page:\u002Fvi\u002Fdocs\u002Fgetting-started\u002Finstallation":3,"docs:navigation:vi":413,"docs:section-descriptions:\u002Fvi\u002Fdocs\u002Fgetting-started\u002Finstallation":504,"docs:translations:\u002Fvi\u002Fdocs\u002Fgetting-started\u002Finstallation":505,"docs:surroundings:\u002Fvi\u002Fdocs\u002Fgetting-started\u002Finstallation":507},{"id":4,"title":5,"body":6,"description":405,"extension":406,"meta":407,"navigation":408,"path":409,"seo":410,"stem":411,"__hash__":412},"docs\u002Fvi\u002Fdocs\u002F1.getting-started\u002Finstallation.md","Cài đặt",{"type":7,"value":8,"toc":394},"minimark",[9,13,17,22,25,69,85,99,103,118,128,154,158,161,166,169,189,193,200,228,232,248,255,271,274,294,298,313,331,337,343,361,377,380,390],[10,11,5],"h1",{"id":12},"cài-đặt",[14,15,16],"p",{},"Trang này mô tả những gì cần có trước khi chạy repository cục bộ, và ý nghĩa\ncơ bản của \"phát triển cục bộ\" trong workspace này.",[18,19,21],"h2",{"id":20},"yêu-cầu-tiên-quyết","Yêu cầu tiên quyết",[14,23,24],{},"Cần các công cụ sau:",[26,27,28,41],"table",{},[29,30,31],"thead",{},[32,33,34,38],"tr",{},[35,36,37],"th",{},"Công cụ",[35,39,40],{},"Mục đích",[42,43,44,53,61],"tbody",{},[32,45,46,50],{},[47,48,49],"td",{},"Node.js 24+",[47,51,52],{},"Runtime cho tooling và build",[32,54,55,58],{},[47,56,57],{},"pnpm 12+",[47,59,60],{},"Package manager cho workspace",[32,62,63,66],{},[47,64,65],{},"Git",[47,67,68],{},"Quản lý phiên bản",[14,70,71,72,76,77,80,81,84],{},"Version chính xác được pin trong repository: ",[73,74,75],"code",{},".node-version"," pin Node.js và\nfield ",[73,78,79],{},"packageManager"," trong ",[73,82,83],{},"package.json"," pin pnpm. Dùng Corepack hoặc cài\ntrực tiếp đúng các version đó là toàn bộ toolchain sẽ thống nhất với nhau.",[86,87,88],"blockquote",{},[14,89,90,94,95,98],{},[91,92,93],"strong",{},"Lưu ý"," — trên macOS có thể cần ",[73,96,97],{},"watchman"," nếu trình theo dõi file báo\nrebuild không liên quan.",[18,100,102],{"id":101},"repository-và-workspace","Repository và workspace",[14,104,105,106,109,110,117],{},"Repository là một ",[91,107,108],{},"monorepo"," được quản lý bằng ",[111,112,116],"a",{"href":113,"rel":114},"https:\u002F\u002Fnx.dev\u002F",[115],"nofollow","Nx"," và pnpm:",[119,120,126],"pre",{"className":121,"code":123,"language":124,"meta":125},[122],"language-text","apps\u002F    runtime và deploy unit (web app, service)\nlibs\u002F    library dùng chung, thuộc bounded context\ndocs\u002F    tài liệu kiến trúc và vận hành\ntools\u002F   tooling dành cho developer (dx CLI)\n","text","",[73,127,123],{"__ignoreMap":125},[14,129,130,131,134,135,138,139,142,143,146,147,149,150,153],{},"pnpm workspace bao phủ ",[73,132,133],{},"apps\u002F*",", ",[73,136,137],{},"tools\u002F*"," và ",[73,140,141],{},"docs","; các library dưới ",[73,144,145],{},"libs\u002F","\nlà Nx project không có ",[73,148,83],{}," riêng, được resolve qua workspace alias.\nMọi thư mục còn lại trong layout trên là package của pnpm workspace. ",[73,151,152],{},"apps\u002Fhome","\nlà ứng dụng public mà bạn đang đọc — gồm cả docs và blog.",[18,155,157],{"id":156},"tổng-quan-phát-triển-cục-bộ","Tổng quan phát triển cục bộ",[14,159,160],{},"Vòng lặp phát triển điển hình gồm ba bước.",[162,163,165],"h3",{"id":164},"cài-dependencies","Cài dependencies",[14,167,168],{},"Từ root của workspace:",[119,170,174],{"className":171,"code":172,"language":173,"meta":125,"style":125},"language-bash shiki shiki-themes github-light github-dark","pnpm install\n","bash",[73,175,176],{"__ignoreMap":125},[177,178,181,185],"span",{"class":179,"line":180},"line",1,[177,182,184],{"class":183},"sScJk","pnpm",[177,186,188],{"class":187},"sZZnC"," install\n",[162,190,192],{"id":191},"tạo-type-cho-nuxt","Tạo type cho Nuxt",[14,194,195,196,199],{},"Nuxt sinh các file type trong ",[73,197,198],{},".nuxt\u002F"," một lần trước lần chạy đầu tiên:",[119,201,203],{"className":171,"code":202,"language":173,"meta":125,"style":125},"cd apps\u002Fhome\npnpm exec nuxt prepare\n",[73,204,205,214],{"__ignoreMap":125},[177,206,207,211],{"class":179,"line":180},[177,208,210],{"class":209},"sj4cs","cd",[177,212,213],{"class":187}," apps\u002Fhome\n",[177,215,217,219,222,225],{"class":179,"line":216},2,[177,218,184],{"class":183},[177,220,221],{"class":187}," exec",[177,223,224],{"class":187}," nuxt",[177,226,227],{"class":187}," prepare\n",[162,229,231],{"id":230},"khởi-động-dev-server","Khởi động dev server",[119,233,235],{"className":171,"code":234,"language":173,"meta":125,"style":125},"pnpm exec nuxt dev\n",[73,236,237],{"__ignoreMap":125},[177,238,239,241,243,245],{"class":179,"line":180},[177,240,184],{"class":183},[177,242,221],{"class":187},[177,244,224],{"class":187},[177,246,247],{"class":187}," dev\n",[14,249,250,251,254],{},"Dev server có thể truy cập tại ",[73,252,253],{},"http:\u002F\u002Flocalhost:4200",":",[119,256,258],{"className":171,"code":257,"language":173,"meta":125,"style":125},"curl -I http:\u002F\u002Flocalhost:4200\u002Fvi\u002Fdocs\u002Fgetting-started\n",[73,259,260],{"__ignoreMap":125},[177,261,262,265,268],{"class":179,"line":180},[177,263,264],{"class":183},"curl",[177,266,267],{"class":209}," -I",[177,269,270],{"class":187}," http:\u002F\u002Flocalhost:4200\u002Fvi\u002Fdocs\u002Fgetting-started\n",[14,272,273],{},"Chạy unit test cho một app từ root:",[119,275,277],{"className":171,"code":276,"language":173,"meta":125,"style":125},"pnpm exec nx test home\n",[73,278,279],{"__ignoreMap":125},[177,280,281,283,285,288,291],{"class":179,"line":180},[177,282,184],{"class":183},[177,284,221],{"class":187},[177,286,287],{"class":187}," nx",[177,289,290],{"class":187}," test",[177,292,293],{"class":187}," home\n",[18,295,297],{"id":296},"build-sẽ-làm-gì","Build sẽ làm gì",[14,299,300,301,304,305,308,309,312],{},"Ứng dụng public là một ",[91,302,303],{},"Cloudflare Worker có SSR",": ",[73,306,307],{},"nitro.config.ts"," chọn\npreset ",[73,310,311],{},"cloudflare-module",", còn các trang content được prerender ở build time\ntrên Node — nơi truy vấn content được phép — nên không có database runtime nào\nliên quan. Nx target build chạy Nuxt:",[119,314,316],{"className":171,"code":315,"language":173,"meta":125,"style":125},"npx nx build @ecoma-io\u002Fhome\n",[73,317,318],{"__ignoreMap":125},[177,319,320,323,325,328],{"class":179,"line":180},[177,321,322],{"class":183},"npx",[177,324,287],{"class":187},[177,326,327],{"class":187}," build",[177,329,330],{"class":187}," @ecoma-io\u002Fhome\n",[14,332,333,334,254],{},"Output nằm trong ",[73,335,336],{},"apps\u002Fhome\u002F.output",[119,338,341],{"className":339,"code":340,"language":124,"meta":125},[122],".output\u002Fserver\u002Findex.mjs  entry script của Worker\n.output\u002Fpublic\u002F           HTML content đã prerender, một thư mục cho mỗi route\n.output\u002Fpublic\u002F_nuxt\u002F     client asset đã hash\n.output\u002Fpublic\u002F__nuxt_content\u002F  dump của content database\n",[73,342,340],{"__ignoreMap":125},[14,344,345,348,349,352,353,356,357,360],{},[73,346,347],{},"wrangler.jsonc"," trỏ Worker vào output đó và deploy các trang đã prerender như\nWorker static assets — ",[73,350,351],{},"nx deploy @ecoma-io\u002Fhome --configuration=staging"," (build\ntrước, rồi publish) trỏ vào staging; dùng ",[73,354,355],{},"--configuration=production"," cho\nWorker production. Lệnh ",[73,358,359],{},"nx deploy"," không kèm configuration sẽ từ chối chạy —\nenvironment Wrangler là lựa chọn tường minh.",[86,362,363],{},[14,364,365,368,369,372,373,376],{},[91,366,367],{},"Cảnh báo"," — không bao giờ commit secret vào ",[73,370,371],{},".dev.vars*"," hoặc ",[73,374,375],{},".env*",".\nCấu hình Worker cục bộ chỉ dùng cho phát triển.",[378,379],"hr",{},[14,381,382],{},[383,384,385,386],"em",{},"Tiếp: ",[111,387,389],{"href":388},"\u002Fvi\u002Fdocs\u002Fgetting-started\u002Ffirst-steps","Các bước đầu tiên",[391,392,393],"style",{},"html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#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 .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":125,"searchDepth":216,"depth":216,"links":395},[396,397,398,404],{"id":20,"depth":216,"text":21},{"id":101,"depth":216,"text":102},{"id":156,"depth":216,"text":157,"children":399},[400,402,403],{"id":164,"depth":401,"text":165},3,{"id":191,"depth":401,"text":192},{"id":230,"depth":401,"text":231},{"id":296,"depth":216,"text":297},"Yêu cầu tiên quyết và tổng quan về phát triển cục bộ cho monorepo Ecoma.","md",{},true,"\u002Fvi\u002Fdocs\u002Fgetting-started\u002Finstallation",{"title":5,"description":405},"vi\u002Fdocs\u002F1.getting-started\u002Finstallation","93agFdQk9ZQZvzwDxe4D2QAvJquwdiwqskDAE4ZYDXA",[414],{"title":415,"path":416,"stem":417,"children":418,"page":460},"Vi","\u002Fvi","vi",[419,461],{"title":420,"path":421,"stem":422,"children":423,"page":460},"Blog","\u002Fvi\u002Fblog","vi\u002Fblog",[424,430,436,442,448,454],{"title":425,"path":426,"stem":427,"children":428},"Một mô hình URL cho mọi trang public","\u002Fvi\u002Fblog\u002Furl-model","vi\u002Fblog\u002F1.url-model\u002Findex",[429],{"title":425,"path":426,"stem":427},{"title":431,"path":432,"stem":433,"children":434},"Content được resolve ở build time","\u002Fvi\u002Fblog\u002Fbuild-time-content","vi\u002Fblog\u002F2.build-time-content\u002Findex",[435],{"title":431,"path":432,"stem":433},{"title":437,"path":438,"stem":439,"children":440},"Locale switching không bao giờ nói dối","\u002Fvi\u002Fblog\u002Flocale-switching","vi\u002Fblog\u002F3.locale-switching\u002Findex",[441],{"title":437,"path":438,"stem":439},{"title":443,"path":444,"stem":445,"children":446},"Deploy một blog như static assets","\u002Fvi\u002Fblog\u002Fstatic-deployment","vi\u002Fblog\u002F4.static-deployment\u002Findex",[447],{"title":443,"path":444,"stem":445},{"title":449,"path":450,"stem":451,"children":452},"Trang đọc bài không phải trang tài liệu","\u002Fvi\u002Fblog\u002Freading-first-design","vi\u002Fblog\u002F5.reading-first-design\u002Findex",[453],{"title":449,"path":450,"stem":451},{"title":455,"path":456,"stem":457,"children":458},"Blog này là gì (và không phải gì)","\u002Fvi\u002Fblog\u002Fdemo-content-note","vi\u002Fblog\u002F6.demo-content-note\u002Findex",[459],{"title":455,"path":456,"stem":457},false,{"title":462,"path":463,"stem":464,"children":465},"Tổng quan","\u002Fvi\u002Fdocs","vi\u002Fdocs\u002Findex",[466,467,476,490],{"title":462,"path":463,"stem":464},{"title":468,"path":469,"stem":470,"children":471},"Bắt đầu","\u002Fvi\u002Fdocs\u002Fgetting-started","vi\u002Fdocs\u002F1.getting-started\u002Findex",[472,473,475],{"title":468,"path":469,"stem":470},{"title":389,"path":388,"stem":474},"vi\u002Fdocs\u002F1.getting-started\u002Ffirst-steps",{"title":5,"path":409,"stem":411},{"title":477,"path":478,"stem":479,"children":480},"Khái niệm","\u002Fvi\u002Fdocs\u002Fconcepts","vi\u002Fdocs\u002F2.concepts\u002Findex",[481,482,486],{"title":477,"path":478,"stem":479},{"title":483,"path":484,"stem":485},"Nội dung và ngôn ngữ","\u002Fvi\u002Fdocs\u002Fconcepts\u002Fcontent-and-locales","vi\u002Fdocs\u002F2.concepts\u002Fcontent-and-locales",{"title":487,"path":488,"stem":489},"Web công khai","\u002Fvi\u002Fdocs\u002Fconcepts\u002Fpublic-web","vi\u002Fdocs\u002F2.concepts\u002Fpublic-web",{"title":491,"path":492,"stem":493,"children":494},"Hướng dẫn","\u002Fvi\u002Fdocs\u002Fguides","vi\u002Fdocs\u002F3.guides\u002Findex",[495,496,500],{"title":491,"path":492,"stem":493},{"title":497,"path":498,"stem":499},"Xây dựng một trang công khai","\u002Fvi\u002Fdocs\u002Fguides\u002Fbuilding-a-public-page","vi\u002Fdocs\u002F3.guides\u002Fbuilding-a-public-page",{"title":501,"path":502,"stem":503},"Phát triển cục bộ","\u002Fvi\u002Fdocs\u002Fguides\u002Flocal-development","vi\u002Fdocs\u002F3.guides\u002Flocal-development",{},[506,417],"en",[508,509],{"title":389,"path":388,"stem":474,"children":-1},{"title":477,"path":478,"stem":479,"children":-1},1791809693985]