
Next.js Bundle Analyzer基于交互式 Treemap 的 Bundle 體積與依賴分析工具深度解析【免費(fèi)下載鏈接】next.jsThe React Framework項(xiàng)目地址: https://gitcode.com/GitHub_Trending/next/next.js本篇技術(shù)文章聚焦 Next.js 倉(cāng)庫(kù)中的 Bundle Analyzer 應(yīng)用apps/bundle-analyzer/README.md它是一個(gè)專門用于可視化 bundle 體積、分析依賴關(guān)系的 Next.js 應(yīng)用。讀完后你將掌握它的五大核心功能交互式 Treemap、路由級(jí)分析、依賴鏈追蹤、環(huán)境/文件類型過濾、文件搜索、它與主next包構(gòu)建期內(nèi)嵌vendor的分發(fā)機(jī)制以及底層二進(jìn)制分析數(shù)據(jù)格式analyze.data/modules.data的解析原理并知道如何通過next experimental-analyze在實(shí)際項(xiàng)目中使用它。它是什么一個(gè)內(nèi)嵌于 next 包的獨(dú)立 Next.js 應(yīng)用根據(jù) README 的定義Bundle Analyzer 是A Next.js application for visualizing bundle sizes and analyzing dependencies using interactive treemaps.從 package.json 可以確認(rèn)其工程屬性包名為next/bundle-analyzer-ui且聲明了private: true—— 它不會(huì)發(fā)布到 npmREADME 明確指出This package is not published to npm. Instead its built and vendored into the mainnextpackage during its build process.它不發(fā)布到 npm而是在主next包的構(gòu)建過程中被構(gòu)建并內(nèi)嵌進(jìn)去它本身就是一個(gè)用 React 19 Tailwind CSS 4 Radix UI 組件構(gòu)建的完整 Next.js App Router 應(yīng)用入口為 app/page.tsx 和 app/layout.tsx頁(yè)面元數(shù)據(jù)標(biāo)題即為 Next.js Bundle Analyzer。從源碼結(jié)構(gòu)看vendor 內(nèi)嵌是如何落地的這一分發(fā)機(jī)制在倉(cāng)庫(kù)中有兩處源碼證據(jù)構(gòu)建依賴聲明packages/next/turbo.json 中主next包的build任務(wù)聲明了dependsOn: [next/bundle-analyzer-ui#build, ^build]即每次構(gòu)建next包時(shí)會(huì)先觸發(fā) Bundle Analyzer UI 的構(gòu)建其構(gòu)建腳本為next build --no-mangling見 package.json 的 scripts 字段。運(yùn)行時(shí)復(fù)制在 packages/next/src/build/analyze/index.ts 中analyze函數(shù)完成 Turbopack 分析后執(zhí)行await cp(path.join(__dirname, ../../bundle-analyzer), analyzeDir, { recursive: true, })也就是說(shuō)next包內(nèi)dist/bundle-analyzer目錄即構(gòu)建期內(nèi)嵌的靜態(tài)站點(diǎn)會(huì)被整體復(fù)制到目標(biāo)項(xiàng)目的.next/diagnostics/analyze目錄下與data/數(shù)據(jù)目錄放在一起供本地服務(wù)器托管。核心功能README 五大特性的源碼印證README 的 Features 一節(jié)列出了五項(xiàng)核心能力下文逐項(xiàng)結(jié)合源碼展開。1. 交互式 TreemapInteractive Treemap頁(yè)面主體由 TreemapVisualizer 組件渲染布局算法實(shí)現(xiàn)在 lib/treemap-layout.ts 與 lib/layout-treemap.ts 中。從 page.tsx 的渲染代碼可以看到Treemap 以SizeMode.Compressed壓縮后體積作為默認(rèn)尺寸模式TreemapVisualizer analyzeData{analyzeData} sourceIndex{rootSourceIndex} selectedSourceIndex{selectedSourceIndex ?? rootSourceIndex} ... sizeMode{SizeMode.Compressed} /交互細(xì)節(jié)還包括底部狀態(tài)欄實(shí)時(shí)顯示懸停文件的名稱、壓縮體積以及 client / server / traced 徽標(biāo)見 page.tsx 底部hoveredNodeInfo渲染邏輯按Escape鍵可將 Treemap 選區(qū)重置回當(dāng)前路由的根 sourcehandleKeyDown邏輯右側(cè)詳情面板Sidebar寬度可在 10%–50% 之間拖拽調(diào)整。2. 路由級(jí)分析Route-based Analysis分析數(shù)據(jù)按路由組織存儲(chǔ)根路由讀取data/analyze.data其余路由讀取data/route/analyze.data。page.tsx 中的數(shù)據(jù)路徑推導(dǎo)邏輯let analyzeDataPath if (selectedRoute selectedRoute /) { analyzeDataPath data/analyze.data } else if (selectedRoute) { analyzeDataPath data/${selectedRoute.replace(/^\//, )}/analyze.data }路由列表來(lái)源是 packages/next/src/build/analyze/index.ts 中collectRoutesForAnalyze函數(shù)生成的routes.json它同時(shí)掃描app與pages目錄支持 hybrid 項(xiàng)目經(jīng)discoverRoutesgenerateRoutesManifest得到全部靜態(tài)/動(dòng)態(tài)路由后序列化寫入analyzeDir/data/routes.json。UI 側(cè)由 RouteTypeahead 組件提供路由輸入聯(lián)想。數(shù)據(jù)文件類型定義RouteManifest見 lib/types.ts。3. 依賴鏈追蹤Dependency Tracking點(diǎn)擊某個(gè)文件后import-chain 組件基于模塊圖展示導(dǎo)入鏈路與依賴關(guān)系。底層計(jì)算依賴 lib/module-graph.ts 中的computeActiveEntries與computeModuleDepthMap數(shù)據(jù)則來(lái)自全局共享的modules.data所有路由共用一份模塊表每路由只持有自己的analyze.dataconst { data: modulesData } useSWRModulesData(data/modules.data, fetchModulesData)4. 過濾控制Filter ControlsREADME 說(shuō)明可以按環(huán)境client/server和文件類型JS/CSS/JSON/Assets過濾。page.tsx 頂欄提供環(huán)境單選Monitor/Server圖標(biāo)對(duì)應(yīng)的 Client/Server與文件類型多選JavaScript/CSS/JSON/Asset過濾謂詞filterSource通過analyzeData.getSourceFlags(sourceIndex)判定每個(gè) source 的歸屬const hasEnvironment (environmentFilter Environment.Client flags.client) || (environmentFilter Environment.Server flags.server)getSourceFlags的判定規(guī)則見 lib/analyze-data.ts頗具信息量輸出文件以[client-fs]/開頭 → 標(biāo)記為client以[project]/開頭 → 標(biāo)記為server traced即被追蹤保留到運(yùn)行時(shí)的服務(wù)端文件其余 →server按擴(kuò)展名區(qū)分類型.js/.mjs/.cjs→ js.css→ css.json→ json其他 → asset。5. 文件搜索Search FunctionalityFileSearch 組件基于 cmdk 實(shí)現(xiàn)對(duì) bundle 內(nèi)文件進(jìn)行搜索搜索詞searchQuery傳入 Treemap 高亮匹配項(xiàng)。文件索引由AnalyzeData構(gòu)造時(shí)建立的pathToSourceIndex路徑映射與ModulesData的pathToModuleIndex映射提供支撐。數(shù)據(jù)協(xié)議JSON 頭 二進(jìn)制邊的.data文件格式這是本應(yīng)用最有技術(shù)含量的部分。lib/analyze-data.ts 注釋說(shuō)明這些類型匹配 Rust 側(cè) analyze.rs 的結(jié)構(gòu)——即 TurbopackRust產(chǎn)出分析數(shù)據(jù)TypeScript 側(cè)負(fù)責(zé)解析與渲染。文件布局為[ u32: JSON 頭長(zhǎng)度 ][ JSON 頭 ][ 二進(jìn)制邊數(shù)據(jù)u32 數(shù)組 ]其中AnalyzeDataHeaderanalyze.datasourcessource 樹含parent_source_index組成目錄層級(jí)、chunk_parts每個(gè) chunk 分片記錄source_index/output_file_index/size/compressed_size、output_files輸出文件名、三組EdgesDataReferenceoutput_file_chunk_parts、source_chunk_parts、source_children以及source_rootsModulesDataHeadermodules.datamodules表加上module_dependents、module_dependencies及其 async/traced 變體共 6 組邊引用。readEdgesDataAtIndex用 CSR壓縮稀疏行風(fēng)格讀取邊表只讀取目標(biāo)索引所需的前后兩個(gè) offset避免整表反序列化使單文件依賴查詢接近 O(出度) 而非 O(總邊數(shù))。在此基礎(chǔ)上封裝了getOwnSizes/getRecursiveSizes遞歸體積支持過濾謂詞、sourceChunks所在 chunk 列表、getRecursiveModuleCount等 API供 Treemap 布局與側(cè)邊欄統(tǒng)計(jì)調(diào)用。如何使用next experimental-analyze的完整鏈路雖然本應(yīng)用不發(fā)布 npm但它是next experimental-analyze命令的可視端。從 packages/next/src/build/analyze/index.ts 可以還原完整調(diào)用鏈與參數(shù)export type AnalyzeOptions { dir: string reactProductionProfiling?: boolean noMangling?: boolean appDirOnly?: boolean output?: boolean port?: number }參數(shù)默認(rèn)值作用dir-項(xiàng)目目錄.next作為 distDirnoManglingfalse不做符號(hào)混淆便于閱讀模塊名appDirOnlyfalse僅分析app目錄路由路由收集時(shí)傳入discoverRoutesoutputfalsetrue時(shí)僅產(chǎn)出結(jié)果文件到.next/diagnostics/analyze不啟動(dòng)服務(wù)器port4000交互式結(jié)果服務(wù)器的監(jiān)聽端口僅監(jiān)聽localhost執(zhí)行流程強(qiáng)制process.env.TURBOPACK ?? 1——analyze 是 Turbopack 專屬能力源碼注釋analyze is Turbopack-only以PHASE_ANALYZE階段加載項(xiàng)目配置調(diào)用turbopackAnalyze執(zhí)行生產(chǎn)構(gòu)建級(jí)分析并返回耗時(shí)將next包內(nèi)嵌的bundle-analyzer靜態(tài)站點(diǎn)復(fù)制到.next/diagnostics/analyze寫入data/routes.json若未指定output調(diào)用startServer基于serve-handler在localhost:port默認(rèn) 4000啟動(dòng)靜態(tài)服務(wù)器打印Bundle analyzer available at http://address后阻塞等待。開發(fā)該應(yīng)用本身時(shí)next.config.mjs 有一個(gè)值得注意的配置開發(fā)模式下將/data/:path*重寫代理到http://localhost:4000/data/:path*即從正在運(yùn)行的next experimental-analyze服務(wù)器實(shí)時(shí)拉取分析數(shù)據(jù)調(diào)試 UI而構(gòu)建發(fā)布時(shí)使用output: export導(dǎo)出純靜態(tài)站點(diǎn)到dist。此外構(gòu)建腳本攜帶NEXT_TEST_NATIVE_IGNORE_LOCAL_INSTALLtrue環(huán)境變量表明它使用next包內(nèi)置的原生二進(jìn)制而非本地工作區(qū)安裝。維護(hù)約定重要變更需同步更新 Demo 站點(diǎn)README 的 Updating 一節(jié)給出了一條明確的維護(hù)約定當(dāng)落地非平凡non-trivial的改動(dòng)時(shí)應(yīng)考慮同步更新官方 demo 站點(diǎn)README 中附帶了 demo 站點(diǎn)的 URL 與獨(dú)立倉(cāng)庫(kù)地址此處不再重復(fù)外鏈。這說(shuō)明 Bundle Analyzer 的 UI 迭代是以一個(gè)獨(dú)立演示倉(cāng)庫(kù)為回歸/展示基線的。小結(jié)Bundle Analyzer 是 Next.js 倉(cāng)庫(kù)中一個(gè)私有、構(gòu)建期內(nèi)嵌進(jìn)next包的工具型 Next.js 應(yīng)用服務(wù)于next experimental-analyze命令的交互式結(jié)果展示其數(shù)據(jù)協(xié)議由 TurbopackRust以JSON 頭 CSR 邊表的二進(jìn)制格式產(chǎn)出TypeScript 端按需解析兼顧體積與查詢效率功能面覆蓋 Treemap 可視化、按路由下鉆、import 依賴鏈、client/server 環(huán)境與 JS/CSS/JSON/Asset 類型過濾、文件搜索并支持--output離線產(chǎn)出與--port自定義端口相關(guān)關(guān)鍵文件README、數(shù)據(jù)解析、類型定義、路由與模塊圖、分析入口。適用前提說(shuō)明analyze功能基于 Turbopack且分析的是生產(chǎn)構(gòu)建源碼日志提示 Analyzing a production build...在開發(fā)本倉(cāng)庫(kù)內(nèi)的該應(yīng)用需按 package.json 中的 scripts 執(zhí)行并配合localhost:4000的數(shù)據(jù)服務(wù)?!久赓M(fèi)下載鏈接】next.jsThe React Framework項(xiàng)目地址: https://gitcode.com/GitHub_Trending/next/next.js創(chuàng)作聲明:本文部分內(nèi)容由AI輔助生成(AIGC),僅供參考