[{"data":1,"prerenderedAt":4514},["ShallowReactive",2],{"page-\u002Fvue\u002F构造模式":3},{"id":4,"title":5,"body":6,"description":4507,"extension":4508,"meta":4509,"navigation":1673,"path":4510,"seo":4511,"stem":4512,"__hash__":4513},"content\u002FVue\u002F构造模式.md","构造模式",{"type":7,"value":8,"toc":4424},"minimark",[9,21,24,31,38,120,126,340,342,348,354,393,399,431,433,439,445,477,483,512,514,520,526,544,550,567,569,575,581,611,617,638,640,646,733,735,741,772,788,792,811,813,819,892,894,900,953,955,961,1010,1012,1018,1074,1076,1082,1137,1139,1145,1290,1292,1298,1325,1328,1332,1341,1343,1349,1391,1393,1399,1443,1445,1451,1527,1529,1535,1541,1556,1562,1577,1583,1598,1600,1606,1618,1621,1628,1639,1642,1649,1729,1736,1740,1748,1754,1761,1775,1782,1787,1794,1799,1806,1811,1818,1823,1830,1835,1842,1847,1854,1859,1866,1871,1878,1883,1886,1889,2624,2627,2631,2658,2662,2665,2671,2675,2688,2704,2715,2798,2801,2809,2822,2826,2840,2844,2860,2864,2875,2878,2890,2927,2932,2959,2966,2971,2975,2988,2991,2995,2998,3007,3010,3017,3025,3028,3032,3038,3077,3080,3146,3161,3271,3275,3284,3291,3336,3340,3347,3384,3387,3440,3443,3460,3513,3516,3585,3589,3592,3638,3642,3645,3655,3664,3668,3671,3674,3677,3687,3691,3694,3701,3705,3708,3717,3721,3724,3739,3810,3813,3819,3829,3863,3872,3875,3878,3889,3899,3902,3947,3950,4002,4005,4012,4042,4046,4053,4092,4103,4106,4109,4112,4115,4134,4137,4144,4259,4269,4272,4275,4289,4292,4298,4304,4309,4312,4315,4322,4340,4343,4397,4420],[10,11,12,16,17,20],"p",{},[13,14,15],"strong",{},"Vite"," 和 ",[13,18,19],{},"Webpack"," 是两种流行的前端构建工具，它们在构建模式、性能、开发体验等方面有显著差异。以下是它们的详细对比：",[22,23],"hr",{},[25,26,28],"h2",{"id":27},"_1-构建模式的核心差异",[13,29,30],{},"1. 构建模式的核心差异",[32,33,35],"h3",{"id":34},"_11-webpack",[13,36,37],{},"1.1 Webpack",[39,40,41,67],"ul",{},[42,43,44,47,48],"li",{},[13,45,46],{},"基于打包的构建模式","：",[39,49,50,60],{},[42,51,52,53,56,57],{},"Webpack 是一个",[13,54,55],{},"打包工具","，它在开发和生产环境中都",[13,58,59],{},"会将所有模块（如 JavaScript、CSS、图片等）打包成一个或多个文件。",[42,61,62,63,66],{},"开发环境下，Webpack 会",[13,64,65],{},"将所有模块打包并启动一个开发服务器","。",[42,68,69,47,72,77,80,81,88,89,91,92,95,96,99,100,103,104,107,108],{},[13,70,71],{},"特点",[39,73,74],{},[42,75,76],{},"支持多种模块化规范（CommonJS、ES Module 等）。",[78,79],"br",{},"CommonJS 模块是为 Node.js 打包 JavaScript 代码的原始方式。Node.js 还支持浏览器和其他 JavaScript 运行时使用的 ",[82,83,87],"a",{"href":84,"rel":85},"https:\u002F\u002Fnodejs.cn\u002Fapi\u002Fesm.html",[86],"nofollow","ECMAScript 模块"," 标准。在 Node.js 中，每个文件都被视为一个单独的模块。",[78,90],{},"ES模块（ECMAScript Modules）",[13,93,94],{},"是JavaScript官方的模块系统","，它允许",[13,97,98],{},"开发者将大型程序拆分为可重用的模块","。这些模块可以",[13,101,102],{},"导出和导入类、函数、对象或变量","，以便在不同的文件或项目中使用。",[13,105,106],{},"随着现代浏览器对ES模块的支持","，开发者可以更高效地管理和维护代码。",[39,109,110,117],{},[42,111,112,113,116],{},"通过",[13,114,115],{},"插件和加载器","（Loader）支持丰富的功能（如代码分割、热更新、Tree Shaking 等）。",[42,118,119],{},"配置文件灵活，但可能较为复杂。",[32,121,123],{"id":122},"_12-vite",[13,124,125],{},"1.2 Vite",[39,127,128,315],{},[42,129,130,47,133,150,152,155,156,159,160,163,164,166,167,169,173,179,194,200,218,224,232,238,247,253,262,264,268,274,283,289,297,303],{},[13,131,132],{},"基于原生 ES Module 的构建模式",[39,134,135,144],{},[42,136,137,140,141],{},[13,138,139],{},"Vite 利用现代浏览器的原生 ES Module 支持","，在开发环境下",[13,142,143],{},"直接按需加载模块，无需打包。",[42,145,146,147],{},"生产环境下，",[13,148,149],{},"Vite 使用 Rollup 进行打包。",[78,151],{},[13,153,154],{},"Rollup"," 是一个 ",[13,157,158],{},"JavaScript 模块打包工具","，主要用于将",[13,161,162],{},"小块代码编译成大块复杂的代码","（如库或应用程序）。它专注于 ES Module（ESM）的打包，支持 Tree Shaking（摇树优化）和代码分割等特性，适合构建高效、轻量的 JavaScript 库或应用。",[78,165],{},"以下是 Rollup 的详细介绍：",[22,168],{},[25,170,172],{"id":171},"rollup-的核心特点","Rollup 的核心特点",[32,174,176],{"id":175},"_11-专注于-es-module",[13,177,178],{},"1.1 专注于 ES Module",[39,180,181,187],{},[42,182,183,184,66],{},"Rollup 是首批",[13,185,186],{},"完全支持 ES Module 的打包工具之一",[42,188,189,190,193],{},"它可以将",[13,191,192],{},"多个 ES Module 打包成一个或多个文件","，同时保留模块的静态结构。",[32,195,197],{"id":196},"_12-tree-shaking",[13,198,199],{},"1.2 Tree Shaking",[39,201,202,212],{},[42,203,204,205,208,209,66],{},"Rollup 通过",[13,206,207],{},"静态分析","移除未使用的代码（Dead Code），从而",[13,210,211],{},"减小打包文件的体积",[42,213,214,215,66],{},"这一特性特别",[13,216,217],{},"适合构建库或工具包",[32,219,221],{"id":220},"_13-代码分割",[13,222,223],{},"1.3 代码分割",[39,225,226],{},[42,227,228,229,66],{},"Rollup 支持",[13,230,231],{},"将代码拆分成多个块（Chunk），实现按需加载",[32,233,235],{"id":234},"_14-轻量高效",[13,236,237],{},"1.4 轻量高效",[39,239,240],{},[42,241,242,243,246],{},"Rollup 生成的",[13,244,245],{},"打包文件通常比其他工具（如 Webpack）更小","，因为它专注于 ES Module 并优化了输出。",[32,248,250],{"id":249},"_15-插件系统",[13,251,252],{},"1.5 插件系统",[39,254,255],{},[42,256,257,258,261],{},"Rollup 提供了",[13,259,260],{},"丰富的插件生态系统","，支持扩展功能（如处理 CSS、TypeScript、Babel 等）。",[22,263],{},[25,265,267],{"id":266},"rollup-的适用场景","Rollup 的适用场景",[32,269,271],{"id":270},"_21-构建-javascript-库",[13,272,273],{},"2.1 构建 JavaScript 库",[39,275,276],{},[42,277,278,279,282],{},"Rollup 非常",[13,280,281],{},"适合构建 JavaScript 库（如 React、Vue 等）","，因为它生成的代码更小、更高效。",[32,284,286],{"id":285},"_22-现代浏览器应用",[13,287,288],{},"2.2 现代浏览器应用",[39,290,291],{},[42,292,293,294,66],{},"如果你的项目主要面向现代浏览器（支持 ES Module），",[13,295,296],{},"Rollup 是一个很好的选择",[32,298,300],{"id":299},"_23-工具链开发",[13,301,302],{},"2.3 工具链开发",[39,304,305],{},[42,306,307,308,311,312,66],{},"Rollup 常",[13,309,310],{},"用于构建工具链或 CLI 工具","，因为它可以",[13,313,314],{},"生成轻量的、可复用的代码",[42,316,317,47,319],{},[13,318,71],{},[39,320,321,328,334],{},[42,322,323,324,327],{},"开发环境下",[13,325,326],{},"启动速度极快","，因为不需要打包。",[42,329,330,331,66],{},"支持热模块替换（HMR），且",[13,332,333],{},"性能优于 Webpack",[42,335,336,337,66],{},"配置",[13,338,339],{},"文件简单，开箱即用",[22,341],{},[25,343,345],{"id":344},"_2-开发环境对比",[13,346,347],{},"2. 开发环境对比",[32,349,351],{"id":350},"_21-webpack",[13,352,353],{},"2.1 Webpack",[39,355,356,367,380],{},[42,357,358,361,362],{},[13,359,360],{},"启动速度","：\n",[39,363,364],{},[42,365,366],{},"在开发环境下，Webpack 需要先打包所有模块，然后启动开发服务器。对于大型项目，启动时间可能较长。",[42,368,369,361,372],{},[13,370,371],{},"热更新（HMR）",[39,373,374],{},[42,375,376,379],{},[13,377,378],{},"Webpack 支持热更新","，但在大型项目中，热更新速度可能较慢。",[42,381,382,361,385],{},[13,383,384],{},"开发体验",[39,386,387,390],{},[42,388,389],{},"配置复杂，尤其是对于初学者。",[42,391,392],{},"需要安装和配置大量插件和加载器。",[32,394,396],{"id":395},"_22-vite",[13,397,398],{},"2.2 Vite",[39,400,401,410,419],{},[42,402,403,361,405],{},[13,404,360],{},[39,406,407],{},[42,408,409],{},"Vite 在开发环境下直接按需加载模块，无需打包，因此启动速度极快。",[42,411,412,361,414],{},[13,413,371],{},[39,415,416],{},[42,417,418],{},"Vite 的热更新性能优于 Webpack，尤其是在大型项目中。",[42,420,421,361,423],{},[13,422,384],{},[39,424,425,428],{},[42,426,427],{},"配置简单，开箱即用。",[42,429,430],{},"支持 TypeScript、CSS 预处理器等，无需额外配置。",[22,432],{},[25,434,436],{"id":435},"_3-生产环境对比",[13,437,438],{},"3. 生产环境对比",[32,440,442],{"id":441},"_31-webpack",[13,443,444],{},"3.1 Webpack",[39,446,447,457,467],{},[42,448,449,361,452],{},[13,450,451],{},"打包性能",[39,453,454],{},[42,455,456],{},"Webpack 的打包性能较好，支持代码分割、Tree Shaking 等优化。",[42,458,459,361,462],{},[13,460,461],{},"输出文件",[39,463,464],{},[42,465,466],{},"Webpack 生成的打包文件通常较大，但可以通过配置优化。",[42,468,469,361,472],{},[13,470,471],{},"插件生态",[39,473,474],{},[42,475,476],{},"Webpack 有丰富的插件生态，支持各种复杂的构建需求。",[32,478,480],{"id":479},"_32-vite",[13,481,482],{},"3.2 Vite",[39,484,485,494,503],{},[42,486,487,361,489],{},[13,488,451],{},[39,490,491],{},[42,492,493],{},"Vite 在生产环境下使用 Rollup 进行打包，性能优于 Webpack。",[42,495,496,361,498],{},[13,497,461],{},[39,499,500],{},[42,501,502],{},"Vite 生成的打包文件通常较小，且支持 Tree Shaking 和代码分割。",[42,504,505,361,507],{},[13,506,471],{},[39,508,509],{},[42,510,511],{},"Vite 的插件生态相对较新，但正在快速发展。",[22,513],{},[25,515,517],{"id":516},"_4-适用场景",[13,518,519],{},"4. 适用场景",[32,521,523],{"id":522},"_41-webpack",[13,524,525],{},"4.1 Webpack",[39,527,528],{},[42,529,530,361,533],{},[13,531,532],{},"适合场景",[39,534,535,538,541],{},[42,536,537],{},"大型复杂项目，需要高度定制化的构建流程。",[42,539,540],{},"需要兼容旧版浏览器（如 IE11）。",[42,542,543],{},"需要使用 Webpack 特有的插件或功能。",[32,545,547],{"id":546},"_42-vite",[13,548,549],{},"4.2 Vite",[39,551,552],{},[42,553,554,361,556],{},[13,555,532],{},[39,557,558,561,564],{},[42,559,560],{},"现代浏览器项目，利用原生 ES Module 的优势。",[42,562,563],{},"中小型项目，追求极快的开发体验。",[42,565,566],{},"使用 Vue 3、React 等现代框架的项目。",[22,568],{},[25,570,572],{"id":571},"_5-配置文件对比",[13,573,574],{},"5. 配置文件对比",[32,576,578],{"id":577},"_51-webpack",[13,579,580],{},"5.1 Webpack",[39,582,583,594],{},[42,584,585,586,589,590,593],{},"Webpack 的配置文件通常",[13,587,588],{},"较为复杂","，需要",[13,591,592],{},"手动配置入口、输出、加载器、插件","等。",[42,595,596,597,599,600],{},"示例：",[78,598],{},"javascript",[601,602,607],"pre",{"className":603,"code":605,"language":606},[604],"language-text","const path = require('path');\n\nmodule.exports = {\n  entry: '.\u002Fsrc\u002Findex.js',\n  output: {\n    filename: 'bundle.js',\n    path: path.resolve(__dirname, 'dist'),\n  },\n  module: {\n    rules: [\n      {\n        test: \u002F\\.js$\u002F,\n        use: 'babel-loader',\n      },\n      {\n        test: \u002F\\.css$\u002F,\n        use: ['style-loader', 'css-loader'],\n      },\n    ],\n  },\n  plugins: [\n    new HtmlWebpackPlugin({\n      template: '.\u002Fsrc\u002Findex.html',\n    }),\n  ],\n};\n","text",[608,609,605],"code",{"__ignoreMap":610},"",[32,612,614],{"id":613},"_52-vite",[13,615,616],{},"5.2 Vite",[39,618,619,625],{},[42,620,621,622,66],{},"Vite 的配置文件简单，",[13,623,624],{},"通常只需几行代码即可完成基本配置",[42,626,596,627,599,629,631,632],{},[78,628],{},[78,630],{},"复制",[601,633,636],{"className":634,"code":635,"language":606},[604],"import { defineConfig } from 'vite';\nimport vue from '@vitejs\u002Fplugin-vue';\n\nexport default defineConfig({\n  plugins: [vue()],\n});\n",[608,637,635],{"__ignoreMap":610},[22,639],{},[25,641,643],{"id":642},"_6-性能对比",[13,644,645],{},"6. 性能对比",[647,648,649,664],"table",{},[650,651,652],"thead",{},[653,654,655,660,662],"tr",{},[656,657,659],"th",{"align":658},"left","特性",[656,661,19],{"align":658},[656,663,15],{"align":658},[665,666,667,681,694,707,720],"tbody",{},[653,668,669,675,678],{},[670,671,672],"td",{"align":658},[13,673,674],{},"开发启动速度",[670,676,677],{"align":658},"较慢（需要打包所有模块）",[670,679,680],{"align":658},"极快（按需加载模块）",[653,682,683,688,691],{},[670,684,685],{"align":658},[13,686,687],{},"热更新速度",[670,689,690],{"align":658},"较慢（尤其是大型项目）",[670,692,693],{"align":658},"极快",[653,695,696,701,704],{},[670,697,698],{"align":658},[13,699,700],{},"生产打包速度",[670,702,703],{"align":658},"较慢",[670,705,706],{"align":658},"较快（使用 Rollup）",[653,708,709,714,717],{},[670,710,711],{"align":658},[13,712,713],{},"输出文件大小",[670,715,716],{"align":658},"较大（可通过配置优化）",[670,718,719],{"align":658},"较小",[653,721,722,727,730],{},[670,723,724],{"align":658},[13,725,726],{},"配置复杂度",[670,728,729],{"align":658},"复杂",[670,731,732],{"align":658},"简单",[22,734],{},[25,736,738],{"id":737},"_7-总结",[13,739,740],{},"7. 总结",[39,742,743,755],{},[42,744,745,361,747],{},[13,746,19],{},[39,748,749,752],{},[42,750,751],{},"适合大型复杂项目，功能强大但配置复杂。",[42,753,754],{},"开发环境下启动速度较慢，但生产环境下打包性能较好。",[42,756,757,361,759],{},[13,758,15],{},[39,760,761,764],{},[42,762,763],{},"适合现代浏览器项目，开发体验极佳。",[42,765,323,766,768,769],{},[13,767,326],{},"，生产环境下",[13,770,771],{},"打包性能优于 Webpack。",[10,773,774,775,778,779,781,782,778,785,787],{},"如果你的项目需要快速启动和开发，且主要",[13,776,777],{},"面向现代浏览器","，",[13,780,15],{}," 是更好的选择。如果你的项目需要",[13,783,784],{},"兼容旧版浏览器或需要高度定制化的构建流程",[13,786,19],{}," 可能更适合。",[789,790,791],"h1",{"id":791},"npm客户端",[10,793,794,797,798,797,801,797,804,16,807,810],{},[608,795,796],{},"npm","、",[608,799,800],{},"cnpm",[608,802,803],{},"tnpm",[608,805,806],{},"yarn",[608,808,809],{},"pnpm"," 都是 JavaScript 生态中常用的包管理工具，它们的主要功能是管理项目的依赖包。以下是它们的区别和特点：",[22,812],{},[25,814,816],{"id":815},"_1-npm",[13,817,818],{},"1. npm",[39,820,821,827,833,859,876],{},[42,822,823,826],{},[13,824,825],{},"全称","：Node Package Manager",[42,828,829,832],{},[13,830,831],{},"开发者","：Node.js 官方团队",[42,834,835,47,837],{},[13,836,71],{},[39,838,839,842,845,852],{},[42,840,841],{},"Node.js 的默认包管理工具。",[42,843,844],{},"拥有最大的包生态系统（npm registry）。",[42,846,847,848,851],{},"支持脚本命令（如 ",[608,849,850],{},"npm run","）。",[42,853,854,855,858],{},"支持 ",[608,856,857],{},"package-lock.json"," 文件，用于锁定依赖版本。",[42,860,861,47,864],{},[13,862,863],{},"缺点",[39,865,866,869],{},[42,867,868],{},"安装速度较慢。",[42,870,871,872,875],{},"依赖嵌套结构可能导致 ",[608,873,874],{},"node_modules"," 体积庞大。",[42,877,878,47,881,883,884,631,886],{},[13,879,880],{},"常用命令",[78,882],{},"bash",[78,885],{},[601,887,890],{"className":888,"code":889,"language":606},[604],"npm install\nnpm install \u003Cpackage>\nnpm run \u003Cscript>\n",[608,891,889],{"__ignoreMap":610},[22,893],{},[25,895,897],{"id":896},"_2-cnpm",[13,898,899],{},"2. cnpm",[39,901,902,907,912,927,939],{},[42,903,904,906],{},[13,905,825],{},"：China npm",[42,908,909,911],{},[13,910,831],{},"：阿里巴巴",[42,913,914,47,916],{},[13,915,71],{},[39,917,918,921,924],{},[42,919,920],{},"npm 的国内镜像，专为中国开发者优化。",[42,922,923],{},"安装速度快（使用国内服务器）。",[42,925,926],{},"支持 npm 的所有命令。",[42,928,929,47,931],{},[13,930,863],{},[39,932,933,936],{},[42,934,935],{},"依赖镜像服务器，可能存在同步延迟。",[42,937,938],{},"安装时默认使用软链接，可能导致某些工具（如 Webpack）无法正确解析依赖。",[42,940,941,47,943,883,945,631,947],{},[13,942,880],{},[78,944],{},[78,946],{},[601,948,951],{"className":949,"code":950,"language":606},[604],"cnpm install\ncnpm install \u003Cpackage>\n",[608,952,950],{"__ignoreMap":610},[22,954],{},[25,956,958],{"id":957},"_3-tnpm",[13,959,960],{},"3. tnpm",[39,962,963,968,972,987,996],{},[42,964,965,967],{},[13,966,825],{},"：Taobao npm",[42,969,970,911],{},[13,971,831],{},[42,973,974,47,976],{},[13,975,71],{},[39,977,978,981,984],{},[42,979,980],{},"专为阿里巴巴内部开发的 npm 客户端。",[42,982,983],{},"支持私有 npm 仓库。",[42,985,986],{},"安装速度快，优化了依赖解析和下载。",[42,988,989,47,991],{},[13,990,863],{},[39,992,993],{},[42,994,995],{},"主要用于阿里巴巴内部，普通开发者使用较少。",[42,997,998,47,1000,883,1002,631,1004],{},[13,999,880],{},[78,1001],{},[78,1003],{},[601,1005,1008],{"className":1006,"code":1007,"language":606},[604],"tnpm install\ntnpm install \u003Cpackage>\n",[608,1009,1007],{"__ignoreMap":610},[22,1011],{},[25,1013,1015],{"id":1014},"_4-yarn",[13,1016,1017],{},"4. yarn",[39,1019,1020,1025,1030,1051,1060],{},[42,1021,1022,1024],{},[13,1023,825],{},"：Yarn Package Manager",[42,1026,1027,1029],{},[13,1028,831],{},"：Facebook、Google、Tilde 等",[42,1031,1032,47,1034],{},[13,1033,71],{},[39,1035,1036,1039,1042,1048],{},[42,1037,1038],{},"比 npm 更快的安装速度（并行下载依赖）。",[42,1040,1041],{},"支持离线模式（缓存依赖包）。",[42,1043,854,1044,1047],{},[608,1045,1046],{},"yarn.lock"," 文件，确保依赖版本一致性。",[42,1049,1050],{},"支持工作区（Workspaces），适合管理多包项目。",[42,1052,1053,47,1055],{},[13,1054,863],{},[39,1056,1057],{},[42,1058,1059],{},"依赖解析算法复杂，可能导致某些场景下的兼容性问题。",[42,1061,1062,47,1064,883,1066,631,1068],{},[13,1063,880],{},[78,1065],{},[78,1067],{},[601,1069,1072],{"className":1070,"code":1071,"language":606},[604],"yarn install\nyarn add \u003Cpackage>\nyarn run \u003Cscript>\n",[608,1073,1071],{"__ignoreMap":610},[22,1075],{},[25,1077,1079],{"id":1078},"_5-pnpm",[13,1080,1081],{},"5. pnpm",[39,1083,1084,1089,1094,1114,1123],{},[42,1085,1086,1088],{},[13,1087,825],{},"：Performant npm",[42,1090,1091,1093],{},[13,1092,831],{},"：Zoltan Kochan",[42,1095,1096,47,1098],{},[13,1097,71],{},[39,1099,1100,1103,1106,1111],{},[42,1101,1102],{},"使用硬链接和符号链接，减少磁盘空间占用。",[42,1104,1105],{},"安装速度快，依赖解析效率高。",[42,1107,854,1108,1047],{},[608,1109,1110],{},"pnpm-lock.yaml",[42,1112,1113],{},"支持工作区（Workspaces）。",[42,1115,1116,47,1118],{},[13,1117,863],{},[39,1119,1120],{},[42,1121,1122],{},"某些工具（如 Webpack）可能不兼容 pnpm 的依赖结构。",[42,1124,1125,47,1127,883,1129,631,1131],{},[13,1126,880],{},[78,1128],{},[78,1130],{},[601,1132,1135],{"className":1133,"code":1134,"language":606},[604],"pnpm install\npnpm add \u003Cpackage>\npnpm run \u003Cscript>\n",[608,1136,1134],{"__ignoreMap":610},[22,1138],{},[25,1140,1142],{"id":1141},"_6-对比总结",[13,1143,1144],{},"6. 对比总结",[647,1146,1147,1163],{},[650,1148,1149],{},[653,1150,1151,1153,1155,1157,1159,1161],{},[656,1152,659],{"align":658},[656,1154,796],{"align":658},[656,1156,800],{"align":658},[656,1158,803],{"align":658},[656,1160,806],{"align":658},[656,1162,809],{"align":658},[665,1164,1165,1186,1205,1232,1251,1268],{},[653,1166,1167,1172,1174,1177,1180,1183],{},[670,1168,1169],{"align":658},[13,1170,1171],{},"安装速度",[670,1173,703],{"align":658},[670,1175,1176],{"align":658},"快（国内镜像）",[670,1178,1179],{"align":658},"快（内部优化）",[670,1181,1182],{"align":658},"快（并行下载）",[670,1184,1185],{"align":658},"快（硬链接优化）",[653,1187,1188,1193,1196,1198,1200,1202],{},[670,1189,1190],{"align":658},[13,1191,1192],{},"磁盘空间占用",[670,1194,1195],{"align":658},"高（嵌套依赖）",[670,1197,1195],{"align":658},[670,1199,1195],{"align":658},[670,1201,1195],{"align":658},[670,1203,1204],{"align":658},"低（硬链接共享依赖）",[653,1206,1207,1212,1216,1220,1224,1228],{},[670,1208,1209],{"align":658},[13,1210,1211],{},"依赖锁定文件",[670,1213,1214],{"align":658},[608,1215,857],{},[670,1217,1218],{"align":658},[608,1219,857],{},[670,1221,1222],{"align":658},[608,1223,857],{},[670,1225,1226],{"align":658},[608,1227,1046],{},[670,1229,1230],{"align":658},[608,1231,1110],{},[653,1233,1234,1239,1242,1245,1247,1249],{},[670,1235,1236],{"align":658},[13,1237,1238],{},"工作区支持",[670,1240,1241],{"align":658},"支持",[670,1243,1244],{"align":658},"不支持",[670,1246,1244],{"align":658},[670,1248,1241],{"align":658},[670,1250,1241],{"align":658},[653,1252,1253,1258,1260,1262,1264,1266],{},[670,1254,1255],{"align":658},[13,1256,1257],{},"离线模式",[670,1259,1244],{"align":658},[670,1261,1244],{"align":658},[670,1263,1244],{"align":658},[670,1265,1241],{"align":658},[670,1267,1241],{"align":658},[653,1269,1270,1275,1278,1281,1284,1287],{},[670,1271,1272],{"align":658},[13,1273,1274],{},"适用场景",[670,1276,1277],{"align":658},"通用",[670,1279,1280],{"align":658},"国内开发者",[670,1282,1283],{"align":658},"阿里巴巴内部",[670,1285,1286],{"align":658},"大型项目",[670,1288,1289],{"align":658},"磁盘空间有限的项目",[22,1291],{},[25,1293,1295],{"id":1294},"_7-如何选择",[13,1296,1297],{},"7. 如何选择？",[39,1299,1300,1305,1310,1315,1320],{},[42,1301,1302,1304],{},[13,1303,796],{},"：适合大多数项目，尤其是小型项目或初学者。",[42,1306,1307,1309],{},[13,1308,800],{},"：适合国内开发者，解决 npm 安装速度慢的问题。",[42,1311,1312,1314],{},[13,1313,803],{},"：主要用于阿里巴巴内部项目。",[42,1316,1317,1319],{},[13,1318,806],{},"：适合大型项目，尤其是需要工作区支持的项目。",[42,1321,1322,1324],{},[13,1323,809],{},"：适合磁盘空间有限的项目，或需要高效依赖管理的场景。",[10,1326,1327],{},"根据你的项目需求和环境选择合适的工具即可！",[789,1329,1331],{"id":1330},"包管理仓库","包管理仓库：",[10,1333,1334,16,1337,1340],{},[608,1335,1336],{},"npm registry",[608,1338,1339],{},"taobao registry"," 是 JavaScript 生态中两个常用的包管理仓库。它们的主要区别在于服务器位置、同步机制和使用场景。以下是它们的详细对比：",[22,1342],{},[25,1344,1346],{"id":1345},"_1-npm-registry",[13,1347,1348],{},"1. npm registry",[39,1350,1351,1360,1364,1379],{},[42,1352,1353,47,1356],{},[13,1354,1355],{},"官方地址",[82,1357,1358],{"href":1358,"rel":1359},"https:\u002F\u002Fregistry.npmjs.org\u002F",[86],[42,1361,1362,832],{},[13,1363,831],{},[42,1365,1366,361,1368],{},[13,1367,71],{},[39,1369,1370,1373,1376],{},[42,1371,1372],{},"是 npm 的官方包管理仓库，拥有最大的包生态系统。",[42,1374,1375],{},"所有 npm 包都会首先发布到 npm registry。",[42,1377,1378],{},"支持私有包发布和管理。",[42,1380,1381,361,1383],{},[13,1382,863],{},[39,1384,1385,1388],{},[42,1386,1387],{},"服务器位于国外，国内开发者访问速度较慢。",[42,1389,1390],{},"在某些地区可能受到网络限制。",[22,1392],{},[25,1394,1396],{"id":1395},"_2-taobao-registry",[13,1397,1398],{},"2. taobao registry",[39,1400,1401,1409,1413,1431],{},[42,1402,1403,47,1405],{},[13,1404,1355],{},[82,1406,1407],{"href":1407,"rel":1408},"https:\u002F\u002Fregistry.npmmirror.com\u002F",[86],[42,1410,1411,911],{},[13,1412,831],{},[42,1414,1415,361,1417],{},[13,1416,71],{},[39,1418,1419,1422,1425,1428],{},[42,1420,1421],{},"是 npm registry 的国内镜像，专为中国开发者优化。",[42,1423,1424],{},"服务器位于国内，访问速度快。",[42,1426,1427],{},"定期与 npm registry 同步，确保包的最新性。",[42,1429,1430],{},"支持 npm 的所有功能。",[42,1432,1433,361,1435],{},[13,1434,863],{},[39,1436,1437,1440],{},[42,1438,1439],{},"由于是镜像，可能存在同步延迟（通常几分钟到几小时）。",[42,1441,1442],{},"不支持私有包发布（私有包需要切换到 npm registry）。",[22,1444],{},[25,1446,1448],{"id":1447},"_3-主要区别",[13,1449,1450],{},"3. 主要区别",[647,1452,1453,1463],{},[650,1454,1455],{},[653,1456,1457,1459,1461],{},[656,1458,659],{"align":658},[656,1460,1336],{"align":658},[656,1462,1339],{"align":658},[665,1464,1465,1478,1491,1504,1515],{},[653,1466,1467,1472,1475],{},[670,1468,1469],{"align":658},[13,1470,1471],{},"服务器位置",[670,1473,1474],{"align":658},"国外",[670,1476,1477],{"align":658},"国内",[653,1479,1480,1485,1488],{},[670,1481,1482],{"align":658},[13,1483,1484],{},"访问速度",[670,1486,1487],{"align":658},"较慢（国内用户）",[670,1489,1490],{"align":658},"快（国内用户）",[653,1492,1493,1498,1501],{},[670,1494,1495],{"align":658},[13,1496,1497],{},"同步机制",[670,1499,1500],{"align":658},"官方源",[670,1502,1503],{"align":658},"定期与 npm registry 同步",[653,1505,1506,1511,1513],{},[670,1507,1508],{"align":658},[13,1509,1510],{},"私有包支持",[670,1512,1241],{"align":658},[670,1514,1244],{"align":658},[653,1516,1517,1521,1524],{},[670,1518,1519],{"align":658},[13,1520,1274],{},[670,1522,1523],{"align":658},"全球用户",[670,1525,1526],{"align":658},"国内用户",[22,1528],{},[25,1530,1532],{"id":1531},"_4-如何使用-taobao-registry",[13,1533,1534],{},"4. 如何使用 taobao registry",[32,1536,1538],{"id":1537},"_41-临时使用",[13,1539,1540],{},"4.1 临时使用",[39,1542,1543],{},[42,1544,1545,1546,883,1548,631,1550],{},"在安装包时指定 registry：",[78,1547],{},[78,1549],{},[601,1551,1554],{"className":1552,"code":1553,"language":606},[604],"npm install \u003Cpackage> --registry=https:\u002F\u002Fregistry.npmmirror.com\n",[608,1555,1553],{"__ignoreMap":610},[32,1557,1559],{"id":1558},"_42-永久切换",[13,1560,1561],{},"4.2 永久切换",[39,1563,1564],{},[42,1565,1566,1567,883,1569,631,1571],{},"通过 npm 配置命令切换 registry：",[78,1568],{},[78,1570],{},[601,1572,1575],{"className":1573,"code":1574,"language":606},[604],"npm config set registry https:\u002F\u002Fregistry.npmmirror.com\n",[608,1576,1574],{"__ignoreMap":610},[32,1578,1580],{"id":1579},"_43-恢复默认-registry",[13,1581,1582],{},"4.3 恢复默认 registry",[39,1584,1585],{},[42,1586,1587,1588,883,1590,631,1592],{},"如果需要恢复默认的 npm registry，可以运行：",[78,1589],{},[78,1591],{},[601,1593,1596],{"className":1594,"code":1595,"language":606},[604],"npm config set registry https:\u002F\u002Fregistry.npmjs.org\n",[608,1597,1595],{"__ignoreMap":610},[22,1599],{},[25,1601,1603],{"id":1602},"_5-总结",[13,1604,1605],{},"5. 总结",[39,1607,1608,1613],{},[42,1609,1610,1612],{},[13,1611,1336],{}," 是官方的包管理仓库，适合全球用户，但国内访问速度较慢。",[42,1614,1615,1617],{},[13,1616,1339],{}," 是 npm registry 的国内镜像，适合国内用户，访问速度快，但不支持私有包发布。",[10,1619,1620],{},"根据你的网络环境和需求选择合适的 registry 即可！",[10,1622,1623,1624,1627],{},"注：使用 bun 初始化项目会更快，需要 bun >= ",[608,1625,1626],{},"0.4.0"," 版本。",[10,1629,1630,1631,1634,1635,1638],{},"国内建议选 ",[13,1632,1633],{},"pnpm + taobao 源","，速度提升明显。这一步会自动安装依赖，同时安装成功后会自动执行 ",[608,1636,1637],{},"umi setup"," 做一些文件预处理等工作。",[25,1640,1641],{"id":1641},"部署发布",[10,1643,1644,1645,1648],{},"执行 ",[608,1646,1647],{},"pnpm build"," 命令，",[601,1650,1653],{"className":1651,"code":1652,"language":883,"meta":610,"style":610},"language-bash shiki shiki-themes github-light github-dark","> umi build\n\nevent - compiled successfully in 1179 ms (567 modules)\n\nevent - build index.html\n",[608,1654,1655,1668,1675,1711,1716],{"__ignoreMap":610},[1656,1657,1660,1664],"span",{"class":1658,"line":1659},"line",1,[1656,1661,1663],{"class":1662},"szBVR",">",[1656,1665,1667],{"class":1666},"sVt8B"," umi build\n",[1656,1669,1671],{"class":1658,"line":1670},2,[1656,1672,1674],{"emptyLinePlaceholder":1673},true,"\n",[1656,1676,1678,1682,1686,1689,1692,1695,1699,1702,1705,1708],{"class":1658,"line":1677},3,[1656,1679,1681],{"class":1680},"sScJk","event",[1656,1683,1685],{"class":1684},"sZZnC"," -",[1656,1687,1688],{"class":1684}," compiled",[1656,1690,1691],{"class":1684}," successfully",[1656,1693,1694],{"class":1684}," in",[1656,1696,1698],{"class":1697},"sj4cs"," 1179",[1656,1700,1701],{"class":1684}," ms",[1656,1703,1704],{"class":1666}," (567 ",[1656,1706,1707],{"class":1684},"modules",[1656,1709,1710],{"class":1666},")\n",[1656,1712,1714],{"class":1658,"line":1713},4,[1656,1715,1674],{"emptyLinePlaceholder":1673},[1656,1717,1719,1721,1723,1726],{"class":1658,"line":1718},5,[1656,1720,1681],{"class":1680},[1656,1722,1685],{"class":1684},[1656,1724,1725],{"class":1684}," build",[1656,1727,1728],{"class":1684}," index.html\n",[10,1730,1731,1732,1735],{},"产物默认会生成到 ",[608,1733,1734],{},".\u002Fdist"," 目录下，",[789,1737,1739],{"id":1738},"prettier","Prettier",[10,1741,1742],{},[13,1743,1744,1745],{},"如果需要用 prettier 做项目代码的自动格式化，执行 ",[608,1746,1747],{},"pnpm umi g",[10,1749,1750,1751,1753],{},"使用 ",[13,1752,1739],{}," 来自动格式化项目代码有很多优点，尤其是在团队开发和大规模项目中。下面是一些主要的优点：",[32,1755,1757,1758],{"id":1756},"_1-统一的代码风格","1. ",[13,1759,1760],{},"统一的代码风格",[39,1762,1763,1769],{},[42,1764,1765,1768],{},[13,1766,1767],{},"消除代码风格争议","：Prettier 自动格式化代码，使得所有开发者的代码风格统一，避免了团队内部关于空格、缩进、行长度等细节的争论。",[42,1770,1771,1774],{},[13,1772,1773],{},"可配置性","：Prettier 提供了很多配置选项，允许你根据项目的需要调整格式（例如行宽、缩进方式等）。这样可以根据团队的偏好进行统一配置。",[32,1776,1778,1779],{"id":1777},"_2-提高代码可读性","2. ",[13,1780,1781],{},"提高代码可读性",[39,1783,1784],{},[42,1785,1786],{},"代码格式统一后，不同开发者写的代码会呈现出一致的结构，增强了代码的可读性和可维护性，尤其是在多人协作时，代码的可读性显得尤为重要。",[32,1788,1790,1791],{"id":1789},"_3-减少手动格式化工作","3. ",[13,1792,1793],{},"减少手动格式化工作",[39,1795,1796],{},[42,1797,1798],{},"使用 Prettier 后，开发者不再需要花时间手动调整代码格式，例如调整缩进、对齐等。Prettier 会自动完成这些工作，让开发者可以更专注于功能实现和逻辑编写。",[32,1800,1802,1803],{"id":1801},"_4-自动修复格式问题","4. ",[13,1804,1805],{},"自动修复格式问题",[39,1807,1808],{},[42,1809,1810],{},"Prettier 会自动格式化所有不符合标准的代码，不仅仅是新写的代码，还包括已有的代码。只要运行 Prettier，它会修复格式问题，保持代码库的一致性。",[32,1812,1814,1815],{"id":1813},"_5-减少合并冲突","5. ",[13,1816,1817],{},"减少合并冲突",[39,1819,1820],{},[42,1821,1822],{},"在团队合作时，由于格式化规则不统一，可能会出现大量的无意义的合并冲突（例如空格或换行不同）。Prettier 自动格式化的机制能够减少这种冲突，因为它确保所有开发者使用相同的格式规则，减少因格式差异引发的冲突。",[32,1824,1826,1827],{"id":1825},"_6-提高开发效率","6. ",[13,1828,1829],{},"提高开发效率",[39,1831,1832],{},[42,1833,1834],{},"团队成员不需要花时间去讨论和审查代码格式问题，Prettier 会自动统一，代码审查可以集中在代码逻辑和功能上，提升开发效率和代码质量。",[32,1836,1838,1839],{"id":1837},"_7-与编辑器集成","7. ",[13,1840,1841],{},"与编辑器集成",[39,1843,1844],{},[42,1845,1846],{},"Prettier 可以与常用的代码编辑器（如 VSCode、WebStorm 等）集成，使得开发者在保存文件时自动格式化代码。通过这种方式，你无需手动运行格式化工具，Prettier 会在每次保存时自动修复格式问题。",[32,1848,1850,1851],{"id":1849},"_8-支持多种语言","8. ",[13,1852,1853],{},"支持多种语言",[39,1855,1856],{},[42,1857,1858],{},"Prettier 支持多种语言和文件类型（如 JavaScript、TypeScript、HTML、CSS、JSON、Markdown、YAML 等），因此在全栈项目中，它能够保持各个语言之间的格式一致性。",[32,1860,1862,1863],{"id":1861},"_9-减轻代码审查的负担","9. ",[13,1864,1865],{},"减轻代码审查的负担",[39,1867,1868],{},[42,1869,1870],{},"代码审查时，Prettier 的使用让审查者能够专注于业务逻辑和代码质量，而不是纠结于代码风格问题。减少了代码审查过程中的冗余讨论，提高了审查效率。",[32,1872,1874,1875],{"id":1873},"_10-可与其他工具协同工作","10. ",[13,1876,1877],{},"可与其他工具协同工作",[39,1879,1880],{},[42,1881,1882],{},"Prettier 可以与其他静态分析工具（如 ESLint、TSLint 等）一起使用。比如，Prettier 可以专注于格式化，而 ESLint 可以专注于代码质量检查。两者协同工作能够全面提升代码质量。",[789,1884,1885],{"id":1885},"目录结构",[10,1887,1888],{},"这里罗列了 Umi 项目中约定（或推荐）的目录结构，在项目开发中，请遵照这个目录结构组织代码。",[601,1890,1892],{"className":1651,"code":1891,"language":883,"meta":610,"style":610},".\n\n├── config\n\n│   └── config.ts\n\n├── dist \n\n├── mock \u002F\u002Fmock数据\n\n│   └── app.ts｜tsx\n\n├── src\n\n│   ├── .umi  \u002F\u002F编译后自动生成的文件\n\n│   ├── .umi-production\n\n│   ├── layouts\n\n│   │   ├── BasicLayout.tsx\n\n│   │   ├── index.less\n\n│   ├── models\n\n│   │   ├── global.ts\n\n│   │   └── index.ts\n\n│   ├── pages \u002F\u002F业务组件文件夹（页面）\n\n│   │   ├── index.less\n\n│   │   └── index.tsx \u002F\u002F业务组件\n\n│   ├── utils \u002F\u002F 推荐目录\n\n│   │   └── index.ts\n\n│   ├── services \u002F\u002F 推荐目录\n\n│   │   └── api.ts\n\n│   ├── app.(ts|tsx)\n\n│   ├── global.ts\n\n│   ├── global.(css|less|sass|scss)\n\n│   ├── overrides.(css|less|sass|scss)\n\n│   ├── favicon.(ico|gif|png|jpg|jpeg|svg|avif|webp)\n\n│   └── loading.(tsx|jsx)\n\n├── node_modules\n\n│   └── .cache\n\n│       ├── bundler-webpack\n\n│       ├── mfsu\n\n│       └── mfsu-deps\n\n├── .env \u002F\u002F环境参数文件\n\n├── plugin.ts \n\n├── .umirc.ts \u002F\u002F 与 config\u002Fconfig 文件 2 选一 核心配置文件\n\n├── package.json \u002F\u002F项目基本信息，依赖信息\n\n├── tsconfig.json\n\n└── typings.d.ts\n",[608,1893,1894,1899,1903,1911,1915,1926,1931,1942,1947,1958,1963,1973,1978,1986,1991,2005,2010,2020,2025,2035,2040,2053,2058,2070,2075,2085,2090,2102,2107,2119,2124,2137,2142,2153,2158,2173,2178,2194,2199,2210,2215,2229,2234,2246,2251,2275,2280,2289,2294,2326,2331,2359,2364,2416,2421,2442,2447,2455,2460,2470,2475,2486,2491,2501,2506,2517,2522,2533,2538,2548,2553,2581,2586,2597,2602,2610,2615],{"__ignoreMap":610},[1656,1895,1896],{"class":1658,"line":1659},[1656,1897,1898],{"class":1697},".\n",[1656,1900,1901],{"class":1658,"line":1670},[1656,1902,1674],{"emptyLinePlaceholder":1673},[1656,1904,1905,1908],{"class":1658,"line":1677},[1656,1906,1907],{"class":1680},"├──",[1656,1909,1910],{"class":1684}," config\n",[1656,1912,1913],{"class":1658,"line":1713},[1656,1914,1674],{"emptyLinePlaceholder":1673},[1656,1916,1917,1920,1923],{"class":1658,"line":1718},[1656,1918,1919],{"class":1680},"│",[1656,1921,1922],{"class":1684},"   └──",[1656,1924,1925],{"class":1684}," config.ts\n",[1656,1927,1929],{"class":1658,"line":1928},6,[1656,1930,1674],{"emptyLinePlaceholder":1673},[1656,1932,1934,1936,1939],{"class":1658,"line":1933},7,[1656,1935,1907],{"class":1680},[1656,1937,1938],{"class":1684}," dist",[1656,1940,1941],{"class":1666}," \n",[1656,1943,1945],{"class":1658,"line":1944},8,[1656,1946,1674],{"emptyLinePlaceholder":1673},[1656,1948,1950,1952,1955],{"class":1658,"line":1949},9,[1656,1951,1907],{"class":1680},[1656,1953,1954],{"class":1684}," mock",[1656,1956,1957],{"class":1684}," \u002F\u002Fmock数据\n",[1656,1959,1961],{"class":1658,"line":1960},10,[1656,1962,1674],{"emptyLinePlaceholder":1673},[1656,1964,1966,1968,1970],{"class":1658,"line":1965},11,[1656,1967,1919],{"class":1680},[1656,1969,1922],{"class":1684},[1656,1971,1972],{"class":1684}," app.ts｜tsx\n",[1656,1974,1976],{"class":1658,"line":1975},12,[1656,1977,1674],{"emptyLinePlaceholder":1673},[1656,1979,1981,1983],{"class":1658,"line":1980},13,[1656,1982,1907],{"class":1680},[1656,1984,1985],{"class":1684}," src\n",[1656,1987,1989],{"class":1658,"line":1988},14,[1656,1990,1674],{"emptyLinePlaceholder":1673},[1656,1992,1994,1996,1999,2002],{"class":1658,"line":1993},15,[1656,1995,1919],{"class":1680},[1656,1997,1998],{"class":1684},"   ├──",[1656,2000,2001],{"class":1684}," .umi",[1656,2003,2004],{"class":1684},"  \u002F\u002F编译后自动生成的文件\n",[1656,2006,2008],{"class":1658,"line":2007},16,[1656,2009,1674],{"emptyLinePlaceholder":1673},[1656,2011,2013,2015,2017],{"class":1658,"line":2012},17,[1656,2014,1919],{"class":1680},[1656,2016,1998],{"class":1684},[1656,2018,2019],{"class":1684}," .umi-production\n",[1656,2021,2023],{"class":1658,"line":2022},18,[1656,2024,1674],{"emptyLinePlaceholder":1673},[1656,2026,2028,2030,2032],{"class":1658,"line":2027},19,[1656,2029,1919],{"class":1680},[1656,2031,1998],{"class":1684},[1656,2033,2034],{"class":1684}," layouts\n",[1656,2036,2038],{"class":1658,"line":2037},20,[1656,2039,1674],{"emptyLinePlaceholder":1673},[1656,2041,2043,2045,2048,2050],{"class":1658,"line":2042},21,[1656,2044,1919],{"class":1680},[1656,2046,2047],{"class":1684},"   │",[1656,2049,1998],{"class":1684},[1656,2051,2052],{"class":1684}," BasicLayout.tsx\n",[1656,2054,2056],{"class":1658,"line":2055},22,[1656,2057,1674],{"emptyLinePlaceholder":1673},[1656,2059,2061,2063,2065,2067],{"class":1658,"line":2060},23,[1656,2062,1919],{"class":1680},[1656,2064,2047],{"class":1684},[1656,2066,1998],{"class":1684},[1656,2068,2069],{"class":1684}," index.less\n",[1656,2071,2073],{"class":1658,"line":2072},24,[1656,2074,1674],{"emptyLinePlaceholder":1673},[1656,2076,2078,2080,2082],{"class":1658,"line":2077},25,[1656,2079,1919],{"class":1680},[1656,2081,1998],{"class":1684},[1656,2083,2084],{"class":1684}," models\n",[1656,2086,2088],{"class":1658,"line":2087},26,[1656,2089,1674],{"emptyLinePlaceholder":1673},[1656,2091,2093,2095,2097,2099],{"class":1658,"line":2092},27,[1656,2094,1919],{"class":1680},[1656,2096,2047],{"class":1684},[1656,2098,1998],{"class":1684},[1656,2100,2101],{"class":1684}," global.ts\n",[1656,2103,2105],{"class":1658,"line":2104},28,[1656,2106,1674],{"emptyLinePlaceholder":1673},[1656,2108,2110,2112,2114,2116],{"class":1658,"line":2109},29,[1656,2111,1919],{"class":1680},[1656,2113,2047],{"class":1684},[1656,2115,1922],{"class":1684},[1656,2117,2118],{"class":1684}," index.ts\n",[1656,2120,2122],{"class":1658,"line":2121},30,[1656,2123,1674],{"emptyLinePlaceholder":1673},[1656,2125,2127,2129,2131,2134],{"class":1658,"line":2126},31,[1656,2128,1919],{"class":1680},[1656,2130,1998],{"class":1684},[1656,2132,2133],{"class":1684}," pages",[1656,2135,2136],{"class":1684}," \u002F\u002F业务组件文件夹（页面）\n",[1656,2138,2140],{"class":1658,"line":2139},32,[1656,2141,1674],{"emptyLinePlaceholder":1673},[1656,2143,2145,2147,2149,2151],{"class":1658,"line":2144},33,[1656,2146,1919],{"class":1680},[1656,2148,2047],{"class":1684},[1656,2150,1998],{"class":1684},[1656,2152,2069],{"class":1684},[1656,2154,2156],{"class":1658,"line":2155},34,[1656,2157,1674],{"emptyLinePlaceholder":1673},[1656,2159,2161,2163,2165,2167,2170],{"class":1658,"line":2160},35,[1656,2162,1919],{"class":1680},[1656,2164,2047],{"class":1684},[1656,2166,1922],{"class":1684},[1656,2168,2169],{"class":1684}," index.tsx",[1656,2171,2172],{"class":1684}," \u002F\u002F业务组件\n",[1656,2174,2176],{"class":1658,"line":2175},36,[1656,2177,1674],{"emptyLinePlaceholder":1673},[1656,2179,2181,2183,2185,2188,2191],{"class":1658,"line":2180},37,[1656,2182,1919],{"class":1680},[1656,2184,1998],{"class":1684},[1656,2186,2187],{"class":1684}," utils",[1656,2189,2190],{"class":1684}," \u002F\u002F",[1656,2192,2193],{"class":1684}," 推荐目录\n",[1656,2195,2197],{"class":1658,"line":2196},38,[1656,2198,1674],{"emptyLinePlaceholder":1673},[1656,2200,2202,2204,2206,2208],{"class":1658,"line":2201},39,[1656,2203,1919],{"class":1680},[1656,2205,2047],{"class":1684},[1656,2207,1922],{"class":1684},[1656,2209,2118],{"class":1684},[1656,2211,2213],{"class":1658,"line":2212},40,[1656,2214,1674],{"emptyLinePlaceholder":1673},[1656,2216,2218,2220,2222,2225,2227],{"class":1658,"line":2217},41,[1656,2219,1919],{"class":1680},[1656,2221,1998],{"class":1684},[1656,2223,2224],{"class":1684}," services",[1656,2226,2190],{"class":1684},[1656,2228,2193],{"class":1684},[1656,2230,2232],{"class":1658,"line":2231},42,[1656,2233,1674],{"emptyLinePlaceholder":1673},[1656,2235,2237,2239,2241,2243],{"class":1658,"line":2236},43,[1656,2238,1919],{"class":1680},[1656,2240,2047],{"class":1684},[1656,2242,1922],{"class":1684},[1656,2244,2245],{"class":1684}," api.ts\n",[1656,2247,2249],{"class":1658,"line":2248},44,[1656,2250,1674],{"emptyLinePlaceholder":1673},[1656,2252,2254,2256,2258,2261,2264,2267,2270,2273],{"class":1658,"line":2253},45,[1656,2255,1919],{"class":1680},[1656,2257,1998],{"class":1684},[1656,2259,2260],{"class":1684}," app.",[1656,2262,2263],{"class":1666},"(",[1656,2265,2266],{"class":1680},"ts",[1656,2268,2269],{"class":1662},"|",[1656,2271,2272],{"class":1680},"tsx",[1656,2274,1710],{"class":1666},[1656,2276,2278],{"class":1658,"line":2277},46,[1656,2279,1674],{"emptyLinePlaceholder":1673},[1656,2281,2283,2285,2287],{"class":1658,"line":2282},47,[1656,2284,1919],{"class":1680},[1656,2286,1998],{"class":1684},[1656,2288,2101],{"class":1684},[1656,2290,2292],{"class":1658,"line":2291},48,[1656,2293,1674],{"emptyLinePlaceholder":1673},[1656,2295,2297,2299,2301,2304,2306,2309,2311,2314,2316,2319,2321,2324],{"class":1658,"line":2296},49,[1656,2298,1919],{"class":1680},[1656,2300,1998],{"class":1684},[1656,2302,2303],{"class":1684}," global.",[1656,2305,2263],{"class":1666},[1656,2307,2308],{"class":1680},"css",[1656,2310,2269],{"class":1662},[1656,2312,2313],{"class":1680},"less",[1656,2315,2269],{"class":1662},[1656,2317,2318],{"class":1680},"sass",[1656,2320,2269],{"class":1662},[1656,2322,2323],{"class":1680},"scss",[1656,2325,1710],{"class":1666},[1656,2327,2329],{"class":1658,"line":2328},50,[1656,2330,1674],{"emptyLinePlaceholder":1673},[1656,2332,2334,2336,2338,2341,2343,2345,2347,2349,2351,2353,2355,2357],{"class":1658,"line":2333},51,[1656,2335,1919],{"class":1680},[1656,2337,1998],{"class":1684},[1656,2339,2340],{"class":1684}," overrides.",[1656,2342,2263],{"class":1666},[1656,2344,2308],{"class":1680},[1656,2346,2269],{"class":1662},[1656,2348,2313],{"class":1680},[1656,2350,2269],{"class":1662},[1656,2352,2318],{"class":1680},[1656,2354,2269],{"class":1662},[1656,2356,2323],{"class":1680},[1656,2358,1710],{"class":1666},[1656,2360,2362],{"class":1658,"line":2361},52,[1656,2363,1674],{"emptyLinePlaceholder":1673},[1656,2365,2367,2369,2371,2374,2376,2379,2381,2384,2386,2389,2391,2394,2396,2399,2401,2404,2406,2409,2411,2414],{"class":1658,"line":2366},53,[1656,2368,1919],{"class":1680},[1656,2370,1998],{"class":1684},[1656,2372,2373],{"class":1684}," favicon.",[1656,2375,2263],{"class":1666},[1656,2377,2378],{"class":1680},"ico",[1656,2380,2269],{"class":1662},[1656,2382,2383],{"class":1680},"gif",[1656,2385,2269],{"class":1662},[1656,2387,2388],{"class":1680},"png",[1656,2390,2269],{"class":1662},[1656,2392,2393],{"class":1680},"jpg",[1656,2395,2269],{"class":1662},[1656,2397,2398],{"class":1680},"jpeg",[1656,2400,2269],{"class":1662},[1656,2402,2403],{"class":1680},"svg",[1656,2405,2269],{"class":1662},[1656,2407,2408],{"class":1680},"avif",[1656,2410,2269],{"class":1662},[1656,2412,2413],{"class":1680},"webp",[1656,2415,1710],{"class":1666},[1656,2417,2419],{"class":1658,"line":2418},54,[1656,2420,1674],{"emptyLinePlaceholder":1673},[1656,2422,2424,2426,2428,2431,2433,2435,2437,2440],{"class":1658,"line":2423},55,[1656,2425,1919],{"class":1680},[1656,2427,1922],{"class":1684},[1656,2429,2430],{"class":1684}," loading.",[1656,2432,2263],{"class":1666},[1656,2434,2272],{"class":1680},[1656,2436,2269],{"class":1662},[1656,2438,2439],{"class":1680},"jsx",[1656,2441,1710],{"class":1666},[1656,2443,2445],{"class":1658,"line":2444},56,[1656,2446,1674],{"emptyLinePlaceholder":1673},[1656,2448,2450,2452],{"class":1658,"line":2449},57,[1656,2451,1907],{"class":1680},[1656,2453,2454],{"class":1684}," node_modules\n",[1656,2456,2458],{"class":1658,"line":2457},58,[1656,2459,1674],{"emptyLinePlaceholder":1673},[1656,2461,2463,2465,2467],{"class":1658,"line":2462},59,[1656,2464,1919],{"class":1680},[1656,2466,1922],{"class":1684},[1656,2468,2469],{"class":1684}," .cache\n",[1656,2471,2473],{"class":1658,"line":2472},60,[1656,2474,1674],{"emptyLinePlaceholder":1673},[1656,2476,2478,2480,2483],{"class":1658,"line":2477},61,[1656,2479,1919],{"class":1680},[1656,2481,2482],{"class":1684},"       ├──",[1656,2484,2485],{"class":1684}," bundler-webpack\n",[1656,2487,2489],{"class":1658,"line":2488},62,[1656,2490,1674],{"emptyLinePlaceholder":1673},[1656,2492,2494,2496,2498],{"class":1658,"line":2493},63,[1656,2495,1919],{"class":1680},[1656,2497,2482],{"class":1684},[1656,2499,2500],{"class":1684}," mfsu\n",[1656,2502,2504],{"class":1658,"line":2503},64,[1656,2505,1674],{"emptyLinePlaceholder":1673},[1656,2507,2509,2511,2514],{"class":1658,"line":2508},65,[1656,2510,1919],{"class":1680},[1656,2512,2513],{"class":1684},"       └──",[1656,2515,2516],{"class":1684}," mfsu-deps\n",[1656,2518,2520],{"class":1658,"line":2519},66,[1656,2521,1674],{"emptyLinePlaceholder":1673},[1656,2523,2525,2527,2530],{"class":1658,"line":2524},67,[1656,2526,1907],{"class":1680},[1656,2528,2529],{"class":1684}," .env",[1656,2531,2532],{"class":1684}," \u002F\u002F环境参数文件\n",[1656,2534,2536],{"class":1658,"line":2535},68,[1656,2537,1674],{"emptyLinePlaceholder":1673},[1656,2539,2541,2543,2546],{"class":1658,"line":2540},69,[1656,2542,1907],{"class":1680},[1656,2544,2545],{"class":1684}," plugin.ts",[1656,2547,1941],{"class":1666},[1656,2549,2551],{"class":1658,"line":2550},70,[1656,2552,1674],{"emptyLinePlaceholder":1673},[1656,2554,2556,2558,2561,2563,2566,2569,2572,2575,2578],{"class":1658,"line":2555},71,[1656,2557,1907],{"class":1680},[1656,2559,2560],{"class":1684}," .umirc.ts",[1656,2562,2190],{"class":1684},[1656,2564,2565],{"class":1684}," 与",[1656,2567,2568],{"class":1684}," config\u002Fconfig",[1656,2570,2571],{"class":1684}," 文件",[1656,2573,2574],{"class":1697}," 2",[1656,2576,2577],{"class":1684}," 选一",[1656,2579,2580],{"class":1684}," 核心配置文件\n",[1656,2582,2584],{"class":1658,"line":2583},72,[1656,2585,1674],{"emptyLinePlaceholder":1673},[1656,2587,2589,2591,2594],{"class":1658,"line":2588},73,[1656,2590,1907],{"class":1680},[1656,2592,2593],{"class":1684}," package.json",[1656,2595,2596],{"class":1684}," \u002F\u002F项目基本信息，依赖信息\n",[1656,2598,2600],{"class":1658,"line":2599},74,[1656,2601,1674],{"emptyLinePlaceholder":1673},[1656,2603,2605,2607],{"class":1658,"line":2604},75,[1656,2606,1907],{"class":1680},[1656,2608,2609],{"class":1684}," tsconfig.json\n",[1656,2611,2613],{"class":1658,"line":2612},76,[1656,2614,1674],{"emptyLinePlaceholder":1673},[1656,2616,2618,2621],{"class":1658,"line":2617},77,[1656,2619,2620],{"class":1680},"└──",[1656,2622,2623],{"class":1684}," typings.d.ts\n",[25,2625,2626],{"id":2626},"根目录",[32,2628,2630],{"id":2629},"packagejson","package.json",[10,2632,2633,2634,2636,2637,797,2640,797,2643,16,2646,2649,2650,2657],{},"与 Umi 3 不同，Umi 4 不会自动注册 ",[608,2635,2630],{}," 中以 ",[608,2638,2639],{},"@umijs\u002Fpreset-",[608,2641,2642],{},"@umijs\u002Fplugin-",[608,2644,2645],{},"umi-preset-",[608,2647,2648],{},"umi-plugin-"," 开头的插件、预设，若你需要自定义额外的插件、预设，需要手动配置到 ",[82,2651,2654],{"href":2652,"rel":2653},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fconfig#plugins",[86],[608,2655,2656],{},"plugins"," 。",[32,2659,2661],{"id":2660},"env",".env",[10,2663,2664],{},"环境变量，比如：",[601,2666,2669],{"className":2667,"code":2668,"language":606,"meta":610},[604],"PORT=8888\n\nCOMPRESS=none\n",[608,2670,2668],{"__ignoreMap":610},[32,2672,2674],{"id":2673},"umircts",".umirc.ts",[2676,2677,2678],"blockquote",{},[10,2679,2680,2681,2684,2685,2687],{},"与 ",[608,2682,2683],{},"config\u002Fconfig.ts"," 文件功能相同，2 选 1 。",[608,2686,2674],{}," 文件优先级较高",[10,2689,2690,2691,2696,2697,851],{},"配置文件，包含 Umi 所有",[82,2692,2695],{"href":2693,"rel":2694},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fconfig",[86],"非运行时配置","（运行时配置一般定义于 ",[82,2698,2701],{"href":2699,"rel":2700},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fguides\u002Fdirectory-structure#apptstsx",[86],[608,2702,2703],{},"app.ts",[10,2705,2706,2707,2714],{},"若你需要在不同环境中加载不同配置，这在 Umi 中是根据 ",[82,2708,2711],{"href":2709,"rel":2710},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fguides\u002Fenv-variables#umi_env",[86],[608,2712,2713],{},"UMI_ENV"," 来实现的，一个不同环境启动的例子：",[601,2716,2719],{"className":2717,"code":2718,"language":2266,"meta":610,"style":610},"language-ts shiki shiki-themes github-light github-dark","\u002F\u002F package.json\n\n{\n\n  \"scripts\": {\n\n    \"dev\": \"umi dev\",\n\n    \"dev:pre\": \"cross-env UMI_ENV=pre umi dev\"\n\n  }\n\n}\n",[608,2720,2721,2727,2731,2736,2740,2748,2752,2766,2770,2780,2784,2789,2793],{"__ignoreMap":610},[1656,2722,2723],{"class":1658,"line":1659},[1656,2724,2726],{"class":2725},"sJ8bj","\u002F\u002F package.json\n",[1656,2728,2729],{"class":1658,"line":1670},[1656,2730,1674],{"emptyLinePlaceholder":1673},[1656,2732,2733],{"class":1658,"line":1677},[1656,2734,2735],{"class":1666},"{\n",[1656,2737,2738],{"class":1658,"line":1713},[1656,2739,1674],{"emptyLinePlaceholder":1673},[1656,2741,2742,2745],{"class":1658,"line":1718},[1656,2743,2744],{"class":1684},"  \"scripts\"",[1656,2746,2747],{"class":1666},": {\n",[1656,2749,2750],{"class":1658,"line":1928},[1656,2751,1674],{"emptyLinePlaceholder":1673},[1656,2753,2754,2757,2760,2763],{"class":1658,"line":1933},[1656,2755,2756],{"class":1684},"    \"dev\"",[1656,2758,2759],{"class":1666},": ",[1656,2761,2762],{"class":1684},"\"umi dev\"",[1656,2764,2765],{"class":1666},",\n",[1656,2767,2768],{"class":1658,"line":1944},[1656,2769,1674],{"emptyLinePlaceholder":1673},[1656,2771,2772,2775,2777],{"class":1658,"line":1949},[1656,2773,2774],{"class":1684},"    \"dev:pre\"",[1656,2776,2759],{"class":1666},[1656,2778,2779],{"class":1684},"\"cross-env UMI_ENV=pre umi dev\"\n",[1656,2781,2782],{"class":1658,"line":1960},[1656,2783,1674],{"emptyLinePlaceholder":1673},[1656,2785,2786],{"class":1658,"line":1965},[1656,2787,2788],{"class":1666},"  }\n",[1656,2790,2791],{"class":1658,"line":1975},[1656,2792,1674],{"emptyLinePlaceholder":1673},[1656,2794,2795],{"class":1658,"line":1980},[1656,2796,2797],{"class":1666},"}\n",[32,2799,2683],{"id":2800},"configconfigts",[2676,2802,2803],{},[10,2804,2680,2805,2684,2807,2687],{},[608,2806,2674],{},[608,2808,2674],{},[10,2810,2680,2811,2817,2818,2821],{},[82,2812,2815],{"href":2813,"rel":2814},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fguides\u002Fdirectory-structure#umircts",[86],[608,2816,2674],{}," 相同，区别是你可以单独在一个 ",[608,2819,2820],{},"config"," 文件夹下集中管理所有的配置，保持项目根目录整洁。",[32,2823,2825],{"id":2824},"dist-目录","dist 目录",[10,2827,1644,2828,2831,2832,2839],{},[608,2829,2830],{},"umi build"," 后产物的默认输出文件夹。可通过 ",[82,2833,2836],{"href":2834,"rel":2835},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fconfig#outputpath",[86],[608,2837,2838],{},"outputPath"," 配置修改产物输出文件夹。",[32,2841,2843],{"id":2842},"mock-目录","mock 目录",[10,2845,2846,2847,2850,2851,2854,2855,2657],{},"存放 mock 文件，此目录下所有 ",[608,2848,2849],{},".ts"," \u002F ",[608,2852,2853],{},".js"," 文件会被 mock 服务加载，从而提供模拟数据，使用方法详见 ",[82,2856,2859],{"href":2857,"rel":2858},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fguides\u002Fmock",[86],"Mock",[32,2861,2863],{"id":2862},"public-目录","public 目录",[10,2865,2866,2867,2870,2871,2874],{},"存放固定的静态资源，如存放 ",[608,2868,2869],{},"public\u002Fimage.png"," ，则开发时可以通过 ",[608,2872,2873],{},"\u002Fimage.png"," 访问到，构建后会被拷贝到输出文件夹。",[10,2876,2877],{},"注：",[2879,2880,2881],"ol",{},[42,2882,2883,2884,2889],{},"对于 svg 资源，Umi 支持 ",[82,2885,2888],{"href":2886,"rel":2887},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fconfig#svgr",[86],"svgr"," ，可以直接导入作为组件使用：",[601,2891,2893],{"className":2717,"code":2892,"language":2266,"meta":610,"style":610},"import SmileUrl, { ReactComponent as SvgSmile } from '.\u002Fsmile.svg';\n\n\u002F\u002F \u003CSvgSmile \u002F>\n",[608,2894,2895,2918,2922],{"__ignoreMap":610},[1656,2896,2897,2900,2903,2906,2909,2912,2915],{"class":1658,"line":1659},[1656,2898,2899],{"class":1662},"import",[1656,2901,2902],{"class":1666}," SmileUrl, { ReactComponent ",[1656,2904,2905],{"class":1662},"as",[1656,2907,2908],{"class":1666}," SvgSmile } ",[1656,2910,2911],{"class":1662},"from",[1656,2913,2914],{"class":1684}," '.\u002Fsmile.svg'",[1656,2916,2917],{"class":1666},";\n",[1656,2919,2920],{"class":1658,"line":1670},[1656,2921,1674],{"emptyLinePlaceholder":1673},[1656,2923,2924],{"class":1658,"line":1677},[1656,2925,2926],{"class":2725},"\u002F\u002F \u003CSvgSmile \u002F>\n",[2879,2928,2929],{},[42,2930,2931],{},"对于图片等资源，Umi 支持直接导入获取资源路径：",[601,2933,2936],{"className":2934,"code":2935,"language":2272,"meta":610,"style":610},"language-tsx shiki shiki-themes github-light github-dark","import imgUrl from '.\u002Fimage.png'\n\n\u002F\u002F \u003Cimg src={imgUrl} \u002F>>\n",[608,2937,2938,2950,2954],{"__ignoreMap":610},[1656,2939,2940,2942,2945,2947],{"class":1658,"line":1659},[1656,2941,2899],{"class":1662},[1656,2943,2944],{"class":1666}," imgUrl ",[1656,2946,2911],{"class":1662},[1656,2948,2949],{"class":1684}," '.\u002Fimage.png'\n",[1656,2951,2952],{"class":1658,"line":1670},[1656,2953,1674],{"emptyLinePlaceholder":1673},[1656,2955,2956],{"class":1658,"line":1677},[1656,2957,2958],{"class":2725},"\u002F\u002F \u003Cimg src={imgUrl} \u002F>>\n",[32,2960,2962,2965],{"id":2961},"src-目录",[608,2963,2964],{},"src"," 目录",[2967,2968,2970],"h4",{"id":2969},"umi-目录",".umi 目录",[2967,2972,2974],{"id":2973},"️","🛎️",[10,2976,2977],{},[13,2978,2979,2980,2983,2984,2987],{},"不要提交 ",[608,2981,2982],{},".umi"," 临时文件到 git 仓库，默认已在 ",[608,2985,2986],{},".gitignore"," 被忽略。",[10,2989,2990],{},"dev 时的临时文件目录，比如入口文件、路由等，都会被临时生成到这里。",[2967,2992,2994],{"id":2993},"umi-production-目录",".umi-production 目录",[2967,2996,2974],{"id":2997},"️-1",[10,2999,3000],{},[13,3001,2979,3002,2983,3005,2987],{},[608,3003,3004],{},".umi-production",[608,3006,2986],{},[10,3008,3009],{},"build 时的临时文件目录，比如入口文件、路由等，都会被临时生成到这里。",[2967,3011,3013,3014],{"id":3012},"apptstsx","app.",[1656,3015,3016],{},"ts｜tsx",[10,3018,3019,3024],{},[82,3020,3023],{"href":3021,"rel":3022},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fruntime-config",[86],"运行时配置"," 文件，可以在这里扩展运行时的能力，比如修改路由、修改 render 方法等。",[10,3026,3027],{},"运行时配置带来的逻辑会在浏览器中运行，因此当有远程配置、动态内容时，这些我们在本地开发时还不确定，不能写死，所以需要在浏览器实际运行项目时动态获取他们。",[2967,3029,3031],{"id":3030},"layoutsindextsx","layouts\u002Findex.tsx",[10,3033,3034,3037],{},[13,3035,3036],{},"全局布局，默认会在所有路由下生效","，比如有以下路由关系：",[601,3039,3043],{"className":3040,"code":3041,"language":3042,"meta":610,"style":610},"language-undefined shiki shiki-themes github-light github-dark","[\n\n  { path: '\u002F', component: '@\u002Fpages\u002Findex' },\n\n  { path: '\u002Fusers', component: '@\u002Fpages\u002Fusers' },\n\n]\n","undefined",[608,3044,3045,3050,3054,3059,3063,3068,3072],{"__ignoreMap":610},[1656,3046,3047],{"class":1658,"line":1659},[1656,3048,3049],{},"[\n",[1656,3051,3052],{"class":1658,"line":1670},[1656,3053,1674],{"emptyLinePlaceholder":1673},[1656,3055,3056],{"class":1658,"line":1677},[1656,3057,3058],{},"  { path: '\u002F', component: '@\u002Fpages\u002Findex' },\n",[1656,3060,3061],{"class":1658,"line":1713},[1656,3062,1674],{"emptyLinePlaceholder":1673},[1656,3064,3065],{"class":1658,"line":1718},[1656,3066,3067],{},"  { path: '\u002Fusers', component: '@\u002Fpages\u002Fusers' },\n",[1656,3069,3070],{"class":1658,"line":1928},[1656,3071,1674],{"emptyLinePlaceholder":1673},[1656,3073,3074],{"class":1658,"line":1933},[1656,3075,3076],{},"]\n",[10,3078,3079],{},"输出为：",[601,3081,3084],{"className":3082,"code":3083,"language":2439,"meta":610,"style":610},"language-jsx shiki shiki-themes github-light github-dark","\u003CLayout>\n\n  \u003CPage>index\u003C\u002FPage>\n\n  \u003CPage>users\u003C\u002FPage>\n\n\u003C\u002FLayout>\n",[608,3085,3086,3097,3101,3116,3120,3133,3137],{"__ignoreMap":610},[1656,3087,3088,3091,3094],{"class":1658,"line":1659},[1656,3089,3090],{"class":1666},"\u003C",[1656,3092,3093],{"class":1697},"Layout",[1656,3095,3096],{"class":1666},">\n",[1656,3098,3099],{"class":1658,"line":1670},[1656,3100,1674],{"emptyLinePlaceholder":1673},[1656,3102,3103,3106,3109,3112,3114],{"class":1658,"line":1677},[1656,3104,3105],{"class":1666},"  \u003C",[1656,3107,3108],{"class":1697},"Page",[1656,3110,3111],{"class":1666},">index\u003C\u002F",[1656,3113,3108],{"class":1697},[1656,3115,3096],{"class":1666},[1656,3117,3118],{"class":1658,"line":1713},[1656,3119,1674],{"emptyLinePlaceholder":1673},[1656,3121,3122,3124,3126,3129,3131],{"class":1658,"line":1718},[1656,3123,3105],{"class":1666},[1656,3125,3108],{"class":1697},[1656,3127,3128],{"class":1666},">users\u003C\u002F",[1656,3130,3108],{"class":1697},[1656,3132,3096],{"class":1666},[1656,3134,3135],{"class":1658,"line":1928},[1656,3136,1674],{"emptyLinePlaceholder":1673},[1656,3138,3139,3142,3144],{"class":1658,"line":1933},[1656,3140,3141],{"class":1666},"\u003C\u002F",[1656,3143,3093],{"class":1697},[1656,3145,3096],{"class":1666},[10,3147,3148,3149,3152,3153,3160],{},"当你需要关闭 layout 时可以使用 ",[608,3150,3151],{},"layout: false"," ，当你需要更多层 layout 时，可以考虑使用 ",[82,3154,3157],{"href":3155,"rel":3156},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fguides\u002Froutes#wrappers",[86],[608,3158,3159],{},"wrappers"," ，仅在配置式路由可用：",[601,3162,3164],{"className":2717,"code":3163,"language":2266,"meta":610,"style":610},"routes: [\n\n    { path: '\u002F', component: '.\u002Findex', layout: false },\n\n    { \n\n      path: '\u002Fusers', \n\n      component: '.\u002Fusers', \n\n      wrappers: ['@\u002Fwrappers\u002Fauth']\n\n    }\n\n  ]\n",[608,3165,3166,3174,3178,3201,3205,3210,3214,3225,3229,3239,3243,3253,3257,3262,3266],{"__ignoreMap":610},[1656,3167,3168,3171],{"class":1658,"line":1659},[1656,3169,3170],{"class":1680},"routes",[1656,3172,3173],{"class":1666},": [\n",[1656,3175,3176],{"class":1658,"line":1670},[1656,3177,1674],{"emptyLinePlaceholder":1673},[1656,3179,3180,3183,3186,3189,3192,3195,3198],{"class":1658,"line":1677},[1656,3181,3182],{"class":1666},"    { path: ",[1656,3184,3185],{"class":1684},"'\u002F'",[1656,3187,3188],{"class":1666},", component: ",[1656,3190,3191],{"class":1684},"'.\u002Findex'",[1656,3193,3194],{"class":1666},", layout: ",[1656,3196,3197],{"class":1697},"false",[1656,3199,3200],{"class":1666}," },\n",[1656,3202,3203],{"class":1658,"line":1713},[1656,3204,1674],{"emptyLinePlaceholder":1673},[1656,3206,3207],{"class":1658,"line":1718},[1656,3208,3209],{"class":1666},"    { \n",[1656,3211,3212],{"class":1658,"line":1928},[1656,3213,1674],{"emptyLinePlaceholder":1673},[1656,3215,3216,3219,3222],{"class":1658,"line":1933},[1656,3217,3218],{"class":1666},"      path: ",[1656,3220,3221],{"class":1684},"'\u002Fusers'",[1656,3223,3224],{"class":1666},", \n",[1656,3226,3227],{"class":1658,"line":1944},[1656,3228,1674],{"emptyLinePlaceholder":1673},[1656,3230,3231,3234,3237],{"class":1658,"line":1949},[1656,3232,3233],{"class":1666},"      component: ",[1656,3235,3236],{"class":1684},"'.\u002Fusers'",[1656,3238,3224],{"class":1666},[1656,3240,3241],{"class":1658,"line":1960},[1656,3242,1674],{"emptyLinePlaceholder":1673},[1656,3244,3245,3248,3251],{"class":1658,"line":1965},[1656,3246,3247],{"class":1666},"      wrappers: [",[1656,3249,3250],{"class":1684},"'@\u002Fwrappers\u002Fauth'",[1656,3252,3076],{"class":1666},[1656,3254,3255],{"class":1658,"line":1975},[1656,3256,1674],{"emptyLinePlaceholder":1673},[1656,3258,3259],{"class":1658,"line":1980},[1656,3260,3261],{"class":1666},"    }\n",[1656,3263,3264],{"class":1658,"line":1988},[1656,3265,1674],{"emptyLinePlaceholder":1673},[1656,3267,3268],{"class":1658,"line":1993},[1656,3269,3270],{"class":1666},"  ]\n",[2967,3272,3274],{"id":3273},"pages-目录","pages 目录",[10,3276,3277,66],{},[13,3278,3279,3280,3283],{},"约定式路由默认以 ",[608,3281,3282],{},"pages\u002F*"," 文件夹的文件层级结构来生成路由表",[10,3285,3286,3287,3290],{},"在配置式路由中，",[608,3288,3289],{},"component"," 若写为相对路径，将从该文件夹为起点开始寻找文件：",[601,3292,3294],{"className":2717,"code":3293,"language":2266,"meta":610,"style":610},"routes: [\n\n    \u002F\u002F `.\u002Findex` === `@\u002Fpages\u002Findex`\n\n    { path: '\u002F', component: '.\u002Findex' }\n\n  ]\n",[608,3295,3296,3302,3306,3311,3315,3328,3332],{"__ignoreMap":610},[1656,3297,3298,3300],{"class":1658,"line":1659},[1656,3299,3170],{"class":1680},[1656,3301,3173],{"class":1666},[1656,3303,3304],{"class":1658,"line":1670},[1656,3305,1674],{"emptyLinePlaceholder":1673},[1656,3307,3308],{"class":1658,"line":1677},[1656,3309,3310],{"class":2725},"    \u002F\u002F `.\u002Findex` === `@\u002Fpages\u002Findex`\n",[1656,3312,3313],{"class":1658,"line":1713},[1656,3314,1674],{"emptyLinePlaceholder":1673},[1656,3316,3317,3319,3321,3323,3325],{"class":1658,"line":1718},[1656,3318,3182],{"class":1666},[1656,3320,3185],{"class":1684},[1656,3322,3188],{"class":1666},[1656,3324,3191],{"class":1684},[1656,3326,3327],{"class":1666}," }\n",[1656,3329,3330],{"class":1658,"line":1928},[1656,3331,1674],{"emptyLinePlaceholder":1673},[1656,3333,3334],{"class":1658,"line":1933},[1656,3335,3270],{"class":1666},[3337,3338,3339],"h5",{"id":3339},"基础路由",[10,3341,3342,3343,3346],{},"假设 ",[608,3344,3345],{},"pages"," 目录结构如下：",[601,3348,3350],{"className":3040,"code":3349,"language":3042,"meta":610,"style":610},"+ pages\u002F\n\n  + users\u002F\n\n    - index.tsx\n\n  - index.tsx\n",[608,3351,3352,3357,3361,3366,3370,3375,3379],{"__ignoreMap":610},[1656,3353,3354],{"class":1658,"line":1659},[1656,3355,3356],{},"+ pages\u002F\n",[1656,3358,3359],{"class":1658,"line":1670},[1656,3360,1674],{"emptyLinePlaceholder":1673},[1656,3362,3363],{"class":1658,"line":1677},[1656,3364,3365],{},"  + users\u002F\n",[1656,3367,3368],{"class":1658,"line":1713},[1656,3369,1674],{"emptyLinePlaceholder":1673},[1656,3371,3372],{"class":1658,"line":1718},[1656,3373,3374],{},"    - index.tsx\n",[1656,3376,3377],{"class":1658,"line":1928},[1656,3378,1674],{"emptyLinePlaceholder":1673},[1656,3380,3381],{"class":1658,"line":1933},[1656,3382,3383],{},"  - index.tsx\n",[10,3385,3386],{},"那么，会自动生成路由配置如下：",[601,3388,3390],{"className":2717,"code":3389,"language":2266,"meta":610,"style":610},"[\n\n  { path: '\u002F', component: '@\u002Fpages\u002Findex.tsx' },\n\n  { path: '\u002Fusers\u002F', component: '@\u002Fpages\u002Fusers\u002Findex.tsx' },\n\n]\n",[608,3391,3392,3396,3400,3414,3418,3432,3436],{"__ignoreMap":610},[1656,3393,3394],{"class":1658,"line":1659},[1656,3395,3049],{"class":1666},[1656,3397,3398],{"class":1658,"line":1670},[1656,3399,1674],{"emptyLinePlaceholder":1673},[1656,3401,3402,3405,3407,3409,3412],{"class":1658,"line":1677},[1656,3403,3404],{"class":1666},"  { path: ",[1656,3406,3185],{"class":1684},[1656,3408,3188],{"class":1666},[1656,3410,3411],{"class":1684},"'@\u002Fpages\u002Findex.tsx'",[1656,3413,3200],{"class":1666},[1656,3415,3416],{"class":1658,"line":1713},[1656,3417,1674],{"emptyLinePlaceholder":1673},[1656,3419,3420,3422,3425,3427,3430],{"class":1658,"line":1718},[1656,3421,3404],{"class":1666},[1656,3423,3424],{"class":1684},"'\u002Fusers\u002F'",[1656,3426,3188],{"class":1666},[1656,3428,3429],{"class":1684},"'@\u002Fpages\u002Fusers\u002Findex.tsx'",[1656,3431,3200],{"class":1666},[1656,3433,3434],{"class":1658,"line":1928},[1656,3435,1674],{"emptyLinePlaceholder":1673},[1656,3437,3438],{"class":1658,"line":1933},[1656,3439,3076],{"class":1666},[3337,3441,3442],{"id":3442},"动态路由",[10,3444,3445,3446,3452,3453,3455,3456,3459],{},"约定带 ",[13,3447,3448,3451],{},[608,3449,3450],{},"$"," 前缀的目录或文件为动态路由","。若 ",[608,3454,3450],{}," 后不指定参数名，则代表 ",[608,3457,3458],{},"*"," 通配，比如以下目录结构：",[601,3461,3463],{"className":3040,"code":3462,"language":3042,"meta":610,"style":610},"+ pages\u002F\n\n  + foo\u002F\n\n    - $slug.tsx\n\n  + $bar\u002F\n\n    - $.tsx\n\n  - index.tsx\n",[608,3464,3465,3469,3473,3478,3482,3487,3491,3496,3500,3505,3509],{"__ignoreMap":610},[1656,3466,3467],{"class":1658,"line":1659},[1656,3468,3356],{},[1656,3470,3471],{"class":1658,"line":1670},[1656,3472,1674],{"emptyLinePlaceholder":1673},[1656,3474,3475],{"class":1658,"line":1677},[1656,3476,3477],{},"  + foo\u002F\n",[1656,3479,3480],{"class":1658,"line":1713},[1656,3481,1674],{"emptyLinePlaceholder":1673},[1656,3483,3484],{"class":1658,"line":1718},[1656,3485,3486],{},"    - $slug.tsx\n",[1656,3488,3489],{"class":1658,"line":1928},[1656,3490,1674],{"emptyLinePlaceholder":1673},[1656,3492,3493],{"class":1658,"line":1933},[1656,3494,3495],{},"  + $bar\u002F\n",[1656,3497,3498],{"class":1658,"line":1944},[1656,3499,1674],{"emptyLinePlaceholder":1673},[1656,3501,3502],{"class":1658,"line":1949},[1656,3503,3504],{},"    - $.tsx\n",[1656,3506,3507],{"class":1658,"line":1960},[1656,3508,1674],{"emptyLinePlaceholder":1673},[1656,3510,3511],{"class":1658,"line":1965},[1656,3512,3383],{},[10,3514,3515],{},"会生成路由配置如下：",[601,3517,3519],{"className":2717,"code":3518,"language":2266,"meta":610,"style":610},"[\n\n  { path: '\u002F', component: '@\u002Fpages\u002Findex.tsx' },\n\n  { path: '\u002Ffoo\u002F:slug', component: '@\u002Fpages\u002Ffoo\u002F$slug.tsx' },\n\n  { path: '\u002F:bar\u002F*', component: '@\u002Fpages\u002F$bar\u002F$.tsx' },\n\n]\n",[608,3520,3521,3525,3529,3541,3545,3559,3563,3577,3581],{"__ignoreMap":610},[1656,3522,3523],{"class":1658,"line":1659},[1656,3524,3049],{"class":1666},[1656,3526,3527],{"class":1658,"line":1670},[1656,3528,1674],{"emptyLinePlaceholder":1673},[1656,3530,3531,3533,3535,3537,3539],{"class":1658,"line":1677},[1656,3532,3404],{"class":1666},[1656,3534,3185],{"class":1684},[1656,3536,3188],{"class":1666},[1656,3538,3411],{"class":1684},[1656,3540,3200],{"class":1666},[1656,3542,3543],{"class":1658,"line":1713},[1656,3544,1674],{"emptyLinePlaceholder":1673},[1656,3546,3547,3549,3552,3554,3557],{"class":1658,"line":1718},[1656,3548,3404],{"class":1666},[1656,3550,3551],{"class":1684},"'\u002Ffoo\u002F:slug'",[1656,3553,3188],{"class":1666},[1656,3555,3556],{"class":1684},"'@\u002Fpages\u002Ffoo\u002F$slug.tsx'",[1656,3558,3200],{"class":1666},[1656,3560,3561],{"class":1658,"line":1928},[1656,3562,1674],{"emptyLinePlaceholder":1673},[1656,3564,3565,3567,3570,3572,3575],{"class":1658,"line":1933},[1656,3566,3404],{"class":1666},[1656,3568,3569],{"class":1684},"'\u002F:bar\u002F*'",[1656,3571,3188],{"class":1666},[1656,3573,3574],{"class":1684},"'@\u002Fpages\u002F$bar\u002F$.tsx'",[1656,3576,3200],{"class":1666},[1656,3578,3579],{"class":1658,"line":1944},[1656,3580,1674],{"emptyLinePlaceholder":1673},[1656,3582,3583],{"class":1658,"line":1949},[1656,3584,3076],{"class":1666},[3337,3586,3588],{"id":3587},"pages404tsx","pages\u002F404.tsx",[10,3590,3591],{},"在使用约定式路由时，该文件会自动被注册为全局 404 的 fallback 页面。若你使用配置式路由，需要自行配置兜底路由到路由表最后一个：",[601,3593,3595],{"className":2717,"code":3594,"language":2266,"meta":610,"style":610},"routes: [\n\n    \u002F\u002F other routes ...\n\n    { path: '\u002F*', component: '@\u002Fpages\u002F404.tsx' }\n\n  ]\n",[608,3596,3597,3603,3607,3612,3616,3630,3634],{"__ignoreMap":610},[1656,3598,3599,3601],{"class":1658,"line":1659},[1656,3600,3170],{"class":1680},[1656,3602,3173],{"class":1666},[1656,3604,3605],{"class":1658,"line":1670},[1656,3606,1674],{"emptyLinePlaceholder":1673},[1656,3608,3609],{"class":1658,"line":1677},[1656,3610,3611],{"class":2725},"    \u002F\u002F other routes ...\n",[1656,3613,3614],{"class":1658,"line":1713},[1656,3615,1674],{"emptyLinePlaceholder":1673},[1656,3617,3618,3620,3623,3625,3628],{"class":1658,"line":1718},[1656,3619,3182],{"class":1666},[1656,3621,3622],{"class":1684},"'\u002F*'",[1656,3624,3188],{"class":1666},[1656,3626,3627],{"class":1684},"'@\u002Fpages\u002F404.tsx'",[1656,3629,3327],{"class":1666},[1656,3631,3632],{"class":1658,"line":1928},[1656,3633,1674],{"emptyLinePlaceholder":1673},[1656,3635,3636],{"class":1658,"line":1933},[1656,3637,3270],{"class":1666},[2967,3639,3641],{"id":3640},"globaljtsx","global.(j|t)sx?",[10,3643,3644],{},"全局前置脚本文件。",[10,3646,3647,3648,3651,3652,2657],{},"Umi 区别于其他前端框架，没有显式的程序主入口（如 ",[608,3649,3650],{},"src\u002Findex.ts","），所以当你有需要在应用前置、全局运行的逻辑时，优先考虑写入 ",[608,3653,3654],{},"global.ts",[10,3656,3657,3658,2657],{},"当你需要添加全局 Context 、修改应用运行时，请使用 ",[82,3659,3661],{"href":2699,"rel":3660},[86],[608,3662,3663],{},"app.tsx",[2967,3665,3667],{"id":3666},"globalcsslesssassscss","global.(css|less|sass|scss)",[10,3669,3670],{},"全局样式文件。",[10,3672,3673],{},"当你有需要全局使用的样式时，请考虑加入此文件。",[2967,3675,3676],{"id":610},"💡",[10,3678,3679,3680,2657],{},"需要注意的是，此文件的优先级在第三方组件库的样式之后，所以当你有覆盖第三方库样式的需求时，请使用 ",[82,3681,3684],{"href":3682,"rel":3683},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fguides\u002Fdirectory-structure#overridescsslesssassscss",[86],[608,3685,3686],{},"overrides.css",[2967,3688,3690],{"id":3689},"overridescsslesssassscss","overrides.(css|less|sass|scss)",[10,3692,3693],{},"高优先级全局样式文件。",[10,3695,3696,3697,3700],{},"该文件一般专用于覆盖第三方库样式，其中所有 CSS 选择器都会附加 ",[608,3698,3699],{},"body"," 前缀以抬高优先级。",[2967,3702,3704],{"id":3703},"loadingtsxjsx","loading.(tsx|jsx)",[10,3706,3707],{},"全局加载组件。",[10,3709,3710,3711,3716],{},"Umi 4 默认 ",[82,3712,3715],{"href":3713,"rel":3714},"https:\u002F\u002Fumijs.org\u002Fblog\u002Fcode-splitting",[86],"按页分包"," ，从而在页面切换时存在加载过程，通过该文件来配置加载动画。",[32,3718,3720],{"id":3719},"plugints","plugin.ts",[10,3722,3723],{},"项目级 Umi 插件。",[10,3725,3726,3727,3732,3733,3738],{},"当你有 Umi 定制需求时，往往会用到 ",[82,3728,3731],{"href":3729,"rel":3730},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fplugin-api",[86],"插件 API"," （比如 ",[82,3734,3737],{"href":3735,"rel":3736},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fplugin-api#modifyhtml",[86],"修改产物 html","），此时可创建该文件进行自定义：",[601,3740,3742],{"className":2717,"code":3741,"language":2266,"meta":610,"style":610},"import type { IApi } from 'umi';\nexport default (api: IApi) => {  api.onDevCompileDone((opts) => {    opts;    \u002F\u002F console.log('> onDevCompileDone', opts.isFirstCompile);  });  api.modifyHTML(($) => {    $;  });  api.chainWebpack((memo) => {    memo;  });};\n",[608,3743,3744,3761],{"__ignoreMap":610},[1656,3745,3746,3748,3751,3754,3756,3759],{"class":1658,"line":1659},[1656,3747,2899],{"class":1662},[1656,3749,3750],{"class":1662}," type",[1656,3752,3753],{"class":1666}," { IApi } ",[1656,3755,2911],{"class":1662},[1656,3757,3758],{"class":1684}," 'umi'",[1656,3760,2917],{"class":1666},[1656,3762,3763,3766,3769,3772,3776,3779,3782,3785,3788,3791,3794,3797,3800,3802,3804,3807],{"class":1658,"line":1670},[1656,3764,3765],{"class":1662},"export",[1656,3767,3768],{"class":1662}," default",[1656,3770,3771],{"class":1666}," (",[1656,3773,3775],{"class":3774},"s4XuR","api",[1656,3777,3778],{"class":1662},":",[1656,3780,3781],{"class":1680}," IApi",[1656,3783,3784],{"class":1666},") ",[1656,3786,3787],{"class":1662},"=>",[1656,3789,3790],{"class":1666}," {  api.",[1656,3792,3793],{"class":1680},"onDevCompileDone",[1656,3795,3796],{"class":1666},"((",[1656,3798,3799],{"class":3774},"opts",[1656,3801,3784],{"class":1666},[1656,3803,3787],{"class":1662},[1656,3805,3806],{"class":1666}," {    opts;    ",[1656,3808,3809],{"class":2725},"\u002F\u002F console.log('> onDevCompileDone', opts.isFirstCompile);  });  api.modifyHTML(($) => {    $;  });  api.chainWebpack((memo) => {    memo;  });};\n",[32,3811,3812],{"id":3812},"favicon",[10,3814,3815,3816,3818],{},"站点 ",[608,3817,3812],{}," 图标文件。",[10,3820,3821,3822,3825,3826,3828],{},"当存在 ",[608,3823,3824],{},"src\u002Ffavicon.(ico|gif|png|jpg|jpeg|svg|avif|webp)"," 文件时，将会自动在产物中添加站点 ",[608,3827,3812],{}," ：",[601,3830,3834],{"className":3831,"code":3832,"language":3833,"meta":610,"style":610},"language-html shiki shiki-themes github-light github-dark","\u003Clink rel=\"shortcut icon\" href=\"\u002Ffavicon.png\">\n","html",[608,3835,3836],{"__ignoreMap":610},[1656,3837,3838,3840,3844,3847,3850,3853,3856,3858,3861],{"class":1658,"line":1659},[1656,3839,3090],{"class":1666},[1656,3841,3843],{"class":3842},"s9eBZ","link",[1656,3845,3846],{"class":1680}," rel",[1656,3848,3849],{"class":1666},"=",[1656,3851,3852],{"class":1684},"\"shortcut icon\"",[1656,3854,3855],{"class":1680}," href",[1656,3857,3849],{"class":1666},[1656,3859,3860],{"class":1684},"\"\u002Ffavicon.png\"",[1656,3862,3096],{"class":1666},[10,3864,3865,3866,3871],{},"若使用外部资源等，可以使用 ",[82,3867,3870],{"href":3868,"rel":3869},"https:\u002F\u002Fumijs.org\u002Fdocs\u002Fapi\u002Fconfig#favicons",[86],"favicons"," 手动配置站点图标，配置值优先于约定。",[789,3873,3874],{"id":3874},"路由",[25,3876,3877],{"id":3877},"约定式路由",[10,3879,3880,3881,3884,3885,3888],{},"除配置式路由外，",[13,3882,3883],{},"Umi 也支持约定式路由","。约定式路由也叫",[13,3886,3887],{},"文件路由","，就是不需要手写配置，文件系统即路由，通过目录和文件及其命名分析出路由配置。",[10,3890,3891,3894,3895,3898],{},[13,3892,3893],{},"如果没有 routes 配置，Umi 会进入约定式路由模式","，然后分析 ",[608,3896,3897],{},"src\u002Fpages"," 目录拿到路由配置。",[10,3900,3901],{},"比如以下文件结构：",[601,3903,3905],{"className":1651,"code":3904,"language":883,"meta":610,"style":610},".\n\n  └── pages\n\n    ├── index.tsx\n\n    └── users.tsx\n",[608,3906,3907,3911,3915,3923,3927,3935,3939],{"__ignoreMap":610},[1656,3908,3909],{"class":1658,"line":1659},[1656,3910,1898],{"class":1697},[1656,3912,3913],{"class":1658,"line":1670},[1656,3914,1674],{"emptyLinePlaceholder":1673},[1656,3916,3917,3920],{"class":1658,"line":1677},[1656,3918,3919],{"class":1680},"  └──",[1656,3921,3922],{"class":1684}," pages\n",[1656,3924,3925],{"class":1658,"line":1713},[1656,3926,1674],{"emptyLinePlaceholder":1673},[1656,3928,3929,3932],{"class":1658,"line":1718},[1656,3930,3931],{"class":1680},"    ├──",[1656,3933,3934],{"class":1684}," index.tsx\n",[1656,3936,3937],{"class":1658,"line":1928},[1656,3938,1674],{"emptyLinePlaceholder":1673},[1656,3940,3941,3944],{"class":1658,"line":1933},[1656,3942,3943],{"class":1680},"    └──",[1656,3945,3946],{"class":1684}," users.tsx\n",[10,3948,3949],{},"会得到以下路由配置，",[601,3951,3954],{"className":3952,"code":3041,"language":3953,"meta":610,"style":610},"language-js shiki shiki-themes github-light github-dark","js",[608,3955,3956,3960,3964,3977,3981,3994,3998],{"__ignoreMap":610},[1656,3957,3958],{"class":1658,"line":1659},[1656,3959,3049],{"class":1666},[1656,3961,3962],{"class":1658,"line":1670},[1656,3963,1674],{"emptyLinePlaceholder":1673},[1656,3965,3966,3968,3970,3972,3975],{"class":1658,"line":1677},[1656,3967,3404],{"class":1666},[1656,3969,3185],{"class":1684},[1656,3971,3188],{"class":1666},[1656,3973,3974],{"class":1684},"'@\u002Fpages\u002Findex'",[1656,3976,3200],{"class":1666},[1656,3978,3979],{"class":1658,"line":1713},[1656,3980,1674],{"emptyLinePlaceholder":1673},[1656,3982,3983,3985,3987,3989,3992],{"class":1658,"line":1718},[1656,3984,3404],{"class":1666},[1656,3986,3221],{"class":1684},[1656,3988,3188],{"class":1666},[1656,3990,3991],{"class":1684},"'@\u002Fpages\u002Fusers'",[1656,3993,3200],{"class":1666},[1656,3995,3996],{"class":1658,"line":1928},[1656,3997,1674],{"emptyLinePlaceholder":1673},[1656,3999,4000],{"class":1658,"line":1933},[1656,4001,3076],{"class":1666},[32,4003,4004],{"id":4004},"路由动态参数",[10,4006,4007],{},[82,4008,4011],{"href":4009,"rel":4010},"https:\u002F\u002Freactrouter.com\u002Fen\u002Fmain\u002Fhooks\u002Fuse-params",[86],"useParams",[601,4013,4015],{"className":3082,"code":4014,"language":2439,"meta":610,"style":610},"\u002F\u002F 路由配置 \u002Fcomp\u002F:id\u002F\u002F 当前 location \u002Fcomp\u002FparamId\nconst params  = useParams();\u002F\u002F params{  \"id\": \"paramId\"}\n",[608,4016,4017,4022],{"__ignoreMap":610},[1656,4018,4019],{"class":1658,"line":1659},[1656,4020,4021],{"class":2725},"\u002F\u002F 路由配置 \u002Fcomp\u002F:id\u002F\u002F 当前 location \u002Fcomp\u002FparamId\n",[1656,4023,4024,4027,4030,4033,4036,4039],{"class":1658,"line":1670},[1656,4025,4026],{"class":1662},"const",[1656,4028,4029],{"class":1697}," params",[1656,4031,4032],{"class":1662},"  =",[1656,4034,4035],{"class":1680}," useParams",[1656,4037,4038],{"class":1666},"();",[1656,4040,4041],{"class":2725},"\u002F\u002F params{  \"id\": \"paramId\"}\n",[32,4043,4045],{"id":4044},"query-信息","query 信息",[10,4047,4048],{},[82,4049,4052],{"href":4050,"rel":4051},"https:\u002F\u002Freactrouter.com\u002Fen\u002Fmain\u002Fhooks\u002Fuse-search-params",[86],"useSearchParams",[601,4054,4056],{"className":3082,"code":4055,"language":2439,"meta":610,"style":610},"\u002F\u002F 当前 location \u002Fcomp?a=b;const [searchParams, setSearchParams] = useSearchParams();searchParams.get('a')  \u002F\u002F bsearchParams.toString()  \u002F\u002F a=b\nsetSearchParams({a:'c',d:'e'}) \u002F\u002F location 变成 \u002Fcomp?a=c&d=e\n",[608,4057,4058,4069],{"__ignoreMap":610},[1656,4059,4060,4063,4066],{"class":1658,"line":1659},[1656,4061,4062],{"class":2725},"\u002F\u002F 当前 location \u002Fcomp?a=b;const [searchParams, setSearchParams] = useSearchParams();searchParams.get('a')",[1656,4064,4065],{"class":2725},"  \u002F\u002F bsearchParams.toString()",[1656,4067,4068],{"class":2725},"  \u002F\u002F a=b\n",[1656,4070,4071,4074,4077,4080,4083,4086,4089],{"class":1658,"line":1670},[1656,4072,4073],{"class":1680},"setSearchParams",[1656,4075,4076],{"class":1666},"({a:",[1656,4078,4079],{"class":1684},"'c'",[1656,4081,4082],{"class":1666},",d:",[1656,4084,4085],{"class":1684},"'e'",[1656,4087,4088],{"class":1666},"}) ",[1656,4090,4091],{"class":2725},"\u002F\u002F location 变成 \u002Fcomp?a=c&d=e\n",[10,4093,4094,4097,4098],{},[608,4095,4096],{},"searchParams","的 api ",[82,4099,4102],{"href":4100,"rel":4101},"https:\u002F\u002Fdeveloper.mozilla.org\u002Fzh-CN\u002Fdocs\u002FWeb\u002FAPI\u002FURL\u002FsearchParams",[86],"参考",[789,4104,4105],{"id":4105},"路由数据加载",[10,4107,4108],{},"Umi 提供了开箱即用的数据预加载方案，能够解决在多层嵌套路由下，页面组件和数据依赖的瀑布流请求。Umi 会自动根据当前路由或准备跳转的路由，并行地发起他们的数据请求，因此当路由组件加载完成后，已经有马上可以使用的数据了。",[25,4110,4111],{"id":4111},"启用方式",[10,4113,4114],{},"配置开启：",[601,4116,4118],{"className":2717,"code":4117,"language":2266,"meta":610,"style":610},"\u002F\u002F .umirc.ts\nexport default {  clientLoader: {}}\n",[608,4119,4120,4125],{"__ignoreMap":610},[1656,4121,4122],{"class":1658,"line":1659},[1656,4123,4124],{"class":2725},"\u002F\u002F .umirc.ts\n",[1656,4126,4127,4129,4131],{"class":1658,"line":1670},[1656,4128,3765],{"class":1662},[1656,4130,3768],{"class":1662},[1656,4132,4133],{"class":1666}," {  clientLoader: {}}\n",[25,4135,4136],{"id":4136},"使用方式",[10,4138,4139,4140,4143],{},"在路由文件中，除了默认导出的页面组件外，再导出一个 ",[608,4141,4142],{},"clientLoader"," 函数，并且在该函数内完成路由数据加载的逻辑。",[601,4145,4147],{"className":2934,"code":4146,"language":2272,"meta":610,"style":610},"\u002F\u002F pages\u002F...\u002Fsome_page.tsx\nimport { useClientLoaderData } from 'umi';\nexport default function SomePage() {  const { data } = useClientLoaderData();  return \u003Cdiv>{data}\u003C\u002Fdiv>;}\nexport async function clientLoader() {  const data = await fetch('\u002Fapi\u002Fdata');  return data;}\n",[608,4148,4149,4154,4167,4218],{"__ignoreMap":610},[1656,4150,4151],{"class":1658,"line":1659},[1656,4152,4153],{"class":2725},"\u002F\u002F pages\u002F...\u002Fsome_page.tsx\n",[1656,4155,4156,4158,4161,4163,4165],{"class":1658,"line":1670},[1656,4157,2899],{"class":1662},[1656,4159,4160],{"class":1666}," { useClientLoaderData } ",[1656,4162,2911],{"class":1662},[1656,4164,3758],{"class":1684},[1656,4166,2917],{"class":1666},[1656,4168,4169,4171,4173,4176,4179,4182,4184,4187,4190,4193,4195,4198,4201,4204,4207,4210,4213,4215],{"class":1658,"line":1677},[1656,4170,3765],{"class":1662},[1656,4172,3768],{"class":1662},[1656,4174,4175],{"class":1662}," function",[1656,4177,4178],{"class":1680}," SomePage",[1656,4180,4181],{"class":1666},"() {  ",[1656,4183,4026],{"class":1662},[1656,4185,4186],{"class":1666}," { ",[1656,4188,4189],{"class":1697},"data",[1656,4191,4192],{"class":1666}," } ",[1656,4194,3849],{"class":1662},[1656,4196,4197],{"class":1680}," useClientLoaderData",[1656,4199,4200],{"class":1666},"();  ",[1656,4202,4203],{"class":1662},"return",[1656,4205,4206],{"class":1666}," \u003C",[1656,4208,4209],{"class":3842},"div",[1656,4211,4212],{"class":1666},">{data}\u003C\u002F",[1656,4214,4209],{"class":3842},[1656,4216,4217],{"class":1666},">;}\n",[1656,4219,4220,4222,4225,4227,4230,4232,4234,4237,4240,4243,4246,4248,4251,4254,4256],{"class":1658,"line":1713},[1656,4221,3765],{"class":1662},[1656,4223,4224],{"class":1662}," async",[1656,4226,4175],{"class":1662},[1656,4228,4229],{"class":1680}," clientLoader",[1656,4231,4181],{"class":1666},[1656,4233,4026],{"class":1662},[1656,4235,4236],{"class":1697}," data",[1656,4238,4239],{"class":1662}," =",[1656,4241,4242],{"class":1662}," await",[1656,4244,4245],{"class":1680}," fetch",[1656,4247,2263],{"class":1666},[1656,4249,4250],{"class":1684},"'\u002Fapi\u002Fdata'",[1656,4252,4253],{"class":1666},");  ",[1656,4255,4203],{"class":1662},[1656,4257,4258],{"class":1666}," data;}\n",[10,4260,4261,4262,4264,4265,4268],{},"如上代码，在 ",[608,4263,4142],{}," 函数返回的数据，可以在组件内调用 ",[608,4266,4267],{},"useClientLoaderData"," 获取。",[25,4270,4271],{"id":4271},"优化效果",[10,4273,4274],{},"考虑一个三层嵌套路由的场景：",[2879,4276,4277,4280,4283,4286],{},[42,4278,4279],{},"我们需要先等第一层路由的组件加载完成，然后第一层路由的组件发起数据请求",[42,4281,4282],{},"第一层路由的数据请求完成后，开始请求第二层路由的组件，第二层路由的组件加载好以后请求第二层路由需要的数据",[42,4284,4285],{},"第二层路由的数据请求完成后，开始请求第三层路由的组件，第三层路由的组件加载好以后请求第三层路由需要的数据",[42,4287,4288],{},"第三层路由的数据请求完成后，整个页面才完成渲染",[10,4290,4291],{},"这样的瀑布流请求会严重影响用户的体验，如下图所示：",[10,4293,4294],{},[4295,4296],"img",{"alt":4295,"src":4297},"https:\u002F\u002Fimg.alicdn.com\u002Fimgextra\u002Fi1\u002FO1CN01OcsOL91CPw46Pm7vz_!!6000000000074-1-tps-600-556.gif",[10,4299,4300,4301,4303],{},"如果将组件请求数据的程序提取到 ",[608,4302,4142],{}," 中，则 Umi 可以并行地请求这些数据：",[10,4305,4306],{},[4295,4307],{"alt":4295,"src":4308},"https:\u002F\u002Fimg.alicdn.com\u002Fimgextra\u002Fi3\u002FO1CN01URnLH81un9EVYGeL9_!!6000000006081-1-tps-600-556.gif",[789,4310,4311],{"id":4311},"插件",[25,4313,4314],{"id":4314},"使用插件",[10,4316,4317,4318,4321],{},"在普通的 Umi 应用中，默认 ",[13,4319,4320],{},"不附带任何插件"," ，如需使用 Max 的功能（如 数据流、antd 等），需要手动安装插件并开启他们：",[601,4323,4325],{"className":1651,"code":4324,"language":883,"meta":610,"style":610},"pnpm add -D @umijs\u002Fplugins\n",[608,4326,4327],{"__ignoreMap":610},[1656,4328,4329,4331,4334,4337],{"class":1658,"line":1659},[1656,4330,809],{"class":1680},[1656,4332,4333],{"class":1684}," add",[1656,4335,4336],{"class":1697}," -D",[1656,4338,4339],{"class":1684}," @umijs\u002Fplugins\n",[10,4341,4342],{},"如开启 antd 插件：",[601,4344,4346],{"className":2717,"code":4345,"language":2266,"meta":610,"style":610},"\u002F\u002F .umirc.ts\n\nexport default {\n\n  plugins: ['@umijs\u002Fplugins\u002Fdist\u002Fantd'],\n\n  antd: {}\n\n}\n",[608,4347,4348,4352,4356,4365,4369,4380,4384,4389,4393],{"__ignoreMap":610},[1656,4349,4350],{"class":1658,"line":1659},[1656,4351,4124],{"class":2725},[1656,4353,4354],{"class":1658,"line":1670},[1656,4355,1674],{"emptyLinePlaceholder":1673},[1656,4357,4358,4360,4362],{"class":1658,"line":1677},[1656,4359,3765],{"class":1662},[1656,4361,3768],{"class":1662},[1656,4363,4364],{"class":1666}," {\n",[1656,4366,4367],{"class":1658,"line":1713},[1656,4368,1674],{"emptyLinePlaceholder":1673},[1656,4370,4371,4374,4377],{"class":1658,"line":1718},[1656,4372,4373],{"class":1666},"  plugins: [",[1656,4375,4376],{"class":1684},"'@umijs\u002Fplugins\u002Fdist\u002Fantd'",[1656,4378,4379],{"class":1666},"],\n",[1656,4381,4382],{"class":1658,"line":1928},[1656,4383,1674],{"emptyLinePlaceholder":1673},[1656,4385,4386],{"class":1658,"line":1933},[1656,4387,4388],{"class":1666},"  antd: {}\n",[1656,4390,4391],{"class":1658,"line":1944},[1656,4392,1674],{"emptyLinePlaceholder":1673},[1656,4394,4395],{"class":1658,"line":1949},[1656,4396,2797],{"class":1666},[10,4398,4399,4400,4403,4404,4407,4408,4411,4412,4419],{},"Umi 与 Max 的区别是 Max 已经内置了大部分插件，如 数据流（ ",[608,4401,4402],{},"initial-state"," 、 ",[608,4405,4406],{},"model"," ）、",[608,4409,4410],{},"antd"," 等，这些插件都可以在 ",[82,4413,4416],{"href":4414,"rel":4415},"https:\u002F\u002Fgithub.com\u002Fumijs\u002Fumi\u002Ftree\u002Fmaster\u002Fpackages\u002Fplugins\u002Fsrc",[86],[608,4417,4418],{},"@umijs\u002Fplugins\u002Fdist\u002F*"," 加载并且开启。",[4421,4422,4423],"style",{},"html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}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 .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .s4XuR, html code.shiki .s4XuR{--shiki-default:#E36209;--shiki-dark:#FFAB70}html pre.shiki code .s9eBZ, html code.shiki .s9eBZ{--shiki-default:#22863A;--shiki-dark:#85E89D}",{"title":610,"searchDepth":1670,"depth":1670,"links":4425},[4426,4430,4434,4438,4442,4446,4447,4448,4449,4450,4451,4452,4453,4454,4455,4456,4457,4458,4463,4464,4486,4499,4503,4504,4505,4506],{"id":27,"depth":1670,"text":30,"children":4427},[4428,4429],{"id":34,"depth":1677,"text":37},{"id":122,"depth":1677,"text":125},{"id":344,"depth":1670,"text":347,"children":4431},[4432,4433],{"id":350,"depth":1677,"text":353},{"id":395,"depth":1677,"text":398},{"id":435,"depth":1670,"text":438,"children":4435},[4436,4437],{"id":441,"depth":1677,"text":444},{"id":479,"depth":1677,"text":482},{"id":516,"depth":1670,"text":519,"children":4439},[4440,4441],{"id":522,"depth":1677,"text":525},{"id":546,"depth":1677,"text":549},{"id":571,"depth":1670,"text":574,"children":4443},[4444,4445],{"id":577,"depth":1677,"text":580},{"id":613,"depth":1677,"text":616},{"id":642,"depth":1670,"text":645},{"id":737,"depth":1670,"text":740},{"id":815,"depth":1670,"text":818},{"id":896,"depth":1670,"text":899},{"id":957,"depth":1670,"text":960},{"id":1014,"depth":1670,"text":1017},{"id":1078,"depth":1670,"text":1081},{"id":1141,"depth":1670,"text":1144},{"id":1294,"depth":1670,"text":1297},{"id":1345,"depth":1670,"text":1348},{"id":1395,"depth":1670,"text":1398},{"id":1447,"depth":1670,"text":1450},{"id":1531,"depth":1670,"text":1534,"children":4459},[4460,4461,4462],{"id":1537,"depth":1677,"text":1540},{"id":1558,"depth":1677,"text":1561},{"id":1579,"depth":1677,"text":1582},{"id":1602,"depth":1670,"text":1605},{"id":1641,"depth":1670,"text":1641,"children":4465},[4466,4468,4470,4472,4474,4476,4478,4480,4482,4484],{"id":1756,"depth":1677,"text":4467},"1. 统一的代码风格",{"id":1777,"depth":1677,"text":4469},"2. 提高代码可读性",{"id":1789,"depth":1677,"text":4471},"3. 减少手动格式化工作",{"id":1801,"depth":1677,"text":4473},"4. 自动修复格式问题",{"id":1813,"depth":1677,"text":4475},"5. 减少合并冲突",{"id":1825,"depth":1677,"text":4477},"6. 提高开发效率",{"id":1837,"depth":1677,"text":4479},"7. 与编辑器集成",{"id":1849,"depth":1677,"text":4481},"8. 支持多种语言",{"id":1861,"depth":1677,"text":4483},"9. 减轻代码审查的负担",{"id":1873,"depth":1677,"text":4485},"10. 可与其他工具协同工作",{"id":2626,"depth":1670,"text":2626,"children":4487},[4488,4489,4490,4491,4492,4493,4494,4495,4497,4498],{"id":2629,"depth":1677,"text":2630},{"id":2660,"depth":1677,"text":2661},{"id":2673,"depth":1677,"text":2674},{"id":2800,"depth":1677,"text":2683},{"id":2824,"depth":1677,"text":2825},{"id":2842,"depth":1677,"text":2843},{"id":2862,"depth":1677,"text":2863},{"id":2961,"depth":1677,"text":4496},"src 目录",{"id":3719,"depth":1677,"text":3720},{"id":3812,"depth":1677,"text":3812},{"id":3877,"depth":1670,"text":3877,"children":4500},[4501,4502],{"id":4004,"depth":1677,"text":4004},{"id":4044,"depth":1677,"text":4045},{"id":4111,"depth":1670,"text":4111},{"id":4136,"depth":1670,"text":4136},{"id":4271,"depth":1670,"text":4271},{"id":4314,"depth":1670,"text":4314},"Vite 和 Webpack 是两种流行的前端构建工具，它们在构建模式、性能、开发体验等方面有显著差异。以下是它们的详细对比：","md",{},"\u002Fvue\u002F构造模式",{"description":4507},"Vue\u002F构造模式","OSfvoFFfmMZCL94q9fEvyizjsu-s8IbOWXhGlKFLvfE",1791042472529]