当前位置: 首页 > 后端技术 > Node.js

40行代码手撸一个静态文档生成器[译]

时间:2023-04-03 14:20:50 Node.js

AStaticDocumentationGeneratorin40LinesofCode前言原文:用Node.js构建一个静态站点生成器40行作者:DouglasMatoso译者:SimonMa日期:2017-09-14为什么要造这个轮子当我打算建立一个个人网站,我的需求很简单,做一个网站,就几个页面,放一些自己的资料,自己的技能和项目就够了。毫无疑问,它应该是纯静态的(不需要后端服务,可以在任何地方托管)。我用过Jekyll、Hugo和Hexo,这些都是著名的静态文档生成器,但我认为它们的功能太多了,我不想为我的网站增加太多复杂性。所以我觉得,对于我的需求,一个简单的静态文档生成器就可以满足。好吧,手动构建一个简单的生成器应该不会那么难。文本需求分析该生成器必须满足以下条件:从EJS模板生成HTML文件。有了布局文件,所有页面都应该有相同的页眉、页脚、导航等。允许可重用??的布局组件。有关站点的一般信息被封装到一个配置文件中。从JSON文件中读取数据。例如:一个项目列表,这样我就可以轻松地迭代和构建项目页面。为什么要使用EJS模板?因为EJS很简单,它只是嵌入HTML中的JavaScript。项目结构public/src/assets/data/pages/partials/layout.ejssite.config.jspublic:站点生成的地方。src:源文件。src/assets:包含CSS、JS、图片等。src/data:包含JSON数据。src/pages:里面根据EJS生成HTML页面的模板文件夹。src/layout.ejs:主要的原始页面模板,包含特殊的<%-body%>占位符,会插入特定的页面内容。site.config.js:模板中的全局配置文件。生成器生成器代码位于scripts/build.js文件中。每次要重建站点时,只需执行npmrunbuild命令即可。这是通过将以下脚本添加到package.json的脚本块来实现的:"build":"node./scripts/build"这是完整的生成器代码:constfse=require('fs-extra')constpath=require('path')const{promisify}=require('util')constejsRenderFile=promisify(require('ejs').renderFile)constglobP=promisify(require('glob'))constconfig=require('../site.config')constsrcPath='./src'constdistPath='./public'//清除目标文件夹fse.emptyDirSync(distPath)//复制资产文件夹fse.copy(`${srcPath}/assets`,`${distPath}/assets`)//读取页面模板globP('**/*.ejs',{cwd:`${srcPath}/pages`}).then((files)=>{files.forEach((file)=>{constfileData=path.parse(file)constdestPath=path.join(distPath,fileData.dir)//创建目标目录fse.mkdirs(destPath).then(()=>{//渲染页面返回ejsRenderFile(`${srcPath}/pages/${file}`,Object.assign({},config))}).then((pageContents)=>{//使用页面内容渲染布局returnejsRenderFile(`${srcPath}/layout.ejs`,Object.assign({},config,{body:pageContents}))}).then((layoutContent)=>{//保存html文件fse.writeFile(`${destPath}/${fileData.name}.html`,layoutContent)}).catch((err)=>{console.error(err)})})}).catch((err)=>{console.error(err)})接下来我会解释代码中的具体组件Dependencies我们只需要三个依赖:ejs将我们的模板编译成HTML。fs-extraNode文件模块的衍生版本,具有更多功能和增强的Promise支持。glob递归读取目录并返回所有匹配指定模式的文件,类型为数组。Promisify我们使用Node提供的util.promisify将所有回调函数转换为基于Promise的函数。它使我们的代码更短、更清晰且更易于阅读。const{promisify}=require('util')constejsRenderFile=promisify(require('ejs').renderFile)constglobP=promisify(require('glob'))加载配置然后将其注入模板渲染器。constconfig=require('../site.config')站点配置文件本身会加载其他JSON数据,例如:constprojects=require('./src/data/projects')module.exports={site:{title:'NanoGen',description:'MicroStaticSiteGeneratorinNode.js',projects}}清空站点文件夹我们使用fs-extra提供的emptyDirSync函数来清除生成的站点文件夹。fse.emptyDirSync(distPath)复制静态资源我们使用fs-extra提供的复制功能,递归地将静态资源复制到site文件夹。fse.copy(`${srcPath}/assets`,`${distPath}/assets`)编译页面模板首先,我们使用glob(promisified)递归读取src/pages文件夹以查找.ejs文件。它将返回与给定模式匹配的所有文件的数组。globP('**/*.ejs',{cwd:`${srcPath}/pages`}).then((files)=>{对于找到的每个模板文件,我们使用Node的path.parse函数来分离各种文件路径的组成部分(如目录、名称和扩展名)。然后我们使用fs-extra提供的mkdirs函数在站点目录中创建相应的文件夹。files.forEach((file)=>{constfileData=path.parse(file)constdestPath=path.join(distPath,fileData.dir)//创建目标目录fse.mkdirs(destPath)然后,我们使用EJS编译文件并将配置数据作为数据参数传递。由于我们是使用promified的ejs.renderFile函数,所以我们可以返回调用结果并在下一个promise链中处理结果。.then(()=>{//渲染页面returnejsRenderFile(`${srcPath}/pages/${file}`,Object.assign({},config))})在下一个then块中我们得到编译页面内容。现在,我们编译布局文件,将页面内容作为body属性传入。.then((pageContents)=>{//使用页面内容渲染布局returnejsRenderFile(`${srcPath}/layout.ejs`,Object.assign({},config,{body:pageContents}))})最后,我们得到生成的编译结果(布局+页面内容HTML),然后保存到对应的HTML文件中。.then((layoutContent)=>{//保存html文件fse.writeFile(`${destPath}/${fileData.name}.html`,layoutContent)})调试服务器添加一个简单的静态服务器到脚本package.json的。"serve":"serve./public"运行npmrunserve命令,打开http://localhost:5000,查看结果。进一步探索Markdown大多数静态文档生成器都支持以Markdown格式编写内容。并且,他们还支持在YAML格式的顶部添加一些元数据,就像这样:---title:HelloWorlddate:2013/7/1320:46:25---只需稍加修改,我们就可以支持Same现在运作。首先,我们必须添加两个依赖项:marked将markdown编译为HTML,front-matter从markdown中提取frontmatter。然后我们更新了glob的匹配模式以包含.md文件并保留.ejs以支持渲染复杂页面。如果要部署一些纯HTML页面,还需要包含.html。globP('**/*.@(md|ejs|html)',{cwd:`${srcPath}/pages`})对于每个文件,我们必须加载文件内容,以便我们可以在顶级数据。.then(()=>{//读取页面文件returnfse.readFile(`${srcPath}/pages/${file}`,'utf-8')})我们将加载的内容传递给前端。它将返回一个对象,其中属性属性是提取的元数据。然后我们使用这些数据来扩充站点配置。.then((data)=>{//提取frontmatterconstpageData=frontMatter(data)consttemplateConfig=Object.assign({},config,{page:pageData.attributes})现在我们根据fileextension编译成HTML,如果是.md,就用标记的函数编译;如果是.ejs,我们继续用EJS编译;如果是.html,就不用编译了。让pageContent切换(fileData.ext){case'.md':pageContent=marked(pageData.body)breakcase'.ejs':pageContent=ejs.render(pageData.body,templateConfig)breakdefault:pageContent=pageData.body}最后,我们像以前一样渲染布局。添加元数据最明显的意义就是我们可以为每个页面设置一个单独的标题,如下:---title:AnotherPage---让布局动态渲染这些数据:<%=page.title?`${page.title}|`:''%><%=site.title%>这样,每个页面都会有一个唯一的标签。支持多种布局另一个有趣的探索是在特定页面上使用不同的布局。比如给网站首页设置一个独特的布局:---layout:minimal---我们需要有一个单独的布局文件,我把它们放在src/layouts文件夹下:src/layouts/default.ejsmininal.ejs如果frontmatter有layout属性,我们会使用layouts文件夹下的同名模板文件进行渲染;如果未设置,将使用默认模板进行渲染。常量布局=pageData.attributes.layout||'default'returnejsRenderFile(`${srcPath}/layouts/${layout}.ejs`,Object.assign({},templateConfig,{body:pageContent}))即使添加了这些新功能,构建脚本也是只有60行长。下一步如果你想更进一步,你可以添加一些不那么困难的添加:一个可热重载的调试服务器,你可以使用live-server(内置自动重载)或chokidar(监视文件修改自动触发构建脚本)模块完成。自动部署添加脚本以将您的站点部署到GitHubPages等常见托管服务,或者通过SSH(使用scp或rsync等命令)简单地将文件上传到您自己的服务器。支持CSS/JS预处理器在将静态文件复制到站点文件之前添加一些预处理器(SASS编译为CSS,ES6编译为ES5等)。更好的日志记录添加一些console.log日志输出以更好地分析正在发生的事情。你可以使用粉笔包来完善这个东西。反馈?有什么建议么?请随时发表评论或与我联系!结论本文的完整示例可在此处找到:https://github.com/doug2k1/na...。一段时间后,我决定将该项目转换为CLI模块以使其更易于使用,它位于上面链接的master分支中。译者:今天想写一篇ants(一个高性能的goroutinepool)源码分析的文章,但是环境太吵了,静不下来,就停了。这是前几天无意中看到的一篇文章。虽然是2017年写的文章,但看完还是让我有些感悟。希望这篇文章对你有所帮助。转载本站文章请注明作者和出处。一个破烂的番茄,请勿用于任何商业用途。</p> </div> </div> <div class="zuowen_sxy"> <div class="prev">上一篇:<a title="如何搭建自己的web服务器" href="/houduanjishu/238276.html">如何搭建自己的web服务器</a> </div> <div class="prev">下一篇:<a title="excel数据分析存储的简单节点爬虫" href="/houduanjishu/238278.html">excel数据分析存储的简单节点爬虫</a> </div> </div> <div class="related_about"> <div class="related_about_t"><code>40行代码手撸一个静态文档生成器[译]相关文章</code></div> <ul> <li><a href="/jishuluodi/333880.html" target="_blank" title="抖音如何激活商店代码? ">抖音如何激活商店代码? </a></li> <li><a href="/jishuluodi/333706.html" target="_blank" title="亚马逊一次性折扣代码和无限制亚马逊折扣代码有什么区别? ">亚马逊一次性折扣代码和无限制亚马逊折扣代码有什么区别? </a></li> <li><a href="/jishuluodi/333616.html" target="_blank" title="代码 2020 是什么意思? ">代码 2020 是什么意思? </a></li> <li><a href="/jishuluodi/329571.html" target="_blank" title="如何申请行程代码? ">如何申请行程代码? </a></li> <li><a href="/jishuluodi/328588.html" target="_blank" title="交警罚款代码1344是什么意思? ">交警罚款代码1344是什么意思? </a></li> <li><a href="/jishuluodi/326629.html" target="_blank" title="如何查看京东电子卡代码? ">如何查看京东电子卡代码? </a></li> <li><a href="/jishuluodi/325918.html" target="_blank" title="代码 13441 是什么违规行为? ">代码 13441 是什么违规行为? </a></li> <li><a href="/jishuluodi/320980.html" target="_blank" title="交通违章代码1212是什么意思? ">交通违章代码1212是什么意思? </a></li> <li><a href="/jishuluodi/320467.html" target="_blank" title="代码字13是什么意思? ">代码字13是什么意思? </a></li> <li><a href="/jishuluodi/320354.html" target="_blank" title="代码 1057 是什么意思? ">代码 1057 是什么意思? </a></li> <li><a href="/jishuluodi/320199.html" target="_blank" title="数字爱情代码552代表什么? ">数字爱情代码552代表什么? </a></li> <li><a href="/jishuluodi/319309.html" target="_blank" title="考研代码是什么意思? ">考研代码是什么意思? </a></li> <li><a href="/jishutupo/318578.html" target="_blank" title="在浏览器中调试JavaScript代码的最佳方法是什么">在浏览器中调试JavaScript代码的最佳方法是什么</a></li> <li><a href="/jishutupo/318533.html" target="_blank" title="调试JavaScript代码的最佳方法是什么">调试JavaScript代码的最佳方法是什么</a></li> <li><a href="/jishutupo/318521.html" target="_blank" title="调试和分析GO代码">调试和分析GO代码</a></li> <li><a href="/jishutupo/318448.html" target="_blank" title="如何调试红宝石代码">如何调试红宝石代码</a></li> <li><a href="/jishutupo/318446.html" target="_blank" title="在控制台?中调试JavaScript代码的最佳方法是什么">在控制台?中调试JavaScript代码的最佳方法是什么</a></li> <li><a href="/jishutupo/318428.html" target="_blank" title="PHP和PHPUNIT:编写可测试代码的高级技术">PHP和PHPUNIT:编写可测试代码的高级技术</a></li> <li><a href="/jishutupo/318423.html" target="_blank" title="编写角度代码的最佳实践是什么">编写角度代码的最佳实践是什么</a></li> <li><a href="/jishutupo/318390.html" target="_blank" title="调试JavaScript代码的最佳技术是什么">调试JavaScript代码的最佳技术是什么</a></li> </ul> </div> </div> <div class="main-right"> <div class="right_fix"> <div class="r_con"> <div class="r_title">最新推荐</div> <ul> <li><em>1</em><a href="/kejifunen/370469.html" title="CODING获腾讯云1亿元B+轮融资,推出Cloud Stu" target="_blank">CODING获腾讯云1亿元B+轮融资,推出Cloud Stu</a></li> <li><em>2</em><a href="/kejifunen/365912.html" title="程序员注意了! AI技术准确率高达83%,可以准确识别代码的" target="_blank">程序员注意了! AI技术准确率高达83%,可以准确识别代码的</a></li> <li><em>3</em><a href="/kejifunen/361575.html" title="华为nova3的强大技术解析,看似简单的摄影背后隐藏着无数的" target="_blank">华为nova3的强大技术解析,看似简单的摄影背后隐藏着无数的</a></li> <li><em>4</em><a href="/kejifunen/350305.html" title="算法正在创造一个无人能读懂的代码世界" target="_blank">算法正在创造一个无人能读懂的代码世界</a></li> <li><em>5</em><a href="/kejifunen/344058.html" title="今年是 Gitee 上线七周年,我们继续努力,体验更好的代码" target="_blank">今年是 Gitee 上线七周年,我们继续努力,体验更好的代码</a></li> <li><em>6</em><a href="/kejifunen/344002.html" title="钉钉发布低代码开发者画像, 20岁以下和50岁以上的开发者占" target="_blank">钉钉发布低代码开发者画像, 20岁以下和50岁以上的开发者占</a></li> <li><em>7</em><a href="/kejifunen/343911.html" title="钉钉低代码开发上千应用,朝阳橡胶数字化转型效率提升70%" target="_blank">钉钉低代码开发上千应用,朝阳橡胶数字化转型效率提升70%</a></li> <li><em>8</em><a href="/kejifunen/342532.html" title="低代码软件快速开发平台环球领导者助力中国企业实现数字化转型" target="_blank">低代码软件快速开发平台环球领导者助力中国企业实现数字化转型</a></li> <li><em>9</em><a href="/kejifunen/341416.html" title="以AI和通信为赋能,容联奇摩主推MoPower零代码开发平台" target="_blank">以AI和通信为赋能,容联奇摩主推MoPower零代码开发平台</a></li> <li><em>10</em><a href="/kejifunen/340998.html" title="奥哲完成2亿元B+轮融资,引领国内低代码数字服务行业" target="_blank">奥哲完成2亿元B+轮融资,引领国内低代码数字服务行业</a></li> </ul> </div> <div class="r_con"> <div class="r_title">猜你喜欢</div> <ul class="you_like"> <li><em>1</em><a href="/kejifunen/339588.html" title="声网正式发布智慧课堂:首家教育低代码开发普惠教育机构" target="_blank">声网正式发布智慧课堂:首家教育低代码开发普惠教育机构</a></li> <li><em>2</em><a href="/kejifunen/338366.html" title="一串代码暗藏玄机?鸿蒙4可能亮相HDC? " target="_blank">一串代码暗藏玄机?鸿蒙4可能亮相HDC? </a></li> <li><em>3</em><a href="/kejifunen/338267.html" title="钉钉推出国内首个低代码应用广场“钉钉”" target="_blank">钉钉推出国内首个低代码应用广场“钉钉”</a></li> <li><em>4</em><a href="/kejifunen/338139.html" title="科大讯飞Spark V2.0发布:代码能力突破,提升大模型智" target="_blank">科大讯飞Spark V2.0发布:代码能力突破,提升大模型智</a></li> <li><em>5</em><a href="/kejifunen/337579.html" title="进入百度探索北京当前代智能网科技代码" target="_blank">进入百度探索北京当前代智能网科技代码</a></li> <li><em>6</em><a href="/kejifunen/337500.html" title="百度智能云代码助手“Comate”开放测试,覆盖30种编程语" target="_blank">百度智能云代码助手“Comate”开放测试,覆盖30种编程语</a></li> <li><em>7</em><a href="/kejifunen/337445.html" title="荣耀Magic3系列电影技术解析:改写手机视频拍摄底层逻辑的" target="_blank">荣耀Magic3系列电影技术解析:改写手机视频拍摄底层逻辑的</a></li> <li><em>8</em><a href="/kejifunen/336545.html" title="“伟大的作品”因其实力而脱颖而出,开发者力荐北大aiXcod" target="_blank">“伟大的作品”因其实力而脱颖而出,开发者力荐北大aiXcod</a></li> <li><em>9</em><a href="/kejifunen/336409.html" title="可以自动编写代码的大型AI模型来了,阿里云推出智能编码助手通" target="_blank">可以自动编写代码的大型AI模型来了,阿里云推出智能编码助手通</a></li> <li><em>10</em><a href="/kejifunen/336258.html" title="低代码掀起了企业应用开发的潮流,钉钉平台应用总数已突破百万" target="_blank">低代码掀起了企业应用开发的潮流,钉钉平台应用总数已突破百万</a></li> <li><em>11</em><a href="/kejifunen/336084.html" title="OceanBase杨冰:OceanBase在代码、社区、生态" target="_blank">OceanBase杨冰:OceanBase在代码、社区、生态</a></li> <li><em>12</em><a href="/kejifunen/336054.html" title="「去 IOE化」「低代码」:看360数科最新技术发展脉络" target="_blank">「去 IOE化」「低代码」:看360数科最新技术发展脉络</a></li> <li><em>13</em><a href="/kejifunen/335998.html" title="商业数字原生代进入2.0时代,奥哲“All in One”低" target="_blank">商业数字原生代进入2.0时代,奥哲“All in One”低</a></li> <li><em>14</em><a href="/kejifunen/335782.html" title="阿里云内部全面推广AI编程,未来20%的代码将由通义灵码编写" target="_blank">阿里云内部全面推广AI编程,未来20%的代码将由通义灵码编写</a></li> <li><em>15</em><a href="/kejifunen/335598.html" title="使用钉钉低代码构建的工业软件通过工信部电子五院软件测试" target="_blank">使用钉钉低代码构建的工业软件通过工信部电子五院软件测试</a></li> <li><em>16</em><a href="/kejifunen/335531.html" title="北森完成HR SaaS行业最大规模融资,整合×低代码构筑坚实" target="_blank">北森完成HR SaaS行业最大规模融资,整合×低代码构筑坚实</a></li> <li><em>17</em><a href="/kejifunen/335310.html" title="两行代码解决大语言模型对话的局限性!香港中文贾佳亚团队联合M" target="_blank">两行代码解决大语言模型对话的局限性!香港中文贾佳亚团队联合M</a></li> <li><em>18</em><a href="/kejifunen/334976.html" title="蚂蚁集团CodeFuse推出“Code from Drawi" target="_blank">蚂蚁集团CodeFuse推出“Code from Drawi</a></li> <li><em>19</em><a href="/kejifunen/334936.html" title="第八届“创客中国”钉钉低代码大赛启动,普及低代码实现普惠科技" target="_blank">第八届“创客中国”钉钉低代码大赛启动,普及低代码实现普惠科技</a></li> <li><em>20</em><a href="/jishuluodi/334866.html" title="团购房间代码是多少? " target="_blank">团购房间代码是多少? </a></li> </ul> </div> </div> </div> </div> <div class="related_article"></div> <div class="footer"> <p>Copyright © 2012-2022 程序源 版权所有<a href="https://beian.miit.gov.cn/" rel="nofollow" target="_blank">豫ICP备2022028201号</a></p> <p>重要申明:本站所有的文章、图片、评论等,均由网友发表或上传并维护或收集自网络,属个人行为,与本站立场无关。 如果侵犯了您的权利,请与我们联系,我们将在24小时内进行处理、任何非本站因素导致的法律后果,本站均不负任何责任。</p> </div> <!-- 应用插件标签 start --> <!-- 应用插件标签 end --> </body> </html>