[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"knowledge-\u002Fapi\u002Fknowledge\u002Fbooklet\u002Fend\u002Fejs":3,"knowledge-related-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fejs":1916,"knowledge-series-\u002Fknowledge\u002Fbooklet\u002Fend\u002Fejs":1941},{"source":4,"connector":5,"page":6},"sqlite","better-sqlite3",{"path":7,"title":8,"description":9,"category":10,"tags":11,"date":13,"pinned":14,"draft":14,"body":15,"seo":1912,"stem":1913,"id":1914,"extension":1915},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fejs","EJS","EJS（Embedded JavaScript templates）在 HTML 中嵌入 JavaScript，常用于 Express 服务端渲染（SSR）。","技能小册",[12],"ejs","2019-11-03",false,{"type":16,"value":17,"toc":1894},"minimark",[18,21,36,41,74,78,83,108,111,127,131,181,488,492,495,631,635,717,721,780,784,790,918,922,937,1136,1140,1405,1409,1416,1591,1595,1606,1717,1721,1800,1804,1815,1836,1839,1842,1890],[19,20,8],"h1",{"id":12},[22,23,24,30,31,35],"p",{},[25,26,8],"a",{"href":27,"rel":28},"https:\u002F\u002Fejs.co\u002F",[29],"nofollow","（Embedded JavaScript templates）在 HTML 中嵌入 JavaScript，常用于 ",[25,32,34],{"href":33},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fexpress","Express"," 服务端渲染（SSR）。",[37,38,40],"h2",{"id":39},"一ejs-基础概念","一、EJS 基础概念",[42,43,44,52,58,64],"ul",{},[45,46,47,51],"li",{},[48,49,50],"strong",{},"什么是 EJS","：Embedded JavaScript templates，是一款简单高效的嵌入式 JavaScript 模板引擎。",[45,53,54,57],{},[48,55,56],{},"核心定位","：允许在 HTML 中嵌入 JavaScript 代码，实现动态内容生成和复用。",[45,59,60,63],{},[48,61,62],{},"主要优势","：语法简单、可内嵌 JavaScript、与 Express 无缝集成。",[45,65,66,69,70],{},[48,67,68],{},"模板文件后缀","：",[71,72,73],"code",{},".ejs",[37,75,77],{"id":76},"二安装与基础使用","二、安装与基础使用",[79,80,82],"h3",{"id":81},"_1-安装","1. 安装",[84,85,90],"pre",{"className":86,"code":87,"language":88,"meta":89,"style":89},"language-bash shiki shiki-themes material-theme-lighter github-light github-dark","npm install ejs\n","bash","",[71,91,92],{"__ignoreMap":89},[93,94,97,101,105],"span",{"class":95,"line":96},"line",1,[93,98,100],{"class":99},"sbgvK","npm",[93,102,104],{"class":103},"s_sjI"," install",[93,106,107],{"class":103}," ejs\n",[22,109,110],{},"也可同时安装 Express（如需配合使用）：",[84,112,114],{"className":86,"code":113,"language":88,"meta":89,"style":89},"npm install express ejs\n",[71,115,116],{"__ignoreMap":89},[93,117,118,120,122,125],{"class":95,"line":96},[93,119,100],{"class":99},[93,121,104],{"class":103},[93,123,124],{"class":103}," express",[93,126,107],{"class":103},[79,128,130],{"id":129},"_2-核心-api","2. 核心 API",[132,133,134,147],"table",{},[135,136,137],"thead",{},[138,139,140,144],"tr",{},[141,142,143],"th",{},"方法",[141,145,146],{},"说明",[148,149,150,161,171],"tbody",{},[138,151,152,158],{},[153,154,155],"td",{},[71,156,157],{},"ejs.compile(str, options)",[153,159,160],{},"编译模板字符串为可复用的渲染函数",[138,162,163,168],{},[153,164,165],{},[71,166,167],{},"ejs.render(str, data, options)",[153,169,170],{},"渲染模板字符串，直接输出 HTML",[138,172,173,178],{},[153,174,175],{},[71,176,177],{},"ejs.renderFile(filename, data, options, callback)",[153,179,180],{},"读取并渲染模板文件",[84,182,186],{"className":183,"code":184,"language":185,"meta":89,"style":89},"language-javascript shiki shiki-themes material-theme-lighter github-light github-dark","const ejs = require(\"ejs\");\n\n\u002F\u002F 方式一：compile（适合多次使用同一模板）\nconst template = ejs.compile(\"\u003Ch1>\u003C%= name %>\u003C\u002Fh1>\");\nconst html = template({ name: \"张三\" });\n\n\u002F\u002F 方式二：render（一次性渲染）\nconst html2 = ejs.render(\"\u003Ch1>\u003C%= name %>\u003C\u002Fh1>\", { name: \"李四\" });\n\n\u002F\u002F 方式三：renderFile（从文件读取）\nejs.renderFile(\".\u002Fviews\u002Findex.ejs\", { title: \"首页\" }, (err, html) => {\n  if (err) throw err;\n  console.log(html);\n});\n","javascript",[71,187,188,225,232,239,270,309,314,320,368,373,379,436,458,478],{"__ignoreMap":89},[93,189,190,194,198,202,206,210,214,216,218,221],{"class":95,"line":96},[93,191,193],{"class":192},"sbsja","const",[93,195,197],{"class":196},"s_hVV"," ejs",[93,199,201],{"class":200},"smGrS"," =",[93,203,205],{"class":204},"sGLFI"," require",[93,207,209],{"class":208},"su5hD","(",[93,211,213],{"class":212},"sjJ54","\"",[93,215,12],{"class":103},[93,217,213],{"class":212},[93,219,220],{"class":208},")",[93,222,224],{"class":223},"sP7_E",";\n",[93,226,228],{"class":95,"line":227},2,[93,229,231],{"emptyLinePlaceholder":230},true,"\n",[93,233,235],{"class":95,"line":234},3,[93,236,238],{"class":237},"sutJx","\u002F\u002F 方式一：compile（适合多次使用同一模板）\n",[93,240,242,244,247,249,251,254,257,259,261,264,266,268],{"class":95,"line":241},4,[93,243,193],{"class":192},[93,245,246],{"class":196}," template",[93,248,201],{"class":200},[93,250,197],{"class":208},[93,252,253],{"class":223},".",[93,255,256],{"class":204},"compile",[93,258,209],{"class":208},[93,260,213],{"class":212},[93,262,263],{"class":103},"\u003Ch1>\u003C%= name %>\u003C\u002Fh1>",[93,265,213],{"class":212},[93,267,220],{"class":208},[93,269,224],{"class":223},[93,271,273,275,278,280,282,284,287,291,294,297,300,302,305,307],{"class":95,"line":272},5,[93,274,193],{"class":192},[93,276,277],{"class":196}," html",[93,279,201],{"class":200},[93,281,246],{"class":204},[93,283,209],{"class":208},[93,285,286],{"class":223},"{",[93,288,290],{"class":289},"skxfh"," name",[93,292,293],{"class":223},":",[93,295,296],{"class":212}," \"",[93,298,299],{"class":103},"张三",[93,301,213],{"class":212},[93,303,304],{"class":223}," }",[93,306,220],{"class":208},[93,308,224],{"class":223},[93,310,312],{"class":95,"line":311},6,[93,313,231],{"emptyLinePlaceholder":230},[93,315,317],{"class":95,"line":316},7,[93,318,319],{"class":237},"\u002F\u002F 方式二：render（一次性渲染）\n",[93,321,323,325,328,330,332,334,337,339,341,343,345,348,351,353,355,357,360,362,364,366],{"class":95,"line":322},8,[93,324,193],{"class":192},[93,326,327],{"class":196}," html2",[93,329,201],{"class":200},[93,331,197],{"class":208},[93,333,253],{"class":223},[93,335,336],{"class":204},"render",[93,338,209],{"class":208},[93,340,213],{"class":212},[93,342,263],{"class":103},[93,344,213],{"class":212},[93,346,347],{"class":223},",",[93,349,350],{"class":223}," {",[93,352,290],{"class":289},[93,354,293],{"class":223},[93,356,296],{"class":212},[93,358,359],{"class":103},"李四",[93,361,213],{"class":212},[93,363,304],{"class":223},[93,365,220],{"class":208},[93,367,224],{"class":223},[93,369,371],{"class":95,"line":370},9,[93,372,231],{"emptyLinePlaceholder":230},[93,374,376],{"class":95,"line":375},10,[93,377,378],{"class":237},"\u002F\u002F 方式三：renderFile（从文件读取）\n",[93,380,382,384,386,389,391,393,396,398,400,402,405,407,409,412,414,417,420,424,426,428,430,433],{"class":95,"line":381},11,[93,383,12],{"class":208},[93,385,253],{"class":223},[93,387,388],{"class":204},"renderFile",[93,390,209],{"class":208},[93,392,213],{"class":212},[93,394,395],{"class":103},".\u002Fviews\u002Findex.ejs",[93,397,213],{"class":212},[93,399,347],{"class":223},[93,401,350],{"class":223},[93,403,404],{"class":289}," title",[93,406,293],{"class":223},[93,408,296],{"class":212},[93,410,411],{"class":103},"首页",[93,413,213],{"class":212},[93,415,416],{"class":223}," },",[93,418,419],{"class":223}," (",[93,421,423],{"class":422},"s99_P","err",[93,425,347],{"class":223},[93,427,277],{"class":422},[93,429,220],{"class":223},[93,431,432],{"class":192}," =>",[93,434,435],{"class":223}," {\n",[93,437,439,443,445,447,450,453,456],{"class":95,"line":438},12,[93,440,442],{"class":441},"sVHd0","  if",[93,444,419],{"class":289},[93,446,423],{"class":208},[93,448,449],{"class":289},") ",[93,451,452],{"class":441},"throw",[93,454,455],{"class":208}," err",[93,457,224],{"class":223},[93,459,461,464,466,469,471,474,476],{"class":95,"line":460},13,[93,462,463],{"class":208},"  console",[93,465,253],{"class":223},[93,467,468],{"class":204},"log",[93,470,209],{"class":289},[93,472,473],{"class":208},"html",[93,475,220],{"class":289},[93,477,224],{"class":223},[93,479,481,484,486],{"class":95,"line":480},14,[93,482,483],{"class":223},"}",[93,485,220],{"class":208},[93,487,224],{"class":223},[37,489,491],{"id":490},"三核心标签语法","三、核心标签语法",[22,493,494],{},"EJS 使用特殊的标签在 HTML 中嵌入 JavaScript 代码。",[132,496,497,509],{},[135,498,499],{},[138,500,501,504,506],{},[141,502,503],{},"标签",[141,505,146],{},[141,507,508],{},"示例",[148,510,511,529,551,569,587,605],{},[138,512,513,518,524],{},[153,514,515],{},[71,516,517],{},"\u003C%= ... %>",[153,519,520,523],{},[48,521,522],{},"输出标签","：输出变量值，自动 HTML 转义（防止 XSS）",[153,525,526],{},[71,527,528],{},"\u003Ch1>\u003C%= title %>\u003C\u002Fh1>",[138,530,531,536,546],{},[153,532,533],{},[71,534,535],{},"\u003C%- ... %>",[153,537,538,541,542,545],{},[48,539,540],{},"原始输出标签","：输出未经转义的原始 HTML（",[48,543,544],{},"慎用","，需确保内容安全）",[153,547,548],{},[71,549,550],{},"\u003Cdiv>\u003C%- article.content %>\u003C\u002Fdiv>",[138,552,553,558,564],{},[153,554,555],{},[71,556,557],{},"\u003C% ... %>",[153,559,560,563],{},[48,561,562],{},"脚本标签","：执行 JavaScript 逻辑（条件、循环等），不输出内容",[153,565,566],{},[71,567,568],{},"\u003C% if (user) { %>\u003C% } %>",[138,570,571,576,582],{},[153,572,573],{},[71,574,575],{},"\u003C%# ... %>",[153,577,578,581],{},[48,579,580],{},"注释标签","：添加注释，不会出现在最终输出中",[153,583,584],{},[71,585,586],{},"\u003C%# 这是注释 %>",[138,588,589,594,600],{},[153,590,591],{},[71,592,593],{},"\u003C%_ ... _%>",[153,595,596,599],{},[48,597,598],{},"空白修剪标签","：自动去除标签前后的空白字符",[153,601,602],{},[71,603,604],{},"\u003C%_ for (...) { _%>",[138,606,607,612,626],{},[153,608,609],{},[71,610,611],{},"\u003C%% %%>",[153,613,614,617,618,621,622,625],{},[48,615,616],{},"原始标签","：输出 ",[71,619,620],{},"\u003C%"," 或 ",[71,623,624],{},"%>"," 字符本身，避免被解析",[153,627,628],{},[71,629,630],{},"\u003Cp>使用\u003C%%= variable %%>输出\u003C\u002Fp>",[37,632,634],{"id":633},"四条件渲染","四、条件渲染",[84,636,640],{"className":637,"code":638,"language":639,"meta":89,"style":89},"language-js shiki shiki-themes material-theme-lighter github-light github-dark","\u003C% if (isLoggedIn) { %>\n  \u003Cp>欢迎回来，\u003C%= user.name %>！\u003C\u002Fp>\n\u003C% } else { %>\n  \u003Cp>请先登录。\u003C\u002Fp>\n\u003C% } %>\n","js",[71,641,642,657,679,692,709],{"__ignoreMap":89},[93,643,644,646,649,652,654],{"class":95,"line":96},[93,645,620],{"class":200},[93,647,648],{"class":441}," if",[93,650,651],{"class":208}," (isLoggedIn) ",[93,653,286],{"class":223},[93,655,656],{"class":200}," %>\n",[93,658,659,662,665,668,671,674,676],{"class":95,"line":227},[93,660,661],{"class":223},"  \u003C",[93,663,22],{"class":664},"sQzsp",[93,666,667],{"class":223},">",[93,669,670],{"class":208},"欢迎回来，\u003C%= user.name %>！",[93,672,673],{"class":223},"\u003C\u002F",[93,675,22],{"class":664},[93,677,678],{"class":223},">\n",[93,680,681,683,685,688,690],{"class":95,"line":234},[93,682,620],{"class":200},[93,684,304],{"class":223},[93,686,687],{"class":441}," else",[93,689,350],{"class":223},[93,691,656],{"class":200},[93,693,694,696,698,700,703,705,707],{"class":95,"line":241},[93,695,661],{"class":223},[93,697,22],{"class":664},[93,699,667],{"class":223},[93,701,702],{"class":208},"请先登录。",[93,704,673],{"class":223},[93,706,22],{"class":664},[93,708,678],{"class":223},[93,710,711,713,715],{"class":95,"line":272},[93,712,620],{"class":200},[93,714,304],{"class":223},[93,716,656],{"class":200},[37,718,720],{"id":719},"五循环","五、循环",[84,722,724],{"className":637,"code":723,"language":639,"meta":89,"style":89},"\u003Cul>\n  \u003C% products.forEach(product => { %>\n    \u003Cli>\u003C%= product.name %> - ¥\u003C%= product.price %>\u003C\u002Fli>\n  \u003C% }) %>\n\u003C\u002Ful>\n",[71,725,726,735,744,762,772],{"__ignoreMap":89},[93,727,728,731,733],{"class":95,"line":96},[93,729,730],{"class":223},"\u003C",[93,732,42],{"class":664},[93,734,678],{"class":223},[93,736,737,740,742],{"class":95,"line":227},[93,738,739],{"class":208},"  \u003C% products.forEach(product => ",[93,741,286],{"class":223},[93,743,656],{"class":200},[93,745,746,749,751,753,756,758,760],{"class":95,"line":234},[93,747,748],{"class":223},"    \u003C",[93,750,45],{"class":664},[93,752,667],{"class":223},[93,754,755],{"class":208},"\u003C%= product.name %> - ¥\u003C%= product.price %>",[93,757,673],{"class":223},[93,759,45],{"class":664},[93,761,678],{"class":223},[93,763,764,767,769],{"class":95,"line":241},[93,765,766],{"class":200},"  \u003C%",[93,768,304],{"class":223},[93,770,771],{"class":208},") %>\n",[93,773,774,776,778],{"class":95,"line":272},[93,775,673],{"class":223},[93,777,42],{"class":664},[93,779,678],{"class":223},[37,781,783],{"id":782},"六include-机制模块化","六、Include 机制（模块化）",[22,785,786,789],{},[71,787,788],{},"\u003C%- include('partial') %>"," 用于在模板中引入其他模板文件，实现代码复用。",[42,791,792,862,905],{},[45,793,794,69,797],{},[48,795,796],{},"基础用法",[84,798,800],{"className":637,"code":799,"language":639,"meta":89,"style":89},"\u003C%- include('header') %>\n\u003Cmain>页面内容\u003C\u002Fmain>\n\u003C%- include('footer') %>\n",[71,801,802,825,843],{"__ignoreMap":89},[93,803,804,807,810,812,815,818,820,822],{"class":95,"line":96},[93,805,806],{"class":200},"\u003C%-",[93,808,809],{"class":204}," include",[93,811,209],{"class":208},[93,813,814],{"class":212},"'",[93,816,817],{"class":103},"header",[93,819,814],{"class":212},[93,821,449],{"class":208},[93,823,824],{"class":200},"%>\n",[93,826,827,829,832,834,837,839,841],{"class":95,"line":227},[93,828,730],{"class":223},[93,830,831],{"class":664},"main",[93,833,667],{"class":223},[93,835,836],{"class":208},"页面内容",[93,838,673],{"class":223},[93,840,831],{"class":664},[93,842,678],{"class":223},[93,844,845,847,849,851,853,856,858,860],{"class":95,"line":234},[93,846,806],{"class":200},[93,848,809],{"class":204},[93,850,209],{"class":208},[93,852,814],{"class":212},[93,854,855],{"class":103},"footer",[93,857,814],{"class":212},[93,859,449],{"class":208},[93,861,824],{"class":200},[45,863,864,69,867],{},[48,865,866],{},"传递参数给被包含的模板",[84,868,870],{"className":637,"code":869,"language":639,"meta":89,"style":89},"\u003C%- include('user\u002Fprofile', { user: currentUser }) %>\n",[71,871,872],{"__ignoreMap":89},[93,873,874,876,878,880,882,885,887,889,891,894,896,899,901,903],{"class":95,"line":96},[93,875,806],{"class":200},[93,877,809],{"class":204},[93,879,209],{"class":208},[93,881,814],{"class":212},[93,883,884],{"class":103},"user\u002Fprofile",[93,886,814],{"class":212},[93,888,347],{"class":223},[93,890,350],{"class":223},[93,892,893],{"class":289}," user",[93,895,293],{"class":223},[93,897,898],{"class":208}," currentUser ",[93,900,483],{"class":223},[93,902,449],{"class":208},[93,904,824],{"class":200},[45,906,907,69,910],{},[48,908,909],{},"文件夹结构示例",[84,911,916],{"className":912,"code":914,"language":915},[913],"language-text","views\u002F\n├── index.ejs          # 主模板\n└── partials\u002F\n    ├── header.ejs     # 导航栏\n    └── footer.ejs     # 页脚\n","text",[71,917,914],{"__ignoreMap":89},[37,919,921],{"id":920},"七layout-模板继承","七、Layout \u002F 模板继承",[22,923,924,925,928,929,932,933,936],{},"EJS ",[48,926,927],{},"原生不支持","完整的模板继承（如 Jinja2 的 ",[71,930,931],{},"extends","、",[71,934,935],{},"block","），需要通过以下方式实现：",[938,939,940,1056,1126],"ol",{},[45,941,942,945,946],{},[48,943,944],{},"使用 Include 组织 Layout","（最常用）：",[84,947,949],{"className":637,"code":948,"language":639,"meta":89,"style":89},"\u003C!-- layout.ejs -->\n\u003C!DOCTYPE html>\n\u003Chtml>\n\u003Chead>\u003Ctitle>\u003C%= title %>\u003C\u002Ftitle>\u003C\u002Fhead>\n\u003Cbody>\n  \u003C%- include('header') %>\n  \u003C%- body %>\n  \u003C%- include('footer') %>\n\u003C\u002Fbody>\n\u003C\u002Fhtml>\n",[71,950,951,967,979,987,1016,1025,1030,1035,1040,1048],{"__ignoreMap":89},[93,952,953,956,959,961,964],{"class":95,"line":96},[93,954,955],{"class":200},"\u003C!--",[93,957,958],{"class":208}," layout",[93,960,253],{"class":223},[93,962,963],{"class":208},"ejs ",[93,965,966],{"class":200},"-->\n",[93,968,969,972,975,977],{"class":95,"line":227},[93,970,971],{"class":200},"\u003C!",[93,973,974],{"class":196},"DOCTYPE",[93,976,277],{"class":208},[93,978,678],{"class":200},[93,980,981,983,985],{"class":95,"line":234},[93,982,730],{"class":223},[93,984,473],{"class":664},[93,986,678],{"class":223},[93,988,989,991,994,997,1000,1002,1005,1007,1009,1012,1014],{"class":95,"line":241},[93,990,730],{"class":223},[93,992,993],{"class":664},"head",[93,995,996],{"class":223},">\u003C",[93,998,999],{"class":664},"title",[93,1001,667],{"class":223},[93,1003,1004],{"class":208},"\u003C%= title %>",[93,1006,673],{"class":223},[93,1008,999],{"class":664},[93,1010,1011],{"class":223},">\u003C\u002F",[93,1013,993],{"class":664},[93,1015,678],{"class":223},[93,1017,1018,1020,1023],{"class":95,"line":272},[93,1019,730],{"class":223},[93,1021,1022],{"class":664},"body",[93,1024,678],{"class":223},[93,1026,1027],{"class":95,"line":311},[93,1028,1029],{"class":208},"  \u003C%- include('header') %>\n",[93,1031,1032],{"class":95,"line":316},[93,1033,1034],{"class":208},"  \u003C%- body %>\n",[93,1036,1037],{"class":95,"line":322},[93,1038,1039],{"class":208},"  \u003C%- include('footer') %>\n",[93,1041,1042,1044,1046],{"class":95,"line":370},[93,1043,673],{"class":223},[93,1045,1022],{"class":664},[93,1047,678],{"class":223},[93,1049,1050,1052,1054],{"class":95,"line":375},[93,1051,673],{"class":223},[93,1053,473],{"class":664},[93,1055,678],{"class":223},[45,1057,1058,69,1065,1079],{},[48,1059,1060,1061,1064],{},"使用 ",[71,1062,1063],{},"express-ejs-layouts"," 中间件",[84,1066,1068],{"className":86,"code":1067,"language":88,"meta":89,"style":89},"npm install express-ejs-layouts\n",[71,1069,1070],{"__ignoreMap":89},[93,1071,1072,1074,1076],{"class":95,"line":96},[93,1073,100],{"class":99},[93,1075,104],{"class":103},[93,1077,1078],{"class":103}," express-ejs-layouts\n",[84,1080,1082],{"className":183,"code":1081,"language":185,"meta":89,"style":89},"const expressLayouts = require(\"express-ejs-layouts\");\napp.use(expressLayouts); \u002F\u002F 默认使用 views\u002Flayout.ejs\n",[71,1083,1084,1107],{"__ignoreMap":89},[93,1085,1086,1088,1091,1093,1095,1097,1099,1101,1103,1105],{"class":95,"line":96},[93,1087,193],{"class":192},[93,1089,1090],{"class":196}," expressLayouts",[93,1092,201],{"class":200},[93,1094,205],{"class":204},[93,1096,209],{"class":208},[93,1098,213],{"class":212},[93,1100,1063],{"class":103},[93,1102,213],{"class":212},[93,1104,220],{"class":208},[93,1106,224],{"class":223},[93,1108,1109,1112,1114,1117,1120,1123],{"class":95,"line":227},[93,1110,1111],{"class":208},"app",[93,1113,253],{"class":223},[93,1115,1116],{"class":204},"use",[93,1118,1119],{"class":208},"(expressLayouts)",[93,1121,1122],{"class":223},";",[93,1124,1125],{"class":237}," \u002F\u002F 默认使用 views\u002Flayout.ejs\n",[45,1127,1128,1131,1132,1135],{},[48,1129,1130],{},"手动传递 Layout 数据","：通过局部变量或第三方库（如 ",[71,1133,1134],{},"ejs-locals","）组织布局块。",[37,1137,1139],{"id":1138},"八与-express-集成","八、与 Express 集成",[84,1141,1143],{"className":183,"code":1142,"language":185,"meta":89,"style":89},"const express = require(\"express\");\nconst app = express();\n\n\u002F\u002F 1. 设置模板引擎为 ejs\napp.set(\"view engine\", \"ejs\");\n\u002F\u002F 2. 设置模板文件存放目录（默认可不写）\napp.set(\"views\", path.join(__dirname, \"views\"));\n\n\u002F\u002F 3. 在路由中使用 res.render() 渲染\napp.get(\"\u002F\", (req, res) => {\n  res.render(\"index\", {\n    title: \"首页\",\n    user: { name: \"张三\", isAdmin: true },\n  });\n});\n",[71,1144,1145,1168,1184,1188,1193,1223,1228,1271,1275,1280,1316,1338,1354,1387,1396],{"__ignoreMap":89},[93,1146,1147,1149,1151,1153,1155,1157,1159,1162,1164,1166],{"class":95,"line":96},[93,1148,193],{"class":192},[93,1150,124],{"class":196},[93,1152,201],{"class":200},[93,1154,205],{"class":204},[93,1156,209],{"class":208},[93,1158,213],{"class":212},[93,1160,1161],{"class":103},"express",[93,1163,213],{"class":212},[93,1165,220],{"class":208},[93,1167,224],{"class":223},[93,1169,1170,1172,1175,1177,1179,1182],{"class":95,"line":227},[93,1171,193],{"class":192},[93,1173,1174],{"class":196}," app",[93,1176,201],{"class":200},[93,1178,124],{"class":204},[93,1180,1181],{"class":208},"()",[93,1183,224],{"class":223},[93,1185,1186],{"class":95,"line":234},[93,1187,231],{"emptyLinePlaceholder":230},[93,1189,1190],{"class":95,"line":241},[93,1191,1192],{"class":237},"\u002F\u002F 1. 设置模板引擎为 ejs\n",[93,1194,1195,1197,1199,1202,1204,1206,1209,1211,1213,1215,1217,1219,1221],{"class":95,"line":272},[93,1196,1111],{"class":208},[93,1198,253],{"class":223},[93,1200,1201],{"class":204},"set",[93,1203,209],{"class":208},[93,1205,213],{"class":212},[93,1207,1208],{"class":103},"view engine",[93,1210,213],{"class":212},[93,1212,347],{"class":223},[93,1214,296],{"class":212},[93,1216,12],{"class":103},[93,1218,213],{"class":212},[93,1220,220],{"class":208},[93,1222,224],{"class":223},[93,1224,1225],{"class":95,"line":311},[93,1226,1227],{"class":237},"\u002F\u002F 2. 设置模板文件存放目录（默认可不写）\n",[93,1229,1230,1232,1234,1236,1238,1240,1243,1245,1247,1250,1252,1255,1258,1260,1262,1264,1266,1269],{"class":95,"line":316},[93,1231,1111],{"class":208},[93,1233,253],{"class":223},[93,1235,1201],{"class":204},[93,1237,209],{"class":208},[93,1239,213],{"class":212},[93,1241,1242],{"class":103},"views",[93,1244,213],{"class":212},[93,1246,347],{"class":223},[93,1248,1249],{"class":208}," path",[93,1251,253],{"class":223},[93,1253,1254],{"class":204},"join",[93,1256,1257],{"class":208},"(__dirname",[93,1259,347],{"class":223},[93,1261,296],{"class":212},[93,1263,1242],{"class":103},[93,1265,213],{"class":212},[93,1267,1268],{"class":208},"))",[93,1270,224],{"class":223},[93,1272,1273],{"class":95,"line":322},[93,1274,231],{"emptyLinePlaceholder":230},[93,1276,1277],{"class":95,"line":370},[93,1278,1279],{"class":237},"\u002F\u002F 3. 在路由中使用 res.render() 渲染\n",[93,1281,1282,1284,1286,1289,1291,1293,1296,1298,1300,1302,1305,1307,1310,1312,1314],{"class":95,"line":375},[93,1283,1111],{"class":208},[93,1285,253],{"class":223},[93,1287,1288],{"class":204},"get",[93,1290,209],{"class":208},[93,1292,213],{"class":212},[93,1294,1295],{"class":103},"\u002F",[93,1297,213],{"class":212},[93,1299,347],{"class":223},[93,1301,419],{"class":223},[93,1303,1304],{"class":422},"req",[93,1306,347],{"class":223},[93,1308,1309],{"class":422}," res",[93,1311,220],{"class":223},[93,1313,432],{"class":192},[93,1315,435],{"class":223},[93,1317,1318,1321,1323,1325,1327,1329,1332,1334,1336],{"class":95,"line":381},[93,1319,1320],{"class":208},"  res",[93,1322,253],{"class":223},[93,1324,336],{"class":204},[93,1326,209],{"class":289},[93,1328,213],{"class":212},[93,1330,1331],{"class":103},"index",[93,1333,213],{"class":212},[93,1335,347],{"class":223},[93,1337,435],{"class":223},[93,1339,1340,1343,1345,1347,1349,1351],{"class":95,"line":438},[93,1341,1342],{"class":289},"    title",[93,1344,293],{"class":223},[93,1346,296],{"class":212},[93,1348,411],{"class":103},[93,1350,213],{"class":212},[93,1352,1353],{"class":223},",\n",[93,1355,1356,1359,1361,1363,1365,1367,1369,1371,1373,1375,1378,1380,1384],{"class":95,"line":460},[93,1357,1358],{"class":289},"    user",[93,1360,293],{"class":223},[93,1362,350],{"class":223},[93,1364,290],{"class":289},[93,1366,293],{"class":223},[93,1368,296],{"class":212},[93,1370,299],{"class":103},[93,1372,213],{"class":212},[93,1374,347],{"class":223},[93,1376,1377],{"class":289}," isAdmin",[93,1379,293],{"class":223},[93,1381,1383],{"class":1382},"syTEX"," true",[93,1385,1386],{"class":223}," },\n",[93,1388,1389,1392,1394],{"class":95,"line":480},[93,1390,1391],{"class":223},"  }",[93,1393,220],{"class":289},[93,1395,224],{"class":223},[93,1397,1399,1401,1403],{"class":95,"line":1398},15,[93,1400,483],{"class":223},[93,1402,220],{"class":208},[93,1404,224],{"class":223},[37,1406,1408],{"id":1407},"九常用配置选项","九、常用配置选项",[22,1410,1411,1412,1415],{},"通过 ",[71,1413,1414],{},"options"," 参数配置 EJS 行为：",[132,1417,1418,1430],{},[135,1419,1420],{},[138,1421,1422,1425,1428],{},[141,1423,1424],{},"选项",[141,1426,1427],{},"类型",[141,1429,146],{},[148,1431,1432,1445,1468,1481,1493,1509,1523,1535,1547,1560,1572],{},[138,1433,1434,1439,1442],{},[153,1435,1436],{},[71,1437,1438],{},"cache",[153,1440,1441],{},"Boolean",[153,1443,1444],{},"是否缓存编译后的函数",[138,1446,1447,1452,1455],{},[153,1448,1449],{},[71,1450,1451],{},"filename",[153,1453,1454],{},"String",[153,1456,1457,1460,1461,1463,1464,1467],{},[48,1458,1459],{},"必须","在 ",[71,1462,1438],{}," 为 ",[71,1465,1466],{},"true"," 时指定，用于 Include 与缓存",[138,1469,1470,1475,1478],{},[153,1471,1472],{},[71,1473,1474],{},"root",[153,1476,1477],{},"String\u002FArray",[153,1479,1480],{},"Include 文件的根路径",[138,1482,1483,1487,1490],{},[153,1484,1485],{},[71,1486,1242],{},[153,1488,1489],{},"Array",[153,1491,1492],{},"解析相对路径 Include 时使用的路径列表",[138,1494,1495,1500,1502],{},[153,1496,1497],{},[71,1498,1499],{},"compileDebug",[153,1501,1441],{},[153,1503,1504,1505,1508],{},"为 ",[71,1506,1507],{},"false"," 时不编译调试信息（提升性能）",[138,1510,1511,1516,1518],{},[153,1512,1513],{},[71,1514,1515],{},"client",[153,1517,1441],{},[153,1519,1504,1520,1522],{},[71,1521,1466],{}," 时返回可在浏览器端独立运行的编译函数",[138,1524,1525,1530,1532],{},[153,1526,1527],{},[71,1528,1529],{},"debug",[153,1531,1441],{},[153,1533,1534],{},"输出生成的函数体",[138,1536,1537,1542,1544],{},[153,1538,1539],{},[71,1540,1541],{},"strict",[153,1543,1441],{},[153,1545,1546],{},"生成的渲染函数以严格模式运行",[138,1548,1549,1554,1557],{},[153,1550,1551],{},[71,1552,1553],{},"escape",[153,1555,1556],{},"Function",[153,1558,1559],{},"自定义 HTML 转义函数",[138,1561,1562,1567,1569],{},[153,1563,1564],{},[71,1565,1566],{},"async",[153,1568,1441],{},[153,1570,1571],{},"启用异步渲染",[138,1573,1574,1586,1588],{},[153,1575,1576,1579,1580,1579,1583],{},[71,1577,1578],{},"delimiter"," \u002F ",[71,1581,1582],{},"openDelimiter",[71,1584,1585],{},"closeDelimiter",[153,1587,1454],{},[153,1589,1590],{},"自定义标签定界符",[37,1592,1594],{"id":1593},"十缓存机制","十、缓存机制",[22,1596,1597,1598,1601,1602,1605],{},"EJS 内置基础缓存（",[71,1599,1600],{},"ejs.cache","），用于存储编译后的模板函数。搭配 ",[48,1603,1604],{},"LRU 缓存","可有效控制内存上限，避免缓存无限膨胀。",[42,1607,1608,1631],{},[45,1609,1610,69,1613],{},[48,1611,1612],{},"清除缓存",[84,1614,1616],{"className":183,"code":1615,"language":185,"meta":89,"style":89},"ejs.clearCache();\n",[71,1617,1618],{"__ignoreMap":89},[93,1619,1620,1622,1624,1627,1629],{"class":95,"line":96},[93,1621,12],{"class":208},[93,1623,253],{"class":223},[93,1625,1626],{"class":204},"clearCache",[93,1628,1181],{"class":208},[93,1630,224],{"class":223},[45,1632,1633,69,1636],{},[48,1634,1635],{},"使用 LRU 缓存",[84,1637,1639],{"className":183,"code":1638,"language":185,"meta":89,"style":89},"const ejs = require(\"ejs\");\nconst LRU = require(\"lru-cache\");\nejs.cache = new LRU(100); \u002F\u002F 最多缓存 100 个模板\n",[71,1640,1641,1663,1687],{"__ignoreMap":89},[93,1642,1643,1645,1647,1649,1651,1653,1655,1657,1659,1661],{"class":95,"line":96},[93,1644,193],{"class":192},[93,1646,197],{"class":196},[93,1648,201],{"class":200},[93,1650,205],{"class":204},[93,1652,209],{"class":208},[93,1654,213],{"class":212},[93,1656,12],{"class":103},[93,1658,213],{"class":212},[93,1660,220],{"class":208},[93,1662,224],{"class":223},[93,1664,1665,1667,1670,1672,1674,1676,1678,1681,1683,1685],{"class":95,"line":227},[93,1666,193],{"class":192},[93,1668,1669],{"class":196}," LRU",[93,1671,201],{"class":200},[93,1673,205],{"class":204},[93,1675,209],{"class":208},[93,1677,213],{"class":212},[93,1679,1680],{"class":103},"lru-cache",[93,1682,213],{"class":212},[93,1684,220],{"class":208},[93,1686,224],{"class":223},[93,1688,1689,1691,1693,1696,1699,1702,1704,1706,1710,1712,1714],{"class":95,"line":234},[93,1690,12],{"class":208},[93,1692,253],{"class":223},[93,1694,1695],{"class":208},"cache ",[93,1697,1698],{"class":200},"=",[93,1700,1701],{"class":200}," new",[93,1703,1669],{"class":204},[93,1705,209],{"class":208},[93,1707,1709],{"class":1708},"srdBf","100",[93,1711,220],{"class":208},[93,1713,1122],{"class":223},[93,1715,1716],{"class":237}," \u002F\u002F 最多缓存 100 个模板\n",[37,1718,1720],{"id":1719},"十一调试与常见问题","十一、调试与常见问题",[42,1722,1723,1761,1773,1790],{},[45,1724,1725,69,1728],{},[48,1726,1727],{},"开启调试模式",[84,1729,1731],{"className":183,"code":1730,"language":185,"meta":89,"style":89},"ejs.render(str, { debug: true });\n",[71,1732,1733],{"__ignoreMap":89},[93,1734,1735,1737,1739,1741,1744,1746,1748,1751,1753,1755,1757,1759],{"class":95,"line":96},[93,1736,12],{"class":208},[93,1738,253],{"class":223},[93,1740,336],{"class":204},[93,1742,1743],{"class":208},"(str",[93,1745,347],{"class":223},[93,1747,350],{"class":223},[93,1749,1750],{"class":289}," debug",[93,1752,293],{"class":223},[93,1754,1383],{"class":1382},[93,1756,304],{"class":223},[93,1758,220],{"class":208},[93,1760,224],{"class":223},[45,1762,1763,1766,1767,1769,1770,1772],{},[48,1764,1765],{},"变量未渲染","：检查是否误将输出内容放在 ",[71,1768,557],{}," 而非 ",[71,1771,517],{}," 中。",[45,1774,1775,1778,1779,1782,1783,1579,1786,1789],{},[48,1776,1777],{},"Include 路径错误","：确保 ",[71,1780,1781],{},"include"," 路径相对于主模板，或通过 ",[71,1784,1785],{},"options.views",[71,1787,1788],{},"options.root"," 指定绝对路径。",[45,1791,1792,1795,1796,1799],{},[48,1793,1794],{},"安全性注意事项","：不要直接渲染用户提交的模板，也不要将 ",[71,1797,1798],{},"req.query"," 当成数据渲染，否则可能引发 XSS 或远程代码执行漏洞。",[37,1801,1803],{"id":1802},"十二ejs-适用场景","十二、EJS 适用场景",[42,1805,1806,1809,1812],{},[45,1807,1808],{},"需要在服务端生成带动态内容的 HTML（利于 SEO）",[45,1810,1811],{},"快速原型开发，希望用最简单的方式实现模板化展示",[45,1813,1814],{},"与 Express 配合，实现传统的“后端 MVC”模式",[1816,1817,1818],"blockquote",{},[22,1819,1820,1823,1824,1579,1826,1828,1829,621,1832,1835],{},[48,1821,1822],{},"补充说明","：需要完整 ",[71,1825,931],{},[71,1827,935],{}," 继承时，可考虑 ",[48,1830,1831],{},"Pug",[48,1833,1834],{},"Nunjucks","。",[37,1837,1838],{"id":1838},"参考文献",[22,1840,1841],{},"以下链接在编写时均可正常访问：",[132,1843,1844,1853],{},[135,1845,1846],{},[138,1847,1848,1851],{},[141,1849,1850],{},"资料",[141,1852,146],{},[148,1854,1855,1867,1878],{},[138,1856,1857,1864],{},[153,1858,1859],{},[25,1860,1863],{"href":1861,"rel":1862},"https:\u002F\u002Fejs.co\u002F#docs",[29],"EJS 文档",[153,1865,1866],{},"官方",[138,1868,1869,1875],{},[153,1870,1871],{},[25,1872,1063],{"href":1873,"rel":1874},"https:\u002F\u002Fwww.npmjs.com\u002Fpackage\u002Fexpress-ejs-layouts",[29],[153,1876,1877],{},"Layout 中间件",[138,1879,1880,1887],{},[153,1881,1882],{},[25,1883,1886],{"href":1884,"rel":1885},"https:\u002F\u002Fexpressjs.com\u002Fen\u002Fguide\u002Fusing-template-engines.html",[29],"Express 模板引擎",[153,1888,1889],{},"集成方式",[1891,1892,1893],"style",{},"html pre.shiki code .sbgvK, html code.shiki .sbgvK{--shiki-light:#E2931D;--shiki-default:#6F42C1;--shiki-dark:#B392F0}html pre.shiki code .s_sjI, html code.shiki .s_sjI{--shiki-light:#91B859;--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 .sbsja, html code.shiki .sbsja{--shiki-light:#9C3EDA;--shiki-default:#D73A49;--shiki-dark:#F97583}html pre.shiki code .s_hVV, html code.shiki .s_hVV{--shiki-light:#90A4AE;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .smGrS, html code.shiki .smGrS{--shiki-light:#39ADB5;--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 .su5hD, html code.shiki .su5hD{--shiki-light:#90A4AE;--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 .sP7_E, html code.shiki .sP7_E{--shiki-light:#39ADB5;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .skxfh, html code.shiki .skxfh{--shiki-light:#E53935;--shiki-default:#24292E;--shiki-dark:#E1E4E8}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 .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 .sQzsp, html code.shiki .sQzsp{--shiki-light:#E53935;--shiki-default:#22863A;--shiki-dark:#85E89D}html pre.shiki code .syTEX, html code.shiki .syTEX{--shiki-light:#FF5370;--shiki-default:#005CC5;--shiki-dark:#79B8FF}html pre.shiki code .srdBf, html code.shiki .srdBf{--shiki-light:#F76D47;--shiki-default:#005CC5;--shiki-dark:#79B8FF}",{"title":89,"searchDepth":227,"depth":227,"links":1895},[1896,1897,1901,1902,1903,1904,1905,1906,1907,1908,1909,1910,1911],{"id":39,"depth":227,"text":40},{"id":76,"depth":227,"text":77,"children":1898},[1899,1900],{"id":81,"depth":234,"text":82},{"id":129,"depth":234,"text":130},{"id":490,"depth":227,"text":491},{"id":633,"depth":227,"text":634},{"id":719,"depth":227,"text":720},{"id":782,"depth":227,"text":783},{"id":920,"depth":227,"text":921},{"id":1138,"depth":227,"text":1139},{"id":1407,"depth":227,"text":1408},{"id":1593,"depth":227,"text":1594},{"id":1719,"depth":227,"text":1720},{"id":1802,"depth":227,"text":1803},{"id":1838,"depth":227,"text":1838},{"title":8,"description":9},"knowledge\u002Fbooklet\u002Fend\u002FEjs","knowledge\u002Fknowledge\u002Fbooklet\u002Fend\u002FEjs.md","md",{"items":1917},[1918,1922,1926,1930,1934,1938],{"path":1919,"title":1920,"description":1921,"category":10,"score":234},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fbasics","后端入门概览","本目录覆盖 JavaScript\u002FTypeScript 服务端运行时与框架、数据存储，以及 Rust 系统编程入门，提供从零到部署的完整学习路径。前置建议：JavaScript 基础、工程化 · 环境变量。",{"path":1923,"title":1924,"description":1925,"category":10,"score":234},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fbun\u002Fbase","Bun 基础与核心命令","Bun 是用 Zig 编写的 JavaScript 运行时，内置包管理（bun install）、打包（bun build）、测试（bun test）等，并持续兼容 Node.js API。本文介绍核心特点、安装方式，以及日常最常用的命令与包管理功能。见 运行时对比。",{"path":1927,"title":1928,"description":1929,"category":10,"score":234},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fbun\u002Fhttp","HTTP 服务器","Bun 内置了高性能的 HTTP 服务器，通过 Bun.serve 可以轻松启动服务。从 Bun v1.2.3 开始，推荐使用 routes 对象来定义路由，更加直观和灵活。",{"path":1931,"title":1932,"description":1933,"category":10,"score":234},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Ffs","文件系统","Node.js 的 fs 模块提供了与文件系统交互的 API，几乎涵盖了所有标准文件操作。它支持三种风格的 API：同步、回调式异步 和 Promise 式异步。下面详细介绍这些 API 的选择策略、流式读写、文件监视以及常用操作。",{"path":1935,"title":1936,"description":1937,"category":10,"score":234},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Fbase","Deno 基础","Deno 是基于 V8 与 Rust 的 JavaScript\u002FTypeScript 运行时，由 Node.js 原作者 Ryan Dahl 发起。官方文档：docs.deno.com。与 Node、Bun 的对比见 运行时对比。",{"path":1939,"title":1940,"description":89,"category":10,"score":234},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fexce","异常处理器",{"series":1942,"title":1943,"items":1944,"index":2199,"prev":2200,"next":2201},"booklet\u002Fend","end",[1945,1949,1953,1957,1961,1965,1969,1971,1973,1974,1978,1982,1986,1990,1994,1998,2002,2006,2010,2014,2018,2022,2026,2030,2034,2035,2039,2043,2047,2051,2055,2059,2061,2063,2065,2069,2072,2076,2078,2082,2086,2090,2094,2098,2102,2106,2110,2114,2118,2122,2126,2130,2134,2138,2142,2145,2149,2153,2157,2161,2164,2168,2172,2176,2180,2184,2188,2191,2195],{"path":1946,"title":1947,"date":1948,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fasync","第九章：并发与异步","2020-05-22",{"path":1950,"title":1951,"date":1952,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fasync","异步编程与模式","2025-08-20",{"path":1954,"title":1955,"date":1956,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Fauth","权限模型","2021-04-01",{"path":1958,"title":1959,"date":1960,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fauth","认证与授权","2025-12-23",{"path":1962,"title":1963,"date":1964,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fbase","Rust 基础","2020-07-21",{"path":1966,"title":1967,"date":1968,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fbase","NestJS 基础","2021-03-09",{"path":1935,"title":1936,"date":1970,"pinned":14},"2026-06-01",{"path":1923,"title":1924,"date":1972,"pinned":14},"2026-07-23",{"path":1919,"title":1920,"date":1972,"pinned":14},{"path":1975,"title":1976,"date":1977,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fbuffer","缓冲区","2025-01-30",{"path":1979,"title":1980,"date":1981,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fbun-deno-node","Bun \u002F Deno \u002F Node 对比","2024-04-23",{"path":1983,"title":1984,"date":1985,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcache","缓存","2025-07-04",{"path":1987,"title":1988,"date":1989,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fconfig","配置管理（Config 模块）","2023-08-26",{"path":1991,"title":1992,"date":1993,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcontroller","控制器与路由","2020-07-18",{"path":1995,"title":1996,"date":1997,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fcore","第三章：所有权、借用与生命周期（核心）","2023-05-09",{"path":1999,"title":2000,"date":2001,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcron","定时任务","2023-04-12",{"path":2003,"title":2004,"date":2005,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fcustom-decorators","自定义装饰器","2021-09-19",{"path":2007,"title":2008,"date":2009,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdata-type","第四章：复合数据类型","2021-02-24",{"path":2011,"title":2012,"date":2013,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdatabase","数据库集成（以 TypeORM 为例）","2023-05-26",{"path":2015,"title":2016,"date":2017,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fdatabase","数据库的配置","2024-06-22",{"path":2019,"title":2020,"date":2021,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fdemo","入手Demo","2022-10-15",{"path":2023,"title":2024,"date":2025,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fdeploy","部署与运维","2023-01-24",{"path":2027,"title":2028,"date":2029,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fbun\u002Fdeploy","生产环境与部署指南","2024-08-31",{"path":2031,"title":2032,"date":2033,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fdocs","第八章：测试、文档与质量","2026-01-11",{"path":7,"title":8,"date":13,"pinned":14},{"path":2036,"title":2037,"date":2038,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fenv","环境加载","2024-09-01",{"path":2040,"title":2041,"date":2042,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Ferror","异常处理","2020-01-28",{"path":2044,"title":2045,"date":2046,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Ferror","错误处理与健壮性","2021-01-24",{"path":2048,"title":2049,"date":2050,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ferror","第五章：错误处理","2023-11-03",{"path":2052,"title":2053,"date":2054,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent","事件驱动与非阻塞 I\u002FO 模型","2020-06-20",{"path":2056,"title":2057,"date":2058,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fevent-loop","事件循环","2024-11-20",{"path":1939,"title":1940,"date":2060,"pinned":14},"2026-03-17",{"path":33,"title":34,"date":2062,"pinned":14},"2022-01-24",{"path":1931,"title":1932,"date":2064,"pinned":14},"2026-06-04",{"path":2066,"title":2067,"date":2068,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fguards","守卫 (Guards) 与授权","2023-09-09",{"path":2070,"title":1928,"date":2071,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Fhttp","2020-12-11",{"path":2073,"title":2074,"date":2075,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fhttp","网络编程","2023-01-27",{"path":1927,"title":1928,"date":2077,"pinned":14},"2026-07-12",{"path":2079,"title":2080,"date":2081,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Finfo","归档说明（before\u002F）","2023-08-31",{"path":2083,"title":2084,"date":2085,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Finit","项目初始化与基础命令","2025-02-14",{"path":2087,"title":2088,"date":2089,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Finjectable","操作日志拦截器","2020-02-20",{"path":2091,"title":2092,"date":2093,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Finstall","安装与环境","2021-02-05",{"path":2095,"title":2096,"date":2097,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fintercept","拦截器 (Interceptors)","2021-04-26",{"path":2099,"title":2100,"date":2101,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fitc","统一响应格式拦截器","2023-08-17",{"path":2103,"title":2104,"date":2105,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fjwt","JWT 与 Passport 授权","2021-08-10",{"path":2107,"title":2108,"date":2109,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Flogger","日志记录","2022-10-10",{"path":2111,"title":2112,"date":2113,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fmi","Nest 中间件","2022-06-21",{"path":2115,"title":2116,"date":2117,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmiddleware","中间件 (Middleware)","2021-11-26",{"path":2119,"title":2120,"date":2121,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fmodule","模块系统","2020-07-01",{"path":2123,"title":2124,"date":2125,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fmodule","模块系统与依赖注入","2022-06-15",{"path":2127,"title":2128,"date":2129,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs","NestJS 导读","2025-06-21",{"path":2131,"title":2132,"date":2133,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fnext","路由守卫","2022-12-01",{"path":2135,"title":2136,"date":2137,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fother","其他常用模块","2020-03-27",{"path":2139,"title":2140,"date":2141,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Fother","其他配置","2022-02-08",{"path":2143,"title":2140,"date":2144,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fbefore\u002Fother","2022-05-23",{"path":2146,"title":2147,"date":2148,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fother","第十章：进阶特性与模式","2023-12-29",{"path":2150,"title":2151,"date":2152,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Fpackage","第七章：模块系统与包管理","2024-05-26",{"path":2154,"title":2155,"date":2156,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Fpackage","包管理与依赖","2024-07-21",{"path":2158,"title":2159,"date":2160,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fpath","路径处理","2024-03-14",{"path":2162,"title":2163,"date":1993,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fpipes","管道 (Pipes) 与数据验证",{"path":2165,"title":2166,"date":2167,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fprocess","进程与子进程","2023-11-10",{"path":2169,"title":2170,"date":2171,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fqueue","队列（Bull）","2021-07-01",{"path":2173,"title":2174,"date":2175,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fservice","提供者与服务","2024-12-02",{"path":2177,"title":2178,"date":2179,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fcore\u002Fstream","流","2022-05-03",{"path":2181,"title":2182,"date":2183,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ft","泛型与 Trait","2024-10-31",{"path":2185,"title":2186,"date":2187,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fdeno\u002Ftools","内置工具链","2026-01-24",{"path":2189,"title":2190,"date":2029,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Frust\u002Ftype","第二章：基础语法与类型",{"path":2192,"title":2193,"date":2194,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnodejs\u002Fbase\u002Fvar","全局对象与变量","2025-01-03",{"path":2196,"title":2197,"date":2198,"pinned":14},"\u002Fknowledge\u002Fbooklet\u002Fend\u002Fnestjs\u002Fnew\u002Fwebsocket","WebSocket（网关）","2022-12-14",24,{"path":2031,"title":2032,"date":2033,"pinned":14},{"path":2036,"title":2037,"date":2038,"pinned":14}]