[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fplugin":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fplugin":2997,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fplugin":3021},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":14,"pinned":15,"draft":15,"body":16,"seo":2993,"stem":2994,"id":2995,"extension":2996},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fplugin","插件开发","Vite 插件兼容 Rollup 插件，并扩展 config、configureServer、transformIndexHtml 等钩子。原理见 工作原理。","技能小册",[12,13],"vite","plugin","2023-03-27",false,{"type":17,"value":18,"toc":2984},"minimark",[19,22,49,54,57,64,73,250,257,262,332,338,343,466,472,561,567,576,638,641,730,737,742,868,872,875,1063,1073,1077,1087,1109,1114,1313,1319,1400,1404,1413,1419,1617,1620,1665,1670,1694,1698,1702,1705,1896,1900,1903,2580,2584,2587,2817,2820,2856,2859,2932,2935,2939,2942,2980],[20,21,8],"h1",{"id":8},[23,24,25,26,30,31,35,36,35,39,42,43,48],"p",{},"Vite 插件兼容 ",[27,28,29],"strong",{},"Rollup"," 插件，并扩展 ",[32,33,34],"code",{},"config","、",[32,37,38],{},"configureServer",[32,40,41],{},"transformIndexHtml"," 等钩子。原理见 ",[44,45,47],"a",{"href":46},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fworkflow","工作原理","。",[50,51,53],"h3",{"id":52},"一vite-特有钩子","一、Vite 特有钩子",[23,55,56],{},"Vite 在 Rollup 插件生命周期之上新增了以下钩子（仅开发环境或同时用于构建）：",[58,59,61,62],"h4",{"id":60},"_1-config","1. ",[32,63,34],{},[23,65,66,69,70,72],{},[27,67,68],{},"作用","：修改 Vite 配置（在解析配置前调用）。可以返回一个对象（深度合并）或直接修改 ",[32,71,34],{}," 参数。",[74,75,80],"pre",{"className":76,"code":77,"language":78,"meta":79,"style":79},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","\u002F\u002F 修改 alias 或 base\nfunction myPlugin() {\n  return {\n    name: \"my-plugin\",\n    config(config, env) {\n      \u002F\u002F env: { mode, command }\n      config.resolve.alias = { \"@\": \"\u002Fsrc\" };\n      return config; \u002F\u002F 或返回部分配置\n    },\n  };\n}\n","js","",[32,81,82,91,109,118,142,166,172,217,232,238,244],{"__ignoreMap":79},[83,84,87],"span",{"class":85,"line":86},"line",1,[83,88,90],{"class":89},"sutJx","\u002F\u002F 修改 alias 或 base\n",[83,92,94,98,102,106],{"class":85,"line":93},2,[83,95,97],{"class":96},"sbsja","function",[83,99,101],{"class":100},"sGLFI"," myPlugin",[83,103,105],{"class":104},"sP7_E","()",[83,107,108],{"class":104}," {\n",[83,110,112,116],{"class":85,"line":111},3,[83,113,115],{"class":114},"sVHd0","  return",[83,117,108],{"class":104},[83,119,121,125,128,132,136,139],{"class":85,"line":120},4,[83,122,124],{"class":123},"skxfh","    name",[83,126,127],{"class":104},":",[83,129,131],{"class":130},"sjJ54"," \"",[83,133,135],{"class":134},"s_sjI","my-plugin",[83,137,138],{"class":130},"\"",[83,140,141],{"class":104},",\n",[83,143,145,149,152,155,158,161,164],{"class":85,"line":144},5,[83,146,148],{"class":147},"sVXei","    config",[83,150,151],{"class":104},"(",[83,153,34],{"class":154},"s99_P",[83,156,157],{"class":104},",",[83,159,160],{"class":154}," env",[83,162,163],{"class":104},")",[83,165,108],{"class":104},[83,167,169],{"class":85,"line":168},6,[83,170,171],{"class":89},"      \u002F\u002F env: { mode, command }\n",[83,173,175,179,182,185,187,190,194,197,199,203,205,207,209,212,214],{"class":85,"line":174},7,[83,176,178],{"class":177},"su5hD","      config",[83,180,181],{"class":104},".",[83,183,184],{"class":177},"resolve",[83,186,181],{"class":104},[83,188,189],{"class":177},"alias",[83,191,193],{"class":192},"smGrS"," =",[83,195,196],{"class":104}," {",[83,198,131],{"class":130},[83,200,202],{"class":201},"sZUrc","@",[83,204,138],{"class":130},[83,206,127],{"class":104},[83,208,131],{"class":130},[83,210,211],{"class":134},"\u002Fsrc",[83,213,138],{"class":130},[83,215,216],{"class":104}," };\n",[83,218,220,223,226,229],{"class":85,"line":219},8,[83,221,222],{"class":114},"      return",[83,224,225],{"class":177}," config",[83,227,228],{"class":104},";",[83,230,231],{"class":89}," \u002F\u002F 或返回部分配置\n",[83,233,235],{"class":85,"line":234},9,[83,236,237],{"class":104},"    },\n",[83,239,241],{"class":85,"line":240},10,[83,242,243],{"class":104},"  };\n",[83,245,247],{"class":85,"line":246},11,[83,248,249],{"class":104},"}\n",[58,251,253,254],{"id":252},"_2-configresolved","2. ",[32,255,256],{},"configResolved",[23,258,259,261],{},[27,260,68],{},"：在 Vite 配置最终确定后调用，可以获取完整的配置信息。",[74,263,265],{"className":76,"code":264,"language":78,"meta":79,"style":79},"configResolved(resolvedConfig) {\n  console.log('最终配置：', resolvedConfig);\n  \u002F\u002F 可以保存配置供其他钩子使用\n  this.config = resolvedConfig;\n}\n",[32,266,267,277,307,312,328],{"__ignoreMap":79},[83,268,269,271,274],{"class":85,"line":86},[83,270,256],{"class":100},[83,272,273],{"class":177},"(resolvedConfig) ",[83,275,276],{"class":104},"{\n",[83,278,279,282,284,287,289,292,295,297,299,302,304],{"class":85,"line":93},[83,280,281],{"class":177},"  console",[83,283,181],{"class":104},[83,285,286],{"class":100},"log",[83,288,151],{"class":123},[83,290,291],{"class":130},"'",[83,293,294],{"class":134},"最终配置：",[83,296,291],{"class":130},[83,298,157],{"class":104},[83,300,301],{"class":177}," resolvedConfig",[83,303,163],{"class":123},[83,305,306],{"class":104},";\n",[83,308,309],{"class":85,"line":111},[83,310,311],{"class":89},"  \u002F\u002F 可以保存配置供其他钩子使用\n",[83,313,314,318,320,322,324,326],{"class":85,"line":120},[83,315,317],{"class":316},"s39Yj","  this",[83,319,181],{"class":104},[83,321,34],{"class":177},[83,323,193],{"class":192},[83,325,301],{"class":177},[83,327,306],{"class":104},[83,329,330],{"class":85,"line":144},[83,331,249],{"class":104},[58,333,335,336],{"id":334},"_3-configureserver","3. ",[32,337,38],{},[23,339,340,342],{},[27,341,68],{},"：配置开发服务器的自定义中间件。通常用于添加 Mock API、代理、静态文件等。",[74,344,346],{"className":76,"code":345,"language":78,"meta":79,"style":79},"configureServer(server) {\n  \u002F\u002F server 是 ViteDevServer 实例\n  server.middlewares.use('\u002Fapi\u002Fmock', (req, res) => {\n    res.end(JSON.stringify({ data: 'mock' }));\n  });\n}\n",[32,347,348,357,362,406,453,462],{"__ignoreMap":79},[83,349,350,352,355],{"class":85,"line":86},[83,351,38],{"class":100},[83,353,354],{"class":177},"(server) ",[83,356,276],{"class":104},[83,358,359],{"class":85,"line":93},[83,360,361],{"class":89},"  \u002F\u002F server 是 ViteDevServer 实例\n",[83,363,364,367,369,372,374,377,379,381,384,386,388,391,394,396,399,401,404],{"class":85,"line":111},[83,365,366],{"class":177},"  server",[83,368,181],{"class":104},[83,370,371],{"class":177},"middlewares",[83,373,181],{"class":104},[83,375,376],{"class":100},"use",[83,378,151],{"class":123},[83,380,291],{"class":130},[83,382,383],{"class":134},"\u002Fapi\u002Fmock",[83,385,291],{"class":130},[83,387,157],{"class":104},[83,389,390],{"class":104}," (",[83,392,393],{"class":154},"req",[83,395,157],{"class":104},[83,397,398],{"class":154}," res",[83,400,163],{"class":104},[83,402,403],{"class":96}," =>",[83,405,108],{"class":104},[83,407,408,411,413,416,418,422,424,427,429,432,435,437,440,443,445,448,451],{"class":85,"line":120},[83,409,410],{"class":177},"    res",[83,412,181],{"class":104},[83,414,415],{"class":100},"end",[83,417,151],{"class":123},[83,419,421],{"class":420},"s_hVV","JSON",[83,423,181],{"class":104},[83,425,426],{"class":100},"stringify",[83,428,151],{"class":123},[83,430,431],{"class":104},"{",[83,433,434],{"class":123}," data",[83,436,127],{"class":104},[83,438,439],{"class":130}," '",[83,441,442],{"class":134},"mock",[83,444,291],{"class":130},[83,446,447],{"class":104}," }",[83,449,450],{"class":123},"))",[83,452,306],{"class":104},[83,454,455,458,460],{"class":85,"line":144},[83,456,457],{"class":104},"  }",[83,459,163],{"class":123},[83,461,306],{"class":104},[83,463,464],{"class":85,"line":168},[83,465,249],{"class":104},[23,467,468,471],{},[27,469,470],{},"高级用法","：返回一个函数，可以在内部中间件之后执行：",[74,473,475],{"className":76,"code":474,"language":78,"meta":79,"style":79},"configureServer(server) {\n  return () => {\n    server.middlewares.use((req, res, next) => {\n      \u002F\u002F 在所有 Vite 内置中间件之后执行\n      next();\n    });\n  };\n}\n",[32,476,477,485,496,530,535,544,553,557],{"__ignoreMap":79},[83,478,479,481,483],{"class":85,"line":86},[83,480,38],{"class":100},[83,482,354],{"class":177},[83,484,276],{"class":104},[83,486,487,489,492,494],{"class":85,"line":93},[83,488,115],{"class":114},[83,490,491],{"class":104}," ()",[83,493,403],{"class":96},[83,495,108],{"class":104},[83,497,498,501,503,505,507,509,511,513,515,517,519,521,524,526,528],{"class":85,"line":111},[83,499,500],{"class":177},"    server",[83,502,181],{"class":104},[83,504,371],{"class":177},[83,506,181],{"class":104},[83,508,376],{"class":100},[83,510,151],{"class":123},[83,512,151],{"class":104},[83,514,393],{"class":154},[83,516,157],{"class":104},[83,518,398],{"class":154},[83,520,157],{"class":104},[83,522,523],{"class":154}," next",[83,525,163],{"class":104},[83,527,403],{"class":96},[83,529,108],{"class":104},[83,531,532],{"class":85,"line":120},[83,533,534],{"class":89},"      \u002F\u002F 在所有 Vite 内置中间件之后执行\n",[83,536,537,540,542],{"class":85,"line":144},[83,538,539],{"class":100},"      next",[83,541,105],{"class":123},[83,543,306],{"class":104},[83,545,546,549,551],{"class":85,"line":168},[83,547,548],{"class":104},"    }",[83,550,163],{"class":123},[83,552,306],{"class":104},[83,554,555],{"class":85,"line":174},[83,556,243],{"class":104},[83,558,559],{"class":85,"line":219},[83,560,249],{"class":104},[58,562,564,565],{"id":563},"_4-transformindexhtml","4. ",[32,566,41],{},[23,568,569,571,572,575],{},[27,570,68],{},"：转换入口 HTML 文件（",[32,573,574],{},"index.html","）。可添加标签、修改内容等。",[74,577,579],{"className":76,"code":578,"language":78,"meta":79,"style":79},"transformIndexHtml(html, ctx) {\n  \u002F\u002F ctx: { path, filename, originalUrl }\n  return html.replace('\u003C!-- inject -->', '\u003Cscript>console.log(\"injected\")\u003C\u002Fscript>');\n}\n",[32,580,581,595,600,634],{"__ignoreMap":79},[83,582,583,585,588,590,593],{"class":85,"line":86},[83,584,41],{"class":100},[83,586,587],{"class":177},"(html",[83,589,157],{"class":104},[83,591,592],{"class":177}," ctx) ",[83,594,276],{"class":104},[83,596,597],{"class":85,"line":93},[83,598,599],{"class":89},"  \u002F\u002F ctx: { path, filename, originalUrl }\n",[83,601,602,604,607,609,612,614,616,619,621,623,625,628,630,632],{"class":85,"line":111},[83,603,115],{"class":114},[83,605,606],{"class":177}," html",[83,608,181],{"class":104},[83,610,611],{"class":100},"replace",[83,613,151],{"class":123},[83,615,291],{"class":130},[83,617,618],{"class":134},"\u003C!-- inject -->",[83,620,291],{"class":130},[83,622,157],{"class":104},[83,624,439],{"class":130},[83,626,627],{"class":134},"\u003Cscript>console.log(\"injected\")\u003C\u002Fscript>",[83,629,291],{"class":130},[83,631,163],{"class":123},[83,633,306],{"class":104},[83,635,636],{"class":85,"line":120},[83,637,249],{"class":104},[23,639,640],{},"也可以返回对象数组，用于插入特定标签：",[74,642,644],{"className":76,"code":643,"language":78,"meta":79,"style":79},"transformIndexHtml() {\n  return [\n    { tag: 'meta', attrs: { name: 'theme-color', content: '#fff' } },\n  ];\n}\n",[32,645,646,655,662,719,726],{"__ignoreMap":79},[83,647,648,650,653],{"class":85,"line":86},[83,649,41],{"class":100},[83,651,652],{"class":177},"() ",[83,654,276],{"class":104},[83,656,657,659],{"class":85,"line":93},[83,658,115],{"class":114},[83,660,661],{"class":123}," [\n",[83,663,664,667,670,672,674,677,679,681,684,686,688,691,693,695,698,700,702,705,707,709,712,714,716],{"class":85,"line":111},[83,665,666],{"class":104},"    {",[83,668,669],{"class":123}," tag",[83,671,127],{"class":104},[83,673,439],{"class":130},[83,675,676],{"class":134},"meta",[83,678,291],{"class":130},[83,680,157],{"class":104},[83,682,683],{"class":123}," attrs",[83,685,127],{"class":104},[83,687,196],{"class":104},[83,689,690],{"class":123}," name",[83,692,127],{"class":104},[83,694,439],{"class":130},[83,696,697],{"class":134},"theme-color",[83,699,291],{"class":130},[83,701,157],{"class":104},[83,703,704],{"class":123}," content",[83,706,127],{"class":104},[83,708,439],{"class":130},[83,710,711],{"class":134},"#fff",[83,713,291],{"class":130},[83,715,447],{"class":104},[83,717,718],{"class":104}," },\n",[83,720,721,724],{"class":85,"line":120},[83,722,723],{"class":123},"  ]",[83,725,306],{"class":104},[83,727,728],{"class":85,"line":144},[83,729,249],{"class":104},[58,731,733,734],{"id":732},"_5-handlehotupdate","5. ",[32,735,736],{},"handleHotUpdate",[23,738,739,741],{},[27,740,68],{},"：自定义 HMR 更新逻辑，可以过滤或扩展热更新的模块。",[74,743,745],{"className":76,"code":744,"language":78,"meta":79,"style":79},"handleHotUpdate({ file, modules, server }) {\n  \u002F\u002F 如果文件是某个特定组件，可以只重新加载该组件\n  if (file.endsWith('Component.vue')) {\n    return modules.filter(m => m.id === file);\n  }\n  \u002F\u002F 默认返回所有受影响的模块\n  return modules;\n}\n",[32,746,747,776,781,810,846,851,856,864],{"__ignoreMap":79},[83,748,749,751,753,755,758,760,763,765,768,771,774],{"class":85,"line":86},[83,750,736],{"class":100},[83,752,151],{"class":177},[83,754,431],{"class":104},[83,756,757],{"class":177}," file",[83,759,157],{"class":104},[83,761,762],{"class":177}," modules",[83,764,157],{"class":104},[83,766,767],{"class":177}," server ",[83,769,770],{"class":104},"}",[83,772,773],{"class":177},") ",[83,775,276],{"class":104},[83,777,778],{"class":85,"line":93},[83,779,780],{"class":89},"  \u002F\u002F 如果文件是某个特定组件，可以只重新加载该组件\n",[83,782,783,786,788,791,793,796,798,800,803,805,808],{"class":85,"line":111},[83,784,785],{"class":114},"  if",[83,787,390],{"class":123},[83,789,790],{"class":177},"file",[83,792,181],{"class":104},[83,794,795],{"class":100},"endsWith",[83,797,151],{"class":123},[83,799,291],{"class":130},[83,801,802],{"class":134},"Component.vue",[83,804,291],{"class":130},[83,806,807],{"class":123},")) ",[83,809,276],{"class":104},[83,811,812,815,817,819,822,824,827,829,832,834,837,840,842,844],{"class":85,"line":120},[83,813,814],{"class":114},"    return",[83,816,762],{"class":177},[83,818,181],{"class":104},[83,820,821],{"class":100},"filter",[83,823,151],{"class":123},[83,825,826],{"class":154},"m",[83,828,403],{"class":96},[83,830,831],{"class":177}," m",[83,833,181],{"class":104},[83,835,836],{"class":177},"id",[83,838,839],{"class":192}," ===",[83,841,757],{"class":177},[83,843,163],{"class":123},[83,845,306],{"class":104},[83,847,848],{"class":85,"line":144},[83,849,850],{"class":104},"  }\n",[83,852,853],{"class":85,"line":168},[83,854,855],{"class":89},"  \u002F\u002F 默认返回所有受影响的模块\n",[83,857,858,860,862],{"class":85,"line":174},[83,859,115],{"class":114},[83,861,762],{"class":177},[83,863,306],{"class":104},[83,865,866],{"class":85,"line":219},[83,867,249],{"class":104},[50,869,871],{"id":870},"二开发环境与生产环境钩子差异","二、开发环境与生产环境钩子差异",[23,873,874],{},"Vite 插件钩子在不同环境下有选择性执行：",[876,877,878,897],"table",{},[879,880,881],"thead",{},[882,883,884,888,891,894],"tr",{},[885,886,887],"th",{},"钩子",[885,889,890],{},"开发环境",[885,892,893],{},"生产环境",[885,895,896],{},"说明",[898,899,900,915,927,941,954,967,981,994,1007,1021,1035,1049],"tbody",{},[882,901,902,907,910,912],{},[903,904,905],"td",{},[32,906,34],{},[903,908,909],{},"✅",[903,911,909],{},[903,913,914],{},"都执行",[882,916,917,921,923,925],{},[903,918,919],{},[32,920,256],{},[903,922,909],{},[903,924,909],{},[903,926,914],{},[882,928,929,933,935,938],{},[903,930,931],{},[32,932,38],{},[903,934,909],{},[903,936,937],{},"❌",[903,939,940],{},"仅开发服务器",[882,942,943,947,949,951],{},[903,944,945],{},[32,946,41],{},[903,948,909],{},[903,950,909],{},[903,952,953],{},"构建时也会转换 HTML",[882,955,956,960,962,964],{},[903,957,958],{},[32,959,736],{},[903,961,909],{},[903,963,937],{},[903,965,966],{},"仅开发 HMR",[882,968,969,974,976,978],{},[903,970,971],{},[32,972,973],{},"resolveId",[903,975,909],{},[903,977,909],{},[903,979,980],{},"Rollup 钩子，都执行",[882,982,983,988,990,992],{},[903,984,985],{},[32,986,987],{},"load",[903,989,909],{},[903,991,909],{},[903,993,914],{},[882,995,996,1001,1003,1005],{},[903,997,998],{},[32,999,1000],{},"transform",[903,1002,909],{},[903,1004,909],{},[903,1006,914],{},[882,1008,1009,1014,1016,1018],{},[903,1010,1011],{},[32,1012,1013],{},"buildStart",[903,1015,937],{},[903,1017,909],{},[903,1019,1020],{},"构建开始时",[882,1022,1023,1028,1030,1032],{},[903,1024,1025],{},[32,1026,1027],{},"renderStart",[903,1029,937],{},[903,1031,909],{},[903,1033,1034],{},"构建渲染开始时",[882,1036,1037,1042,1044,1046],{},[903,1038,1039],{},[32,1040,1041],{},"generateBundle",[903,1043,937],{},[903,1045,909],{},[903,1047,1048],{},"生成 bundle 时",[882,1050,1051,1056,1058,1060],{},[903,1052,1053],{},[32,1054,1055],{},"writeBundle",[903,1057,937],{},[903,1059,909],{},[903,1061,1062],{},"写入文件后",[23,1064,1065,1066,1069,1070,1072],{},"开发环境实际上是",[27,1067,1068],{},"无打包","的，因此不会触发 Rollup 的 ",[32,1071,1041],{}," 等钩子。生产环境使用 Rollup 打包，这些钩子都会执行。",[50,1074,1076],{"id":1075},"三中间件模式","三、中间件模式",[23,1078,1079,1080,1083,1084,1086],{},"Vite 开发服务器基于 ",[32,1081,1082],{},"connect"," 中间件栈。通过 ",[32,1085,38],{}," 可以注入自定义中间件，常用于：",[1088,1089,1090,1097,1103],"ul",{},[1091,1092,1093,1096],"li",{},[27,1094,1095],{},"Mock API","：拦截特定请求返回 JSON。",[1091,1098,1099,1102],{},[27,1100,1101],{},"代理重写","：修改代理规则或响应。",[1091,1104,1105,1108],{},[27,1106,1107],{},"静态文件托管","：提供额外的静态资源目录。",[23,1110,1111],{},[27,1112,1113],{},"示例：Mock API 中间件",[74,1115,1117],{"className":76,"code":1116,"language":78,"meta":79,"style":79},"export default function mockPlugin() {\n  return {\n    name: \"mock-api\",\n    configureServer(server) {\n      server.middlewares.use(\"\u002Fapi\u002Fusers\", (req, res) => {\n        res.setHeader(\"Content-Type\", \"application\u002Fjson\");\n        res.end(JSON.stringify([{ id: 1, name: \"Alice\" }]));\n      });\n    },\n  };\n}\n",[32,1118,1119,1137,1143,1158,1172,1210,1242,1292,1301,1305,1309],{"__ignoreMap":79},[83,1120,1121,1124,1127,1130,1133,1135],{"class":85,"line":86},[83,1122,1123],{"class":114},"export",[83,1125,1126],{"class":114}," default",[83,1128,1129],{"class":96}," function",[83,1131,1132],{"class":100}," mockPlugin",[83,1134,105],{"class":104},[83,1136,108],{"class":104},[83,1138,1139,1141],{"class":85,"line":93},[83,1140,115],{"class":114},[83,1142,108],{"class":104},[83,1144,1145,1147,1149,1151,1154,1156],{"class":85,"line":111},[83,1146,124],{"class":123},[83,1148,127],{"class":104},[83,1150,131],{"class":130},[83,1152,1153],{"class":134},"mock-api",[83,1155,138],{"class":130},[83,1157,141],{"class":104},[83,1159,1160,1163,1165,1168,1170],{"class":85,"line":120},[83,1161,1162],{"class":147},"    configureServer",[83,1164,151],{"class":104},[83,1166,1167],{"class":154},"server",[83,1169,163],{"class":104},[83,1171,108],{"class":104},[83,1173,1174,1177,1179,1181,1183,1185,1187,1189,1192,1194,1196,1198,1200,1202,1204,1206,1208],{"class":85,"line":144},[83,1175,1176],{"class":177},"      server",[83,1178,181],{"class":104},[83,1180,371],{"class":177},[83,1182,181],{"class":104},[83,1184,376],{"class":100},[83,1186,151],{"class":123},[83,1188,138],{"class":130},[83,1190,1191],{"class":134},"\u002Fapi\u002Fusers",[83,1193,138],{"class":130},[83,1195,157],{"class":104},[83,1197,390],{"class":104},[83,1199,393],{"class":154},[83,1201,157],{"class":104},[83,1203,398],{"class":154},[83,1205,163],{"class":104},[83,1207,403],{"class":96},[83,1209,108],{"class":104},[83,1211,1212,1215,1217,1220,1222,1224,1227,1229,1231,1233,1236,1238,1240],{"class":85,"line":168},[83,1213,1214],{"class":177},"        res",[83,1216,181],{"class":104},[83,1218,1219],{"class":100},"setHeader",[83,1221,151],{"class":123},[83,1223,138],{"class":130},[83,1225,1226],{"class":134},"Content-Type",[83,1228,138],{"class":130},[83,1230,157],{"class":104},[83,1232,131],{"class":130},[83,1234,1235],{"class":134},"application\u002Fjson",[83,1237,138],{"class":130},[83,1239,163],{"class":123},[83,1241,306],{"class":104},[83,1243,1244,1246,1248,1250,1252,1254,1256,1258,1261,1263,1266,1268,1272,1274,1276,1278,1280,1283,1285,1287,1290],{"class":85,"line":174},[83,1245,1214],{"class":177},[83,1247,181],{"class":104},[83,1249,415],{"class":100},[83,1251,151],{"class":123},[83,1253,421],{"class":420},[83,1255,181],{"class":104},[83,1257,426],{"class":100},[83,1259,1260],{"class":123},"([",[83,1262,431],{"class":104},[83,1264,1265],{"class":123}," id",[83,1267,127],{"class":104},[83,1269,1271],{"class":1270},"srdBf"," 1",[83,1273,157],{"class":104},[83,1275,690],{"class":123},[83,1277,127],{"class":104},[83,1279,131],{"class":130},[83,1281,1282],{"class":134},"Alice",[83,1284,138],{"class":130},[83,1286,447],{"class":104},[83,1288,1289],{"class":123},"]))",[83,1291,306],{"class":104},[83,1293,1294,1297,1299],{"class":85,"line":219},[83,1295,1296],{"class":104},"      }",[83,1298,163],{"class":123},[83,1300,306],{"class":104},[83,1302,1303],{"class":85,"line":234},[83,1304,237],{"class":104},[83,1306,1307],{"class":85,"line":240},[83,1308,243],{"class":104},[83,1310,1311],{"class":85,"line":246},[83,1312,249],{"class":104},[23,1314,1315,1318],{},[27,1316,1317],{},"注意中间件顺序","：默认情况下，自定义中间件会添加到内部中间件之前。如果需要在 Vite 内部中间件（如静态文件、HMR）之后执行，可以返回一个函数：",[74,1320,1322],{"className":76,"code":1321,"language":78,"meta":79,"style":79},"configureServer(server) {\n  return () => {\n    server.middlewares.use('\u002Fafter', (req, res) => {\n      \u002F\u002F 在 Vite 内部中间件之后执行\n    });\n  };\n}\n",[32,1323,1324,1332,1342,1379,1384,1392,1396],{"__ignoreMap":79},[83,1325,1326,1328,1330],{"class":85,"line":86},[83,1327,38],{"class":100},[83,1329,354],{"class":177},[83,1331,276],{"class":104},[83,1333,1334,1336,1338,1340],{"class":85,"line":93},[83,1335,115],{"class":114},[83,1337,491],{"class":104},[83,1339,403],{"class":96},[83,1341,108],{"class":104},[83,1343,1344,1346,1348,1350,1352,1354,1356,1358,1361,1363,1365,1367,1369,1371,1373,1375,1377],{"class":85,"line":111},[83,1345,500],{"class":177},[83,1347,181],{"class":104},[83,1349,371],{"class":177},[83,1351,181],{"class":104},[83,1353,376],{"class":100},[83,1355,151],{"class":123},[83,1357,291],{"class":130},[83,1359,1360],{"class":134},"\u002Fafter",[83,1362,291],{"class":130},[83,1364,157],{"class":104},[83,1366,390],{"class":104},[83,1368,393],{"class":154},[83,1370,157],{"class":104},[83,1372,398],{"class":154},[83,1374,163],{"class":104},[83,1376,403],{"class":96},[83,1378,108],{"class":104},[83,1380,1381],{"class":85,"line":120},[83,1382,1383],{"class":89},"      \u002F\u002F 在 Vite 内部中间件之后执行\n",[83,1385,1386,1388,1390],{"class":85,"line":144},[83,1387,548],{"class":104},[83,1389,163],{"class":123},[83,1391,306],{"class":104},[83,1393,1394],{"class":85,"line":168},[83,1395,243],{"class":104},[83,1397,1398],{"class":85,"line":174},[83,1399,249],{"class":104},[50,1401,1403],{"id":1402},"四虚拟模块","四、虚拟模块",[23,1405,1406,1407,1409,1410,1412],{},"虚拟模块是指不实际存在于磁盘上的模块，通过插件动态生成内容。使用 ",[32,1408,973],{}," 和 ",[32,1411,987],{}," 钩子实现。",[23,1414,1415,1418],{},[27,1416,1417],{},"基本模式","：",[74,1420,1422],{"className":76,"code":1421,"language":78,"meta":79,"style":79},"export default function virtualModulePlugin() {\n  const virtualModuleId = \"virtual:my-module\";\n  const resolvedVirtualModuleId = \"\\0\" + virtualModuleId; \u002F\u002F 前缀避免被其他插件处理\n\n  return {\n    name: \"virtual-module\",\n    resolveId(id) {\n      if (id === virtualModuleId) return resolvedVirtualModuleId;\n    },\n    load(id) {\n      if (id === resolvedVirtualModuleId) {\n        return `export const msg = \"Hello from virtual module\";`;\n      }\n    },\n  };\n}\n",[32,1423,1424,1439,1458,1484,1490,1496,1511,1524,1546,1550,1563,1579,1596,1602,1607,1612],{"__ignoreMap":79},[83,1425,1426,1428,1430,1432,1435,1437],{"class":85,"line":86},[83,1427,1123],{"class":114},[83,1429,1126],{"class":114},[83,1431,1129],{"class":96},[83,1433,1434],{"class":100}," virtualModulePlugin",[83,1436,105],{"class":104},[83,1438,108],{"class":104},[83,1440,1441,1444,1447,1449,1451,1454,1456],{"class":85,"line":93},[83,1442,1443],{"class":96},"  const",[83,1445,1446],{"class":420}," virtualModuleId",[83,1448,193],{"class":192},[83,1450,131],{"class":130},[83,1452,1453],{"class":134},"virtual:my-module",[83,1455,138],{"class":130},[83,1457,306],{"class":104},[83,1459,1460,1462,1465,1467,1469,1472,1474,1477,1479,1481],{"class":85,"line":111},[83,1461,1443],{"class":96},[83,1463,1464],{"class":420}," resolvedVirtualModuleId",[83,1466,193],{"class":192},[83,1468,131],{"class":130},[83,1470,1471],{"class":420},"\\0",[83,1473,138],{"class":130},[83,1475,1476],{"class":192}," +",[83,1478,1446],{"class":177},[83,1480,228],{"class":104},[83,1482,1483],{"class":89}," \u002F\u002F 前缀避免被其他插件处理\n",[83,1485,1486],{"class":85,"line":120},[83,1487,1489],{"emptyLinePlaceholder":1488},true,"\n",[83,1491,1492,1494],{"class":85,"line":144},[83,1493,115],{"class":114},[83,1495,108],{"class":104},[83,1497,1498,1500,1502,1504,1507,1509],{"class":85,"line":168},[83,1499,124],{"class":123},[83,1501,127],{"class":104},[83,1503,131],{"class":130},[83,1505,1506],{"class":134},"virtual-module",[83,1508,138],{"class":130},[83,1510,141],{"class":104},[83,1512,1513,1516,1518,1520,1522],{"class":85,"line":174},[83,1514,1515],{"class":147},"    resolveId",[83,1517,151],{"class":104},[83,1519,836],{"class":154},[83,1521,163],{"class":104},[83,1523,108],{"class":104},[83,1525,1526,1529,1531,1533,1535,1537,1539,1542,1544],{"class":85,"line":219},[83,1527,1528],{"class":114},"      if",[83,1530,390],{"class":123},[83,1532,836],{"class":177},[83,1534,839],{"class":192},[83,1536,1446],{"class":177},[83,1538,773],{"class":123},[83,1540,1541],{"class":114},"return",[83,1543,1464],{"class":177},[83,1545,306],{"class":104},[83,1547,1548],{"class":85,"line":234},[83,1549,237],{"class":104},[83,1551,1552,1555,1557,1559,1561],{"class":85,"line":240},[83,1553,1554],{"class":147},"    load",[83,1556,151],{"class":104},[83,1558,836],{"class":154},[83,1560,163],{"class":104},[83,1562,108],{"class":104},[83,1564,1565,1567,1569,1571,1573,1575,1577],{"class":85,"line":246},[83,1566,1528],{"class":114},[83,1568,390],{"class":123},[83,1570,836],{"class":177},[83,1572,839],{"class":192},[83,1574,1464],{"class":177},[83,1576,773],{"class":123},[83,1578,276],{"class":104},[83,1580,1582,1585,1588,1591,1594],{"class":85,"line":1581},12,[83,1583,1584],{"class":114},"        return",[83,1586,1587],{"class":130}," `",[83,1589,1590],{"class":134},"export const msg = \"Hello from virtual module\";",[83,1592,1593],{"class":130},"`",[83,1595,306],{"class":104},[83,1597,1599],{"class":85,"line":1598},13,[83,1600,1601],{"class":104},"      }\n",[83,1603,1605],{"class":85,"line":1604},14,[83,1606,237],{"class":104},[83,1608,1610],{"class":85,"line":1609},15,[83,1611,243],{"class":104},[83,1613,1615],{"class":85,"line":1614},16,[83,1616,249],{"class":104},[23,1618,1619],{},"然后在代码中导入：",[74,1621,1623],{"className":76,"code":1622,"language":78,"meta":79,"style":79},"import { msg } from \"virtual:my-module\";\nconsole.log(msg); \u002F\u002F \"Hello from virtual module\"\n",[32,1624,1625,1648],{"__ignoreMap":79},[83,1626,1627,1630,1632,1635,1637,1640,1642,1644,1646],{"class":85,"line":86},[83,1628,1629],{"class":114},"import",[83,1631,196],{"class":104},[83,1633,1634],{"class":177}," msg",[83,1636,447],{"class":104},[83,1638,1639],{"class":114}," from",[83,1641,131],{"class":130},[83,1643,1453],{"class":134},[83,1645,138],{"class":130},[83,1647,306],{"class":104},[83,1649,1650,1653,1655,1657,1660,1662],{"class":85,"line":93},[83,1651,1652],{"class":177},"console",[83,1654,181],{"class":104},[83,1656,286],{"class":100},[83,1658,1659],{"class":177},"(msg)",[83,1661,228],{"class":104},[83,1663,1664],{"class":89}," \u002F\u002F \"Hello from virtual module\"\n",[23,1666,1667,1418],{},[27,1668,1669],{},"典型应用",[1088,1671,1672,1682,1688],{},[1091,1673,1674,1677,1678,1681],{},[27,1675,1676],{},"注入环境变量","：将 ",[32,1679,1680],{},".env"," 文件变量生成虚拟模块。",[1091,1683,1684,1687],{},[27,1685,1686],{},"生成路由表","：根据文件系统自动生成路由配置。",[1091,1689,1690,1693],{},[27,1691,1692],{},"注入组件库注册信息","：自动导入组件。",[50,1695,1697],{"id":1696},"五插件示例","五、插件示例",[58,1699,1701],{"id":1700},"_1-全局样式自动导入","1. 全局样式自动导入",[23,1703,1704],{},"自动在入口文件或每个模块中注入全局 CSS（如重置样式、主题变量）。",[74,1706,1708],{"className":76,"code":1707,"language":78,"meta":79,"style":79},"function globalStylePlugin() {\n  return {\n    name: \"global-style\",\n    transformIndexHtml(html) {\n      \u002F\u002F 在 HTML 中直接插入 link 标签\n      return html.replace(\n        \"\u003C\u002Fhead>\",\n        '\u003Clink rel=\"stylesheet\" href=\"\u002Fsrc\u002Fstyles\u002Fglobal.css\">\u003C\u002Fhead>',\n      );\n    },\n    \u002F\u002F 或者使用 transform 钩子在 JS 模块中注入 import\n    transform(code, id) {\n      if (id.endsWith(\"main.js\")) {\n        return `import '\u002Fsrc\u002Fstyles\u002Fglobal.css';\\n${code}`;\n      }\n    },\n  };\n}\n",[32,1709,1710,1721,1727,1742,1756,1761,1774,1786,1798,1805,1809,1814,1831,1856,1878,1882,1886,1891],{"__ignoreMap":79},[83,1711,1712,1714,1717,1719],{"class":85,"line":86},[83,1713,97],{"class":96},[83,1715,1716],{"class":100}," globalStylePlugin",[83,1718,105],{"class":104},[83,1720,108],{"class":104},[83,1722,1723,1725],{"class":85,"line":93},[83,1724,115],{"class":114},[83,1726,108],{"class":104},[83,1728,1729,1731,1733,1735,1738,1740],{"class":85,"line":111},[83,1730,124],{"class":123},[83,1732,127],{"class":104},[83,1734,131],{"class":130},[83,1736,1737],{"class":134},"global-style",[83,1739,138],{"class":130},[83,1741,141],{"class":104},[83,1743,1744,1747,1749,1752,1754],{"class":85,"line":120},[83,1745,1746],{"class":147},"    transformIndexHtml",[83,1748,151],{"class":104},[83,1750,1751],{"class":154},"html",[83,1753,163],{"class":104},[83,1755,108],{"class":104},[83,1757,1758],{"class":85,"line":144},[83,1759,1760],{"class":89},"      \u002F\u002F 在 HTML 中直接插入 link 标签\n",[83,1762,1763,1765,1767,1769,1771],{"class":85,"line":168},[83,1764,222],{"class":114},[83,1766,606],{"class":177},[83,1768,181],{"class":104},[83,1770,611],{"class":100},[83,1772,1773],{"class":123},"(\n",[83,1775,1776,1779,1782,1784],{"class":85,"line":174},[83,1777,1778],{"class":130},"        \"",[83,1780,1781],{"class":134},"\u003C\u002Fhead>",[83,1783,138],{"class":130},[83,1785,141],{"class":104},[83,1787,1788,1791,1794,1796],{"class":85,"line":219},[83,1789,1790],{"class":130},"        '",[83,1792,1793],{"class":134},"\u003Clink rel=\"stylesheet\" href=\"\u002Fsrc\u002Fstyles\u002Fglobal.css\">\u003C\u002Fhead>",[83,1795,291],{"class":130},[83,1797,141],{"class":104},[83,1799,1800,1803],{"class":85,"line":234},[83,1801,1802],{"class":123},"      )",[83,1804,306],{"class":104},[83,1806,1807],{"class":85,"line":240},[83,1808,237],{"class":104},[83,1810,1811],{"class":85,"line":246},[83,1812,1813],{"class":89},"    \u002F\u002F 或者使用 transform 钩子在 JS 模块中注入 import\n",[83,1815,1816,1819,1821,1823,1825,1827,1829],{"class":85,"line":1581},[83,1817,1818],{"class":147},"    transform",[83,1820,151],{"class":104},[83,1822,32],{"class":154},[83,1824,157],{"class":104},[83,1826,1265],{"class":154},[83,1828,163],{"class":104},[83,1830,108],{"class":104},[83,1832,1833,1835,1837,1839,1841,1843,1845,1847,1850,1852,1854],{"class":85,"line":1598},[83,1834,1528],{"class":114},[83,1836,390],{"class":123},[83,1838,836],{"class":177},[83,1840,181],{"class":104},[83,1842,795],{"class":100},[83,1844,151],{"class":123},[83,1846,138],{"class":130},[83,1848,1849],{"class":134},"main.js",[83,1851,138],{"class":130},[83,1853,807],{"class":123},[83,1855,276],{"class":104},[83,1857,1858,1860,1862,1865,1868,1871,1873,1876],{"class":85,"line":1604},[83,1859,1584],{"class":114},[83,1861,1587],{"class":130},[83,1863,1864],{"class":134},"import '\u002Fsrc\u002Fstyles\u002Fglobal.css';",[83,1866,1867],{"class":420},"\\n",[83,1869,1870],{"class":130},"${",[83,1872,32],{"class":177},[83,1874,1875],{"class":130},"}`",[83,1877,306],{"class":104},[83,1879,1880],{"class":85,"line":1609},[83,1881,1601],{"class":104},[83,1883,1884],{"class":85,"line":1614},[83,1885,237],{"class":104},[83,1887,1889],{"class":85,"line":1888},17,[83,1890,243],{"class":104},[83,1892,1894],{"class":85,"line":1893},18,[83,1895,249],{"class":104},[58,1897,1899],{"id":1898},"_2-组件库按需加载类似-unplugin-vue-components","2. 组件库按需加载（类似 unplugin-vue-components）",[23,1901,1902],{},"自动解析模板中使用的组件并注册，无需手动导入。",[74,1904,1906],{"className":76,"code":1905,"language":78,"meta":79,"style":79},"import fs from \"fs\";\nimport path from \"path\";\n\nfunction autoComponentsPlugin() {\n  const componentsDir = path.resolve(__dirname, \"src\u002Fcomponents\");\n  const componentList = fs.readdirSync(componentsDir).map((file) => path.basename(file, \".vue\"));\n\n  return {\n    name: \"auto-components\",\n    transform(code, id) {\n      if (!id.endsWith(\".vue\")) return;\n      \u002F\u002F 查找模板中使用了哪些组件名（简单正则匹配）\n      const used = [];\n      const regex = \u002F\u003C(?:[\\w-]+)?\\s+([^>]*?)(?:>|$)\u002Fg;\n      let match;\n      while ((match = regex.exec(code))) {\n        const attrs = match[1];\n        const tagMatch = attrs.match(\u002F^(\\w+)\u002F);\n        if (tagMatch && componentList.includes(tagMatch[1])) {\n          used.push(tagMatch[1]);\n        }\n      }\n      if (used.length) {\n        const imports = used\n          .map((name) => `import ${name} from '@\u002Fcomponents\u002F${name}.vue'`)\n          .join(\"\\n\");\n        return `${imports}\\n\u003Cscript>\\nexport default { components: { ${used.join(\",\")} } }\\n\u003C\u002Fscript>${code}`;\n      }\n      return code;\n    },\n  };\n}\n",[32,1907,1908,1927,1945,1949,1960,1994,2057,2061,2067,2082,2098,2127,2132,2147,2227,2237,2266,2286,2322,2356,2380,2386,2391,2410,2423,2470,2490,2550,2555,2565,2570,2575],{"__ignoreMap":79},[83,1909,1910,1912,1915,1918,1920,1923,1925],{"class":85,"line":86},[83,1911,1629],{"class":114},[83,1913,1914],{"class":177}," fs ",[83,1916,1917],{"class":114},"from",[83,1919,131],{"class":130},[83,1921,1922],{"class":134},"fs",[83,1924,138],{"class":130},[83,1926,306],{"class":104},[83,1928,1929,1931,1934,1936,1938,1941,1943],{"class":85,"line":93},[83,1930,1629],{"class":114},[83,1932,1933],{"class":177}," path ",[83,1935,1917],{"class":114},[83,1937,131],{"class":130},[83,1939,1940],{"class":134},"path",[83,1942,138],{"class":130},[83,1944,306],{"class":104},[83,1946,1947],{"class":85,"line":111},[83,1948,1489],{"emptyLinePlaceholder":1488},[83,1950,1951,1953,1956,1958],{"class":85,"line":120},[83,1952,97],{"class":96},[83,1954,1955],{"class":100}," autoComponentsPlugin",[83,1957,105],{"class":104},[83,1959,108],{"class":104},[83,1961,1962,1964,1967,1969,1972,1974,1976,1978,1981,1983,1985,1988,1990,1992],{"class":85,"line":144},[83,1963,1443],{"class":96},[83,1965,1966],{"class":420}," componentsDir",[83,1968,193],{"class":192},[83,1970,1971],{"class":177}," path",[83,1973,181],{"class":104},[83,1975,184],{"class":100},[83,1977,151],{"class":123},[83,1979,1980],{"class":177},"__dirname",[83,1982,157],{"class":104},[83,1984,131],{"class":130},[83,1986,1987],{"class":134},"src\u002Fcomponents",[83,1989,138],{"class":130},[83,1991,163],{"class":123},[83,1993,306],{"class":104},[83,1995,1996,1998,2001,2003,2006,2008,2011,2013,2016,2018,2020,2023,2025,2027,2029,2031,2033,2035,2037,2040,2042,2044,2046,2048,2051,2053,2055],{"class":85,"line":168},[83,1997,1443],{"class":96},[83,1999,2000],{"class":420}," componentList",[83,2002,193],{"class":192},[83,2004,2005],{"class":177}," fs",[83,2007,181],{"class":104},[83,2009,2010],{"class":100},"readdirSync",[83,2012,151],{"class":123},[83,2014,2015],{"class":177},"componentsDir",[83,2017,163],{"class":123},[83,2019,181],{"class":104},[83,2021,2022],{"class":100},"map",[83,2024,151],{"class":123},[83,2026,151],{"class":104},[83,2028,790],{"class":154},[83,2030,163],{"class":104},[83,2032,403],{"class":96},[83,2034,1971],{"class":177},[83,2036,181],{"class":104},[83,2038,2039],{"class":100},"basename",[83,2041,151],{"class":123},[83,2043,790],{"class":177},[83,2045,157],{"class":104},[83,2047,131],{"class":130},[83,2049,2050],{"class":134},".vue",[83,2052,138],{"class":130},[83,2054,450],{"class":123},[83,2056,306],{"class":104},[83,2058,2059],{"class":85,"line":174},[83,2060,1489],{"emptyLinePlaceholder":1488},[83,2062,2063,2065],{"class":85,"line":219},[83,2064,115],{"class":114},[83,2066,108],{"class":104},[83,2068,2069,2071,2073,2075,2078,2080],{"class":85,"line":234},[83,2070,124],{"class":123},[83,2072,127],{"class":104},[83,2074,131],{"class":130},[83,2076,2077],{"class":134},"auto-components",[83,2079,138],{"class":130},[83,2081,141],{"class":104},[83,2083,2084,2086,2088,2090,2092,2094,2096],{"class":85,"line":240},[83,2085,1818],{"class":147},[83,2087,151],{"class":104},[83,2089,32],{"class":154},[83,2091,157],{"class":104},[83,2093,1265],{"class":154},[83,2095,163],{"class":104},[83,2097,108],{"class":104},[83,2099,2100,2102,2104,2107,2109,2111,2113,2115,2117,2119,2121,2123,2125],{"class":85,"line":246},[83,2101,1528],{"class":114},[83,2103,390],{"class":123},[83,2105,2106],{"class":192},"!",[83,2108,836],{"class":177},[83,2110,181],{"class":104},[83,2112,795],{"class":100},[83,2114,151],{"class":123},[83,2116,138],{"class":130},[83,2118,2050],{"class":134},[83,2120,138],{"class":130},[83,2122,807],{"class":123},[83,2124,1541],{"class":114},[83,2126,306],{"class":104},[83,2128,2129],{"class":85,"line":1581},[83,2130,2131],{"class":89},"      \u002F\u002F 查找模板中使用了哪些组件名（简单正则匹配）\n",[83,2133,2134,2137,2140,2142,2145],{"class":85,"line":1598},[83,2135,2136],{"class":96},"      const",[83,2138,2139],{"class":420}," used",[83,2141,193],{"class":192},[83,2143,2144],{"class":123}," []",[83,2146,306],{"class":104},[83,2148,2149,2151,2154,2156,2159,2163,2167,2170,2174,2177,2180,2182,2185,2188,2190,2192,2194,2197,2200,2202,2205,2208,2210,2213,2216,2218,2221,2225],{"class":85,"line":1604},[83,2150,2136],{"class":96},[83,2152,2153],{"class":420}," regex",[83,2155,193],{"class":192},[83,2157,2158],{"class":130}," \u002F",[83,2160,2162],{"class":2161},"sQRbd","\u003C",[83,2164,2166],{"class":2165},"s-KJb","(?:",[83,2168,2169],{"class":316},"[",[83,2171,2173],{"class":2172},"stzsN","\\w-",[83,2175,2176],{"class":316},"]",[83,2178,2179],{"class":192},"+",[83,2181,163],{"class":2165},[83,2183,2184],{"class":192},"?",[83,2186,2187],{"class":2172},"\\s",[83,2189,2179],{"class":192},[83,2191,151],{"class":2165},[83,2193,2169],{"class":316},[83,2195,2196],{"class":192},"^",[83,2198,2199],{"class":2172},">",[83,2201,2176],{"class":316},[83,2203,2204],{"class":192},"*?",[83,2206,2207],{"class":2165},")(?:",[83,2209,2199],{"class":2161},[83,2211,2212],{"class":192},"|",[83,2214,2215],{"class":114},"$",[83,2217,163],{"class":2165},[83,2219,2220],{"class":130},"\u002F",[83,2222,2224],{"class":2223},"sw1J6","g",[83,2226,306],{"class":104},[83,2228,2229,2232,2235],{"class":85,"line":1609},[83,2230,2231],{"class":96},"      let",[83,2233,2234],{"class":177}," match",[83,2236,306],{"class":104},[83,2238,2239,2242,2245,2248,2250,2252,2254,2257,2259,2261,2264],{"class":85,"line":1614},[83,2240,2241],{"class":114},"      while",[83,2243,2244],{"class":123}," ((",[83,2246,2247],{"class":177},"match",[83,2249,193],{"class":192},[83,2251,2153],{"class":177},[83,2253,181],{"class":104},[83,2255,2256],{"class":100},"exec",[83,2258,151],{"class":123},[83,2260,32],{"class":177},[83,2262,2263],{"class":123},"))) ",[83,2265,276],{"class":104},[83,2267,2268,2271,2273,2275,2277,2279,2282,2284],{"class":85,"line":1888},[83,2269,2270],{"class":96},"        const",[83,2272,683],{"class":420},[83,2274,193],{"class":192},[83,2276,2234],{"class":177},[83,2278,2169],{"class":123},[83,2280,2281],{"class":1270},"1",[83,2283,2176],{"class":123},[83,2285,306],{"class":104},[83,2287,2288,2290,2293,2295,2297,2299,2301,2303,2305,2307,2309,2312,2314,2316,2318,2320],{"class":85,"line":1893},[83,2289,2270],{"class":96},[83,2291,2292],{"class":420}," tagMatch",[83,2294,193],{"class":192},[83,2296,683],{"class":177},[83,2298,181],{"class":104},[83,2300,2247],{"class":100},[83,2302,151],{"class":123},[83,2304,2220],{"class":130},[83,2306,2196],{"class":114},[83,2308,151],{"class":2165},[83,2310,2311],{"class":2172},"\\w",[83,2313,2179],{"class":192},[83,2315,163],{"class":2165},[83,2317,2220],{"class":130},[83,2319,163],{"class":123},[83,2321,306],{"class":104},[83,2323,2325,2328,2330,2333,2336,2338,2340,2343,2345,2347,2349,2351,2354],{"class":85,"line":2324},19,[83,2326,2327],{"class":114},"        if",[83,2329,390],{"class":123},[83,2331,2332],{"class":177},"tagMatch",[83,2334,2335],{"class":192}," &&",[83,2337,2000],{"class":177},[83,2339,181],{"class":104},[83,2341,2342],{"class":100},"includes",[83,2344,151],{"class":123},[83,2346,2332],{"class":177},[83,2348,2169],{"class":123},[83,2350,2281],{"class":1270},[83,2352,2353],{"class":123},"])) ",[83,2355,276],{"class":104},[83,2357,2359,2362,2364,2367,2369,2371,2373,2375,2378],{"class":85,"line":2358},20,[83,2360,2361],{"class":177},"          used",[83,2363,181],{"class":104},[83,2365,2366],{"class":100},"push",[83,2368,151],{"class":123},[83,2370,2332],{"class":177},[83,2372,2169],{"class":123},[83,2374,2281],{"class":1270},[83,2376,2377],{"class":123},"])",[83,2379,306],{"class":104},[83,2381,2383],{"class":85,"line":2382},21,[83,2384,2385],{"class":104},"        }\n",[83,2387,2389],{"class":85,"line":2388},22,[83,2390,1601],{"class":104},[83,2392,2394,2396,2398,2401,2403,2406,2408],{"class":85,"line":2393},23,[83,2395,1528],{"class":114},[83,2397,390],{"class":123},[83,2399,2400],{"class":177},"used",[83,2402,181],{"class":104},[83,2404,2405],{"class":420},"length",[83,2407,773],{"class":123},[83,2409,276],{"class":104},[83,2411,2413,2415,2418,2420],{"class":85,"line":2412},24,[83,2414,2270],{"class":96},[83,2416,2417],{"class":420}," imports",[83,2419,193],{"class":192},[83,2421,2422],{"class":177}," used\n",[83,2424,2426,2429,2431,2433,2435,2438,2440,2442,2444,2447,2449,2451,2453,2456,2458,2460,2462,2465,2467],{"class":85,"line":2425},25,[83,2427,2428],{"class":104},"          .",[83,2430,2022],{"class":100},[83,2432,151],{"class":123},[83,2434,151],{"class":104},[83,2436,2437],{"class":154},"name",[83,2439,163],{"class":104},[83,2441,403],{"class":96},[83,2443,1587],{"class":130},[83,2445,2446],{"class":134},"import ",[83,2448,1870],{"class":130},[83,2450,2437],{"class":177},[83,2452,770],{"class":130},[83,2454,2455],{"class":134}," from '@\u002Fcomponents\u002F",[83,2457,1870],{"class":130},[83,2459,2437],{"class":177},[83,2461,770],{"class":130},[83,2463,2464],{"class":134},".vue'",[83,2466,1593],{"class":130},[83,2468,2469],{"class":123},")\n",[83,2471,2473,2475,2478,2480,2482,2484,2486,2488],{"class":85,"line":2472},26,[83,2474,2428],{"class":104},[83,2476,2477],{"class":100},"join",[83,2479,151],{"class":123},[83,2481,138],{"class":130},[83,2483,1867],{"class":420},[83,2485,138],{"class":130},[83,2487,163],{"class":123},[83,2489,306],{"class":104},[83,2491,2493,2495,2498,2501,2503,2505,2508,2510,2513,2515,2517,2519,2521,2524,2526,2528,2530,2532,2534,2537,2539,2542,2544,2546,2548],{"class":85,"line":2492},27,[83,2494,1584],{"class":114},[83,2496,2497],{"class":130}," `${",[83,2499,2500],{"class":177},"imports",[83,2502,770],{"class":130},[83,2504,1867],{"class":420},[83,2506,2507],{"class":134},"\u003Cscript>",[83,2509,1867],{"class":420},[83,2511,2512],{"class":134},"export default { components: { ",[83,2514,1870],{"class":130},[83,2516,2400],{"class":177},[83,2518,181],{"class":130},[83,2520,2477],{"class":100},[83,2522,151],{"class":2523},"sfo-9",[83,2525,138],{"class":130},[83,2527,157],{"class":134},[83,2529,138],{"class":130},[83,2531,163],{"class":2523},[83,2533,770],{"class":130},[83,2535,2536],{"class":134}," } }",[83,2538,1867],{"class":420},[83,2540,2541],{"class":134},"\u003C\u002Fscript>",[83,2543,1870],{"class":130},[83,2545,32],{"class":177},[83,2547,1875],{"class":130},[83,2549,306],{"class":104},[83,2551,2553],{"class":85,"line":2552},28,[83,2554,1601],{"class":104},[83,2556,2558,2560,2563],{"class":85,"line":2557},29,[83,2559,222],{"class":114},[83,2561,2562],{"class":177}," code",[83,2564,306],{"class":104},[83,2566,2568],{"class":85,"line":2567},30,[83,2569,237],{"class":104},[83,2571,2573],{"class":85,"line":2572},31,[83,2574,243],{"class":104},[83,2576,2578],{"class":85,"line":2577},32,[83,2579,249],{"class":104},[58,2581,2583],{"id":2582},"_3-自动生成-api-类型文件","3. 自动生成 API 类型文件",[23,2585,2586],{},"根据后端接口定义（如 OpenAPI 或自定义 JSON）生成 TypeScript 类型定义并作为虚拟模块提供。",[74,2588,2590],{"className":76,"code":2589,"language":78,"meta":79,"style":79},"import { generateTypes } from \".\u002Fapi-generator\";\n\nfunction apiTypesPlugin() {\n  const virtualId = \"virtual:api-types\";\n  const resolvedId = \"\\0\" + virtualId;\n  let typesContent = \"\";\n\n  return {\n    name: \"api-types\",\n    buildStart() {\n      typesContent = generateTypes(); \u002F\u002F 生成类型字符串\n    },\n    resolveId(id) {\n      if (id === virtualId) return resolvedId;\n    },\n    load(id) {\n      if (id === resolvedId) return typesContent;\n    },\n  };\n}\n",[32,2591,2592,2614,2618,2629,2647,2668,2683,2687,2693,2708,2717,2733,2737,2749,2769,2773,2785,2805,2809,2813],{"__ignoreMap":79},[83,2593,2594,2596,2598,2601,2603,2605,2607,2610,2612],{"class":85,"line":86},[83,2595,1629],{"class":114},[83,2597,196],{"class":104},[83,2599,2600],{"class":177}," generateTypes",[83,2602,447],{"class":104},[83,2604,1639],{"class":114},[83,2606,131],{"class":130},[83,2608,2609],{"class":134},".\u002Fapi-generator",[83,2611,138],{"class":130},[83,2613,306],{"class":104},[83,2615,2616],{"class":85,"line":93},[83,2617,1489],{"emptyLinePlaceholder":1488},[83,2619,2620,2622,2625,2627],{"class":85,"line":111},[83,2621,97],{"class":96},[83,2623,2624],{"class":100}," apiTypesPlugin",[83,2626,105],{"class":104},[83,2628,108],{"class":104},[83,2630,2631,2633,2636,2638,2640,2643,2645],{"class":85,"line":120},[83,2632,1443],{"class":96},[83,2634,2635],{"class":420}," virtualId",[83,2637,193],{"class":192},[83,2639,131],{"class":130},[83,2641,2642],{"class":134},"virtual:api-types",[83,2644,138],{"class":130},[83,2646,306],{"class":104},[83,2648,2649,2651,2654,2656,2658,2660,2662,2664,2666],{"class":85,"line":144},[83,2650,1443],{"class":96},[83,2652,2653],{"class":420}," resolvedId",[83,2655,193],{"class":192},[83,2657,131],{"class":130},[83,2659,1471],{"class":420},[83,2661,138],{"class":130},[83,2663,1476],{"class":192},[83,2665,2635],{"class":177},[83,2667,306],{"class":104},[83,2669,2670,2673,2676,2678,2681],{"class":85,"line":168},[83,2671,2672],{"class":96},"  let",[83,2674,2675],{"class":177}," typesContent",[83,2677,193],{"class":192},[83,2679,2680],{"class":130}," \"\"",[83,2682,306],{"class":104},[83,2684,2685],{"class":85,"line":174},[83,2686,1489],{"emptyLinePlaceholder":1488},[83,2688,2689,2691],{"class":85,"line":219},[83,2690,115],{"class":114},[83,2692,108],{"class":104},[83,2694,2695,2697,2699,2701,2704,2706],{"class":85,"line":234},[83,2696,124],{"class":123},[83,2698,127],{"class":104},[83,2700,131],{"class":130},[83,2702,2703],{"class":134},"api-types",[83,2705,138],{"class":130},[83,2707,141],{"class":104},[83,2709,2710,2713,2715],{"class":85,"line":240},[83,2711,2712],{"class":147},"    buildStart",[83,2714,105],{"class":104},[83,2716,108],{"class":104},[83,2718,2719,2722,2724,2726,2728,2730],{"class":85,"line":246},[83,2720,2721],{"class":177},"      typesContent",[83,2723,193],{"class":192},[83,2725,2600],{"class":100},[83,2727,105],{"class":123},[83,2729,228],{"class":104},[83,2731,2732],{"class":89}," \u002F\u002F 生成类型字符串\n",[83,2734,2735],{"class":85,"line":1581},[83,2736,237],{"class":104},[83,2738,2739,2741,2743,2745,2747],{"class":85,"line":1598},[83,2740,1515],{"class":147},[83,2742,151],{"class":104},[83,2744,836],{"class":154},[83,2746,163],{"class":104},[83,2748,108],{"class":104},[83,2750,2751,2753,2755,2757,2759,2761,2763,2765,2767],{"class":85,"line":1604},[83,2752,1528],{"class":114},[83,2754,390],{"class":123},[83,2756,836],{"class":177},[83,2758,839],{"class":192},[83,2760,2635],{"class":177},[83,2762,773],{"class":123},[83,2764,1541],{"class":114},[83,2766,2653],{"class":177},[83,2768,306],{"class":104},[83,2770,2771],{"class":85,"line":1609},[83,2772,237],{"class":104},[83,2774,2775,2777,2779,2781,2783],{"class":85,"line":1614},[83,2776,1554],{"class":147},[83,2778,151],{"class":104},[83,2780,836],{"class":154},[83,2782,163],{"class":104},[83,2784,108],{"class":104},[83,2786,2787,2789,2791,2793,2795,2797,2799,2801,2803],{"class":85,"line":1888},[83,2788,1528],{"class":114},[83,2790,390],{"class":123},[83,2792,836],{"class":177},[83,2794,839],{"class":192},[83,2796,2653],{"class":177},[83,2798,773],{"class":123},[83,2800,1541],{"class":114},[83,2802,2675],{"class":177},[83,2804,306],{"class":104},[83,2806,2807],{"class":85,"line":1893},[83,2808,237],{"class":104},[83,2810,2811],{"class":85,"line":2324},[83,2812,243],{"class":104},[83,2814,2815],{"class":85,"line":2358},[83,2816,249],{"class":104},[23,2818,2819],{},"然后在代码中：",[74,2821,2825],{"className":2822,"code":2823,"language":2824,"meta":79,"style":79},"language-ts shiki shiki-themes material-theme-lighter github-light github-dark","import type { User, Post } from \"virtual:api-types\";\n","ts",[32,2826,2827],{"__ignoreMap":79},[83,2828,2829,2831,2834,2836,2839,2841,2844,2846,2848,2850,2852,2854],{"class":85,"line":86},[83,2830,1629],{"class":114},[83,2832,2833],{"class":114}," type",[83,2835,196],{"class":104},[83,2837,2838],{"class":177}," User",[83,2840,157],{"class":104},[83,2842,2843],{"class":177}," Post",[83,2845,447],{"class":104},[83,2847,1639],{"class":114},[83,2849,131],{"class":130},[83,2851,2642],{"class":134},[83,2853,138],{"class":130},[83,2855,306],{"class":104},[50,2857,2858],{"id":2858},"总结",[876,2860,2861,2871],{},[879,2862,2863],{},[882,2864,2865,2867,2869],{},[885,2866,887],{},[885,2868,68],{},[885,2870,1669],{},[898,2872,2873,2885,2897,2909,2921],{},[882,2874,2875,2879,2882],{},[903,2876,2877],{},[32,2878,34],{},[903,2880,2881],{},"修改配置",[903,2883,2884],{},"动态添加 alias、proxy",[882,2886,2887,2891,2894],{},[903,2888,2889],{},[32,2890,38],{},[903,2892,2893],{},"添加自定义中间件",[903,2895,2896],{},"Mock API、代理",[882,2898,2899,2903,2906],{},[903,2900,2901],{},[32,2902,41],{},[903,2904,2905],{},"转换 HTML",[903,2907,2908],{},"注入 script、meta",[882,2910,2911,2915,2918],{},[903,2912,2913],{},[32,2914,736],{},[903,2916,2917],{},"自定义 HMR",[903,2919,2920],{},"特定模块只更新自身",[882,2922,2923,2926,2929],{},[903,2924,2925],{},"虚拟模块",[903,2927,2928],{},"动态生成模块内容",[903,2930,2931],{},"类型、路由、常量",[23,2933,2934],{},"Vite 插件开发充分利用这些钩子，可以极大扩展 Vite 的能力，满足各种工程化需求。开发时注意区分开发\u002F生产环境，合理使用 Rollup 兼容钩子。",[2936,2937,2938],"h2",{"id":2938},"参考文献",[23,2940,2941],{},"以下链接在编写时均可正常访问：",[876,2943,2944,2953],{},[879,2945,2946],{},[882,2947,2948,2951],{},[885,2949,2950],{},"资料",[885,2952,896],{},[898,2954,2955,2968],{},[882,2956,2957,2965],{},[903,2958,2959],{},[44,2960,2964],{"href":2961,"rel":2962},"https:\u002F\u002Fcn.vite.dev\u002Fguide\u002Fapi-plugin",[2963],"nofollow","插件 API",[903,2966,2967],{},"官方",[882,2969,2970,2977],{},[903,2971,2972],{},[44,2973,2976],{"href":2974,"rel":2975},"https:\u002F\u002Frollupjs.org\u002Fplugin-development\u002F",[2963],"Rollup 插件",[903,2978,2979],{},"兼容基础",[2981,2982,2983],"style",{},"html pre.shiki code .sutJx, html code.shiki .sutJx{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#6A737D;--shiki-default-font-style:inherit;--shiki-dark:#6A737D;--shiki-dark-font-style:inherit}html pre.shiki code .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sGLFI, html code.shiki .sGLFI{--shiki-light:#6182B8;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sVHd0, html code.shiki .sVHd0{--shiki-light:#39ADB5;--shiki-light-font-style:italic;--shiki-default:#D73A49;--shiki-default-font-style:inherit;--shiki-dark:#F97583;--shiki-dark-font-style:inherit}html pre.shiki code .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sjJ54, html code.shiki .sjJ54{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html pre.shiki code .sVXei, html code.shiki .sVXei{--shiki-light:#E53935;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s99_P, html code.shiki .s99_P{--shiki-light:#90A4AE;--shiki-light-font-style:italic;--shiki-default:#E36209;--shiki-default-font-style:inherit;--shiki-dark:#FFAB70;--shiki-dark-font-style:inherit}html pre.shiki code .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sZUrc, html code.shiki .sZUrc{--shiki-light:#E53935;--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}html.light .shiki span {color: var(--shiki-light);background: var(--shiki-light-bg);font-style: var(--shiki-light-font-style);font-weight: var(--shiki-light-font-weight);text-decoration: var(--shiki-light-text-decoration);}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 .s39Yj, html code.shiki .s39Yj{--shiki-light:#39ADB5;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sQRbd, html code.shiki .sQRbd{--shiki-light:#91B859;--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .s-KJb, html code.shiki .s-KJb{--shiki-light:#39ADB5;--shiki-default:#032F62;--shiki-dark:#DBEDFF}html pre.shiki code .stzsN, html code.shiki .stzsN{--shiki-light:#91B859;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sw1J6, html code.shiki .sw1J6{--shiki-light:#F76D47;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sfo-9, html code.shiki .sfo-9{--shiki-light:#90A4AE;--shiki-default:#032F62;--shiki-dark:#9ECBFF}",{"title":79,"searchDepth":93,"depth":93,"links":2985},[2986,2987,2988,2989,2990,2991,2992],{"id":52,"depth":111,"text":53},{"id":870,"depth":111,"text":871},{"id":1075,"depth":111,"text":1076},{"id":1402,"depth":111,"text":1403},{"id":1696,"depth":111,"text":1697},{"id":2858,"depth":111,"text":2858},{"id":2938,"depth":93,"text":2938},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fproject\u002FVite\u002Fplugin","knowledge\u002Fknowledge\u002Fbooklet\u002Fproject\u002FVite\u002Fplugin.md","md",{"items":2998},[2999,3003,3007,3011,3015,3017],{"path":3000,"title":3001,"description":3002,"category":10,"score":168},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fdeploy","部署实践","Vite 项目的 CI\u002FCD、多环境、CDN、Legacy 与体积预算等工程化要点。环境变量见 env；构建见 生产构建。",{"path":3004,"title":3005,"description":3006,"category":10,"score":168},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fadvanced","进阶配置","Vite 进阶：server.proxy、resolve.alias、SSR、多页面、库模式、vite preview 等。环境变量见 env。",{"path":3008,"title":3009,"description":3010,"category":10,"score":168},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fbuild","生产构建","vite build 使用 Rollup 打包并应用内置优化。开发阶段原理见 工作原理。",{"path":3012,"title":3013,"description":3014,"category":10,"score":168},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fvite\u002Fcreate-vite","create-vite","pnpm create vite 实际执行的是 npm 包 create-vite（与 vite 本体不同）。工程化背景见 工程化概览、工作原理。",{"path":46,"title":47,"description":3016,"category":10,"score":168},"Vite 是面向现代浏览器的前端构建工具：开发阶段利用原生 ES 模块与按需编译；生产构建由 Rollup 完成。对比见 Webpack 与 Vite、工程化概览。",{"path":3018,"title":3019,"description":3020,"category":10,"score":120},"\u002Fknowledge\u002Fbooklet\u002Fproject\u002Fproject\u002Fother","其他配置","除 ESLint、Prettier 等规范文件外，仓库中常见的工具链与包管理配置如下。见 工程化概览。",{"series":3022,"title":12,"items":3023,"index":120,"prev":3035,"next":3036},"booklet\u002Fproject\u002Fvite",[3024,3026,3028,3030,3032,3033],{"path":3004,"title":3005,"date":3025,"pinned":15},"2022-05-08",{"path":3008,"title":3009,"date":3027,"pinned":15},"2021-07-24",{"path":3012,"title":3013,"date":3029,"pinned":15},"2021-03-05",{"path":3000,"title":3001,"date":3031,"pinned":15},"2025-10-12",{"path":7,"title":8,"date":14,"pinned":15},{"path":46,"title":47,"date":3034,"pinned":15},"2020-06-15",{"path":3000,"title":3001,"date":3031,"pinned":15},{"path":46,"title":47,"date":3034,"pinned":15}]