[{"data":1,"prerenderedAt":1029},["ShallowReactive",2],{"doc-page:\u002Fdocs\u002Fapi-design":3},{"doc":4,"prev":994,"next":1001,"resolvedType":8,"readingMinutes":249,"audience":1005,"checklist":1009,"related":1013},{"path":5,"title":6,"description":7,"docType":8,"resourceKind":9,"categoryId":10,"categoryLabel":11,"updatedAt":12,"publishedAt":12,"icon":13,"body":14},"\u002Fdocs\u002Fapi-design","RESTful API 设计","REST API 设计规范、状态码、认证方案、版本控制与文档工具","article",null,"programming-languages","编程语言","2026-02-27","i-carbon-application",{"type":15,"value":16,"toc":967},"minimark",[17,21,25,29,32,48,51,55,66,70,214,217,221,299,303,389,392,470,474,477,483,486,512,515,518,522,528,649,653,659,662,668,671,674,698,700,703,709,713,796,799,863,866,870,885,889,896,899,911,914,934,937,963],[18,19,6],"h1",{"id":20},"restful-api-设计",[22,23,24],"p",{},"这页适合作为“面向团队协作的 API 设计基线”。真正好的 API，不只是能返回数据，而是命名稳定、错误可读、分页一致、版本演进可控，前后端和第三方调用者都能长期接得住。",[26,27,28],"h2",{"id":28},"推荐设计顺序",[22,30,31],{},"设计 API 时，建议按下面顺序思考：",[33,34,35,39,42,45],"ol",{},[36,37,38],"li",{},"先明确资源模型与 URL 命名",[36,40,41],{},"再统一响应格式、错误格式、状态码语义",[36,43,44],{},"然后补认证、权限、限流与幂等性",[36,46,47],{},"最后处理版本控制、文档与测试",[22,49,50],{},"如果一开始就只关注“接口能不能调通”，后面最容易出问题的往往是命名混乱和兼容性失控。",[26,52,54],{"id":53},"url-设计","URL 设计",[56,57,62],"pre",{"className":58,"code":60,"language":61},[59],"language-text","# 资源用名词复数\nGET    \u002Fapi\u002Fusers          # 获取用户列表\nGET    \u002Fapi\u002Fusers\u002F123      # 获取单个用户\nPOST   \u002Fapi\u002Fusers          # 创建用户\nPUT    \u002Fapi\u002Fusers\u002F123      # 更新用户（全量）\nPATCH  \u002Fapi\u002Fusers\u002F123      # 更新用户（部分）\nDELETE \u002Fapi\u002Fusers\u002F123      # 删除用户\n\n# 嵌套资源\nGET    \u002Fapi\u002Fusers\u002F123\u002Fposts        # 用户的文章\nPOST   \u002Fapi\u002Fusers\u002F123\u002Fposts        # 为用户创建文章\n\n# 查询参数\nGET    \u002Fapi\u002Fusers?page=1&limit=20&sort=-created_at\nGET    \u002Fapi\u002Fusers?search=domi&role=admin\n","text",[63,64,60],"code",{"__ignoreMap":65},"",[26,67,69],{"id":68},"http-状态码","HTTP 状态码",[71,72,73,89],"table",{},[74,75,76],"thead",{},[77,78,79,83,86],"tr",{},[80,81,82],"th",{},"状态码",[80,84,85],{},"含义",[80,87,88],{},"使用场景",[90,91,92,104,115,126,137,148,159,170,181,192,203],"tbody",{},[77,93,94,98,101],{},[95,96,97],"td",{},"200",[95,99,100],{},"OK",[95,102,103],{},"成功",[77,105,106,109,112],{},[95,107,108],{},"201",[95,110,111],{},"Created",[95,113,114],{},"创建成功",[77,116,117,120,123],{},[95,118,119],{},"204",[95,121,122],{},"No Content",[95,124,125],{},"删除成功",[77,127,128,131,134],{},[95,129,130],{},"400",[95,132,133],{},"Bad Request",[95,135,136],{},"请求参数错误",[77,138,139,142,145],{},[95,140,141],{},"401",[95,143,144],{},"Unauthorized",[95,146,147],{},"未认证",[77,149,150,153,156],{},[95,151,152],{},"403",[95,154,155],{},"Forbidden",[95,157,158],{},"无权限",[77,160,161,164,167],{},[95,162,163],{},"404",[95,165,166],{},"Not Found",[95,168,169],{},"资源不存在",[77,171,172,175,178],{},[95,173,174],{},"409",[95,176,177],{},"Conflict",[95,179,180],{},"资源冲突",[77,182,183,186,189],{},[95,184,185],{},"422",[95,187,188],{},"Unprocessable Entity",[95,190,191],{},"验证失败",[77,193,194,197,200],{},[95,195,196],{},"429",[95,198,199],{},"Too Many Requests",[95,201,202],{},"限流",[77,204,205,208,211],{},[95,206,207],{},"500",[95,209,210],{},"Internal Server Error",[95,212,213],{},"服务器错误",[26,215,216],{"id":216},"响应格式",[218,219,220],"h3",{"id":220},"成功响应",[56,222,226],{"className":223,"code":224,"language":225,"meta":65,"style":65},"language-json shiki shiki-themes github-light github-dark","{\n  \"data\": {\n    \"id\": 123,\n    \"name\": \"Domi\",\n    \"email\": \"[email]\"\n  }\n}\n","json",[63,227,228,237,247,262,276,287,293],{"__ignoreMap":65},[229,230,233],"span",{"class":231,"line":232},"line",1,[229,234,236],{"class":235},"sVt8B","{\n",[229,238,240,244],{"class":231,"line":239},2,[229,241,243],{"class":242},"sj4cs","  \"data\"",[229,245,246],{"class":235},": {\n",[229,248,250,253,256,259],{"class":231,"line":249},3,[229,251,252],{"class":242},"    \"id\"",[229,254,255],{"class":235},": ",[229,257,258],{"class":242},"123",[229,260,261],{"class":235},",\n",[229,263,265,268,270,274],{"class":231,"line":264},4,[229,266,267],{"class":242},"    \"name\"",[229,269,255],{"class":235},[229,271,273],{"class":272},"sZZnC","\"Domi\"",[229,275,261],{"class":235},[229,277,279,282,284],{"class":231,"line":278},5,[229,280,281],{"class":242},"    \"email\"",[229,283,255],{"class":235},[229,285,286],{"class":272},"\"[email]\"\n",[229,288,290],{"class":231,"line":289},6,[229,291,292],{"class":235},"  }\n",[229,294,296],{"class":231,"line":295},7,[229,297,298],{"class":235},"}\n",[218,300,302],{"id":301},"列表响应分页","列表响应（分页）",[56,304,306],{"className":223,"code":305,"language":225,"meta":65,"style":65},"{\n  \"data\": [...],\n  \"meta\": {\n    \"page\": 1,\n    \"limit\": 20,\n    \"total\": 100,\n    \"totalPages\": 5\n  }\n}\n",[63,307,308,312,326,333,345,357,369,379,384],{"__ignoreMap":65},[229,309,310],{"class":231,"line":232},[229,311,236],{"class":235},[229,313,314,316,319,323],{"class":231,"line":239},[229,315,243],{"class":242},[229,317,318],{"class":235},": [",[229,320,322],{"class":321},"s7hpK","...",[229,324,325],{"class":235},"],\n",[229,327,328,331],{"class":231,"line":249},[229,329,330],{"class":242},"  \"meta\"",[229,332,246],{"class":235},[229,334,335,338,340,343],{"class":231,"line":264},[229,336,337],{"class":242},"    \"page\"",[229,339,255],{"class":235},[229,341,342],{"class":242},"1",[229,344,261],{"class":235},[229,346,347,350,352,355],{"class":231,"line":278},[229,348,349],{"class":242},"    \"limit\"",[229,351,255],{"class":235},[229,353,354],{"class":242},"20",[229,356,261],{"class":235},[229,358,359,362,364,367],{"class":231,"line":289},[229,360,361],{"class":242},"    \"total\"",[229,363,255],{"class":235},[229,365,366],{"class":242},"100",[229,368,261],{"class":235},[229,370,371,374,376],{"class":231,"line":295},[229,372,373],{"class":242},"    \"totalPages\"",[229,375,255],{"class":235},[229,377,378],{"class":242},"5\n",[229,380,382],{"class":231,"line":381},8,[229,383,292],{"class":235},[229,385,387],{"class":231,"line":386},9,[229,388,298],{"class":235},[218,390,391],{"id":391},"错误响应",[56,393,395],{"className":223,"code":394,"language":225,"meta":65,"style":65},"{\n  \"error\": {\n    \"code\": \"VALIDATION_ERROR\",\n    \"message\": \"请求参数验证失败\",\n    \"details\": [{ \"field\": \"email\", \"message\": \"邮箱格式不正确\" }]\n  }\n}\n",[63,396,397,401,408,420,432,462,466],{"__ignoreMap":65},[229,398,399],{"class":231,"line":232},[229,400,236],{"class":235},[229,402,403,406],{"class":231,"line":239},[229,404,405],{"class":242},"  \"error\"",[229,407,246],{"class":235},[229,409,410,413,415,418],{"class":231,"line":249},[229,411,412],{"class":242},"    \"code\"",[229,414,255],{"class":235},[229,416,417],{"class":272},"\"VALIDATION_ERROR\"",[229,419,261],{"class":235},[229,421,422,425,427,430],{"class":231,"line":264},[229,423,424],{"class":242},"    \"message\"",[229,426,255],{"class":235},[229,428,429],{"class":272},"\"请求参数验证失败\"",[229,431,261],{"class":235},[229,433,434,437,440,443,445,448,451,454,456,459],{"class":231,"line":278},[229,435,436],{"class":242},"    \"details\"",[229,438,439],{"class":235},": [{ ",[229,441,442],{"class":242},"\"field\"",[229,444,255],{"class":235},[229,446,447],{"class":272},"\"email\"",[229,449,450],{"class":235},", ",[229,452,453],{"class":242},"\"message\"",[229,455,255],{"class":235},[229,457,458],{"class":272},"\"邮箱格式不正确\"",[229,460,461],{"class":235}," }]\n",[229,463,464],{"class":231,"line":289},[229,465,292],{"class":235},[229,467,468],{"class":231,"line":295},[229,469,298],{"class":235},[26,471,473],{"id":472},"分页筛选排序建议","分页、筛选、排序建议",[22,475,476],{},"这类规则一旦定下来，最好全站统一：",[56,478,481],{"className":479,"code":480,"language":61,"meta":65},[59],"GET \u002Fapi\u002Fusers?page=1&limit=20\nGET \u002Fapi\u002Fusers?sort=-created_at\nGET \u002Fapi\u002Fusers?search=domi&role=admin\n",[63,482,480],{"__ignoreMap":65},[22,484,485],{},"建议：",[487,488,489,499,509],"ul",{},[36,490,491,494,495,498],{},[63,492,493],{},"page"," \u002F ",[63,496,497],{},"limit"," 用于传统分页",[36,500,501,504,505,508],{},[63,502,503],{},"sort=-created_at"," 用 ",[63,506,507],{},"-"," 表示倒序，风格直观",[36,510,511],{},"筛选字段尽量与资源属性同名，避免同一概念多套叫法",[22,513,514],{},"如果系统以后会有大列表、高频翻页或无限加载，也可以尽早评估 cursor pagination。",[26,516,517],{"id":517},"认证方案",[218,519,521],{"id":520},"jwtjson-web-token","JWT（JSON Web Token）",[56,523,526],{"className":524,"code":525,"language":61},[59],"Authorization: Bearer eyJhbGciOiJIUzI1NiIs...\n",[63,527,525],{"__ignoreMap":65},[56,529,533],{"className":530,"code":531,"language":532,"meta":65,"style":65},"language-javascript shiki shiki-themes github-light github-dark","\u002F\u002F 生成\nimport jwt from \"jsonwebtoken\";\n\nconst token = jwt.sign({ userId: 123, role: \"admin\" }, process.env.JWT_SECRET, {\n  expiresIn: \"7d\",\n});\n\n\u002F\u002F 验证\nconst payload = jwt.verify(token, process.env.JWT_SECRET);\n","javascript",[63,534,535,541,559,565,603,613,618,622,627],{"__ignoreMap":65},[229,536,537],{"class":231,"line":232},[229,538,540],{"class":539},"sJ8bj","\u002F\u002F 生成\n",[229,542,543,547,550,553,556],{"class":231,"line":239},[229,544,546],{"class":545},"szBVR","import",[229,548,549],{"class":235}," jwt ",[229,551,552],{"class":545},"from",[229,554,555],{"class":272}," \"jsonwebtoken\"",[229,557,558],{"class":235},";\n",[229,560,561],{"class":231,"line":249},[229,562,564],{"emptyLinePlaceholder":563},true,"\n",[229,566,567,570,573,576,579,583,586,588,591,594,597,600],{"class":231,"line":264},[229,568,569],{"class":545},"const",[229,571,572],{"class":242}," token",[229,574,575],{"class":545}," =",[229,577,578],{"class":235}," jwt.",[229,580,582],{"class":581},"sScJk","sign",[229,584,585],{"class":235},"({ userId: ",[229,587,258],{"class":242},[229,589,590],{"class":235},", role: ",[229,592,593],{"class":272},"\"admin\"",[229,595,596],{"class":235}," }, process.env.",[229,598,599],{"class":242},"JWT_SECRET",[229,601,602],{"class":235},", {\n",[229,604,605,608,611],{"class":231,"line":278},[229,606,607],{"class":235},"  expiresIn: ",[229,609,610],{"class":272},"\"7d\"",[229,612,261],{"class":235},[229,614,615],{"class":231,"line":289},[229,616,617],{"class":235},"});\n",[229,619,620],{"class":231,"line":295},[229,621,564],{"emptyLinePlaceholder":563},[229,623,624],{"class":231,"line":381},[229,625,626],{"class":539},"\u002F\u002F 验证\n",[229,628,629,631,634,636,638,641,644,646],{"class":231,"line":386},[229,630,569],{"class":545},[229,632,633],{"class":242}," payload",[229,635,575],{"class":545},[229,637,578],{"class":235},[229,639,640],{"class":581},"verify",[229,642,643],{"class":235},"(token, process.env.",[229,645,599],{"class":242},[229,647,648],{"class":235},");\n",[218,650,652],{"id":651},"api-key","API Key",[56,654,657],{"className":655,"code":656,"language":61},[59],"# Header\nX-API-Key: sk-xxxxxxxxxxxx\n\n# 或查询参数\nGET \u002Fapi\u002Fdata?api_key=sk-xxxxxxxxxxxx\n",[63,658,656],{"__ignoreMap":65},[26,660,661],{"id":661},"版本控制",[56,663,666],{"className":664,"code":665,"language":61},[59],"# URL 路径（推荐）\n\u002Fapi\u002Fv1\u002Fusers\n\u002Fapi\u002Fv2\u002Fusers\n\n# Header\nAccept: application\u002Fvnd.myapi.v2+json\n",[63,667,665],{"__ignoreMap":65},[26,669,670],{"id":670},"幂等与写操作建议",[22,672,673],{},"写接口时，除了成功与失败，还要考虑“重复请求会怎样”：",[487,675,676,689,695],{},[36,677,678,681,682,681,685,688],{},[63,679,680],{},"GET","、",[63,683,684],{},"PUT",[63,686,687],{},"DELETE"," 天然更适合设计成幂等",[36,690,691,694],{},[63,692,693],{},"POST"," 创建资源时，如果客户端可能重试，最好考虑幂等键或业务去重",[36,696,697],{},"支付、回调、任务创建这类接口，尤其要避免重复提交造成脏数据",[26,699,202],{"id":202},[22,701,702],{},"响应头中返回限流信息：",[56,704,707],{"className":705,"code":706,"language":61},[59],"X-RateLimit-Limit: 100\nX-RateLimit-Remaining: 95\nX-RateLimit-Reset: 1709020800\n",[63,708,706],{"__ignoreMap":65},[26,710,712],{"id":711},"cors","CORS",[56,714,716],{"className":530,"code":715,"language":532,"meta":65,"style":65},"\u002F\u002F Express\napp.use(\n  cors({\n    origin: [\"https:\u002F\u002Fexample.com\"],\n    methods: [\"GET\", \"POST\", \"PUT\", \"DELETE\"],\n    credentials: true,\n  }),\n);\n",[63,717,718,723,734,742,752,777,787,792],{"__ignoreMap":65},[229,719,720],{"class":231,"line":232},[229,721,722],{"class":539},"\u002F\u002F Express\n",[229,724,725,728,731],{"class":231,"line":239},[229,726,727],{"class":235},"app.",[229,729,730],{"class":581},"use",[229,732,733],{"class":235},"(\n",[229,735,736,739],{"class":231,"line":249},[229,737,738],{"class":581},"  cors",[229,740,741],{"class":235},"({\n",[229,743,744,747,750],{"class":231,"line":264},[229,745,746],{"class":235},"    origin: [",[229,748,749],{"class":272},"\"https:\u002F\u002Fexample.com\"",[229,751,325],{"class":235},[229,753,754,757,760,762,765,767,770,772,775],{"class":231,"line":278},[229,755,756],{"class":235},"    methods: [",[229,758,759],{"class":272},"\"GET\"",[229,761,450],{"class":235},[229,763,764],{"class":272},"\"POST\"",[229,766,450],{"class":235},[229,768,769],{"class":272},"\"PUT\"",[229,771,450],{"class":235},[229,773,774],{"class":272},"\"DELETE\"",[229,776,325],{"class":235},[229,778,779,782,785],{"class":231,"line":289},[229,780,781],{"class":235},"    credentials: ",[229,783,784],{"class":242},"true",[229,786,261],{"class":235},[229,788,789],{"class":231,"line":295},[229,790,791],{"class":235},"  }),\n",[229,793,794],{"class":231,"line":381},[229,795,648],{"class":235},[26,797,798],{"id":798},"文档工具",[71,800,801,811],{},[74,802,803],{},[77,804,805,808],{},[80,806,807],{},"工具",[80,809,810],{},"说明",[90,812,813,827,839,851],{},[77,814,815,824],{},[95,816,817],{},[818,819,823],"a",{"href":820,"rel":821},"https:\u002F\u002Fswagger.io\u002F",[822],"nofollow","Swagger\u002FOpenAPI",[95,825,826],{},"API 规范标准",[77,828,829,836],{},[95,830,831],{},[818,832,835],{"href":833,"rel":834},"https:\u002F\u002Fscalar.com\u002F",[822],"Scalar",[95,837,838],{},"现代 API 文档",[77,840,841,848],{},[95,842,843],{},[818,844,847],{"href":845,"rel":846},"https:\u002F\u002Fwww.usebruno.com\u002F",[822],"Bruno",[95,849,850],{},"开源 API 客户端",[77,852,853,860],{},[95,854,855],{},[818,856,859],{"href":857,"rel":858},"https:\u002F\u002Fhoppscotch.io\u002F",[822],"Hoppscotch",[95,861,862],{},"在线 API 测试",[26,864,865],{"id":865},"常见问题",[218,867,869],{"id":868},"url-和资源命名不统一","URL 和资源命名不统一",[22,871,872,873,876,877,880,881,884],{},"例如一会儿叫 ",[63,874,875],{},"\u002Fusers","，一会儿叫 ",[63,878,879],{},"\u002Fuser-list","，一会儿又是 ",[63,882,883],{},"\u002FgetUsers","。这会让前端、文档、测试、SDK 都越来越难维护。资源 URL 尽量保持名词化和稳定。",[218,886,888],{"id":887},"状态码都返回-200","状态码都返回 200",[22,890,891,892,895],{},"这会让调用方很难区分真成功和业务失败。即使接口里有 ",[63,893,894],{},"success: false","，也不应该完全放弃 HTTP 状态码语义。",[218,897,898],{"id":898},"错误结构每个接口都不一样",[22,900,901,902,681,904,681,907,910],{},"一旦错误结构不统一，前端就只能写大量特判。建议把 ",[63,903,63],{},[63,905,906],{},"message",[63,908,909],{},"details"," 这类字段尽量统一下来。",[26,912,913],{"id":913},"延伸阅读",[487,915,916,922,928],{},[36,917,918],{},[818,919,921],{"href":920},"\u002Fdocs\u002Fapi-testing","API 测试与调试",[36,923,924],{},[818,925,927],{"href":926},"\u002Fdocs\u002Ftesting-guide","前端测试指南",[36,929,930],{},[818,931,933],{"href":932},"\u002Fdocs\u002Fenv-variables","环境变量与配置管理",[26,935,936],{"id":936},"参考链接",[487,938,939,947,955],{},[36,940,941,946],{},[818,942,945],{"href":943,"rel":944},"https:\u002F\u002Fgithub.com\u002Finteragent\u002Fhttp-api-design",[822],"HTTP API Design Guide"," — 设计指南",[36,948,949,954],{},[818,950,953],{"href":951,"rel":952},"https:\u002F\u002Frestfulapi.net\u002F",[822],"REST API Tutorial"," — 教程",[36,956,957,962],{},[818,958,961],{"href":959,"rel":960},"https:\u002F\u002Fspec.openapis.org\u002Foas\u002Flatest.html",[822],"OpenAPI 规范"," — 官方规范",[964,965,966],"style",{},"html pre.shiki code .sVt8B, html code.shiki .sVt8B{--shiki-default:#24292E;--shiki-dark:#E1E4E8}html pre.shiki code .sj4cs, html code.shiki .sj4cs{--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .sZZnC, html code.shiki .sZZnC{--shiki-default:#032F62;--shiki-dark:#9ECBFF}html .default .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .shiki span {color: var(--shiki-default);background: var(--shiki-default-bg);font-style: var(--shiki-default-font-style);font-weight: var(--shiki-default-font-weight);text-decoration: var(--shiki-default-text-decoration);}html .dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html.dark .shiki span {color: var(--shiki-dark);background: var(--shiki-dark-bg);font-style: var(--shiki-dark-font-style);font-weight: var(--shiki-dark-font-weight);text-decoration: var(--shiki-dark-text-decoration);}html pre.shiki code .s7hpK, html code.shiki .s7hpK{--shiki-default:#B31D28;--shiki-default-font-style:italic;--shiki-dark:#FDAEB7;--shiki-dark-font-style:italic}html pre.shiki code .sJ8bj, html code.shiki .sJ8bj{--shiki-default:#6A737D;--shiki-dark:#6A737D}html pre.shiki code .szBVR, html code.shiki .szBVR{--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .sScJk, html code.shiki .sScJk{--shiki-default:#6F42C1;--shiki-dark:#B392F0}",{"title":65,"searchDepth":239,"depth":239,"links":968},[969,970,971,972,977,978,982,983,984,985,986,987,992,993],{"id":28,"depth":239,"text":28},{"id":53,"depth":239,"text":54},{"id":68,"depth":239,"text":69},{"id":216,"depth":239,"text":216,"children":973},[974,975,976],{"id":220,"depth":249,"text":220},{"id":301,"depth":249,"text":302},{"id":391,"depth":249,"text":391},{"id":472,"depth":239,"text":473},{"id":517,"depth":239,"text":517,"children":979},[980,981],{"id":520,"depth":249,"text":521},{"id":651,"depth":249,"text":652},{"id":661,"depth":239,"text":661},{"id":670,"depth":239,"text":670},{"id":202,"depth":239,"text":202},{"id":711,"depth":239,"text":712},{"id":798,"depth":239,"text":798},{"id":865,"depth":239,"text":865,"children":988},[989,990,991],{"id":868,"depth":249,"text":869},{"id":887,"depth":249,"text":888},{"id":898,"depth":249,"text":898},{"id":913,"depth":239,"text":913},{"id":936,"depth":239,"text":936},{"path":995,"title":996,"description":997,"docType":8,"resourceKind":9,"categoryId":998,"categoryLabel":999,"updatedAt":12,"publishedAt":12,"icon":1000},"\u002Fdocs\u002Fqbittorrent-setup","qBittorrent 配置指南","qBittorrent 安装、Tracker 配置、RSS 订阅与进阶设置","entertainment-resources","娱乐与资源","i-carbon-game-console",{"path":1002,"title":1003,"description":1004,"docType":8,"resourceKind":9,"categoryId":10,"categoryLabel":11,"updatedAt":12,"publishedAt":12,"icon":13},"\u002Fdocs\u002Frust-basics","Rust 入门","Rust 安装、Cargo 使用、所有权系统、常用模式与工具链",[1006,1007,1008],"希望把零散经验整理成长期可复用工作流的人","想先建立认知，再决定是否深入实践的人","希望阅读时顺手建立自己的操作清单或收藏体系的人",[1010,1011,1012],"先浏览标题、摘要和目录，带着问题阅读会更高效","顺手记录真正对你有用的命令、链接和注意事项，避免重复搜索","如果页面里提到相关文档，尽量一起打开对照，效果通常更完整",[1014,1017,1021,1025],{"path":926,"title":927,"description":1015,"docType":8,"resourceKind":9,"categoryId":10,"categoryLabel":11,"updatedAt":1016,"publishedAt":1016,"icon":13},"Vitest 单元测试、Playwright E2E 测试、测试策略与最佳实践","2026-02-28",{"path":1018,"title":1019,"description":1020,"docType":8,"resourceKind":9,"categoryId":10,"categoryLabel":11,"updatedAt":1016,"publishedAt":1016,"icon":13},"\u002Fdocs\u002Fbun-deno","Bun 与 Deno 运行时","Bun 和 Deno 的安装使用、与 Node.js 对比、包管理与实用命令",{"path":1022,"title":1023,"description":1024,"docType":8,"resourceKind":9,"categoryId":10,"categoryLabel":11,"updatedAt":1016,"publishedAt":1016,"icon":13},"\u002Fdocs\u002Fcss-tricks","CSS 实用技巧","现代 CSS 特性、布局技巧、动画、暗色模式与常用代码片段",{"path":1026,"title":1027,"description":1028,"docType":8,"resourceKind":9,"categoryId":10,"categoryLabel":11,"updatedAt":1016,"publishedAt":1016,"icon":13},"\u002Fdocs\u002Fredis-guide","Redis 使用指南","Redis 安装、数据类型、常用命令、缓存策略与 Node.js 集成",1776215711781]