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

快速搭建你的githubpages个人博客——基于Create-React-App的单页应用实践

时间:2023-04-03 19:27:04 Node.js

相信各位github资深玩家都有自己基于githubpages的个人站点。官方推荐的静态站点生成器是Jekyll。如果大家有兴趣使用Jekyll,请自行google,这里不再赘述。本文主要介绍基于Create-React-App搭建个人博客的相关实践,可能更适合前端开发小伙伴。githubpages是github推出的静态站点服务。它的主要用途是利用你在github仓库中的代码搭建自己的静态站点,为用户提供一个github.io二级域名。您也可以通过添加DNSCNAME记录来绑定设置您自己的域名。githubpages最简单粗暴的方式就是直接在github上面的静态页面,创建一个github仓库,名字叫[你的github账号].github.io,把你的index.html页面代码丢到master分支,就可以了完成您已经通过https://[您的github帐户名].github.io直接访问了您的站点。对于一个简单的个人博客站点,有以下基本功能:添加文章、编辑、文章一键分类、博客风格的评论和良好的归档风格、SEO等。下面介绍如何基于React实现一个简单的博客静态博客。1、创建React项目使用Create-React-App(以下简称CRA)的生成器创建一个React前端项目骨架。对本项目做一些改动,方便我们日常的开发和使用习惯:使用react-app-rewired调整CRA中webpack的配置通过编写不同的React容器组件(container)来实现不同的页面实现对server版本的向后兼容,并通过统一的json结构配置应用的页面路由使用蚂蚁金服的antd设计语言(React组件)快速实现业务UI的使用axios实现前后端数据请求。个人修改的项目代码在这里。你可以直接fork或down来使用它。2.使用markdown获取你的文章2.1创建新文章的交互式命令行(基于inquirer)一般静态博客系统(如gatsby)都会为用户提供创建新文章的交互式命令行,效果大致如下:使用nodejs中readline模块的native方法可以实现类似的功能。这里推荐一个第三方工具:inquirer,本质上是对readline模块的增强,提供了很多交互式命令行开发的实用方法,实现了友好的用户界面(命令行)。对于上述GIF例子的功能,其代码实现如下://newPost.jsconstinquirer=require('inquirer');constmoment=require('moment');constquestions=[{type:'input',name:'post_name',message:'请输入您的文章别名(用于创建文章目录,仅限英文,单词之间用破折号'-'连接):',validate:value=>{if(/(\.|\*|\?|\\|\/)/gi.test(value)){return'文章别名不能包含特殊符号(.*?\\/),请重新输入↑↑';}if(/(([A-z]+-)+)?[A-z]+/gi.test(value)){返回真;}return'文章别名无效,请重新输入↑↑';},过滤器:值=>值。replace(/\s+/gi,'-'),},{type:'input',name:'create_at',message:'请输入文章发表时间(或回车使用默认值):',默认:()=>{returnmoment().format('YYYY-MM-DDThh:mm:ss');},验证:值=>{if(/\d{4}-\d\d-\d\dT\d\d:\d\d:\d\d/gi.test(value)){返回真的;}return'时间格式无效,请重新输入↑↑';},},];inquirer.prompt(questions).then(answers=>{//获取用户输入const{post_name,create_at}=answers;/*在这里做一些命令行反射反馈和程序性工作*//*(如:提示用户输入是否合法,创建文章对应的目录和文件等)*/}).catch(err=>{/*异常处理*/});如果是,将这个node脚本添加到项目package.json的脚本中(如:new-post:"nodenewPost.js"),即可执行2.2mdtohtml(基于react-markdown)使用markdown文档通过npmrun命令编辑和存储博客文章的内容,需要将md文档转换成ReactJSX对象渲染到网页中。这里推荐使用react-markdown,有6个功能,作者维护比较用心。用法如下:importReactMarkdownfrom'react-markdown';//

这是文章的标题

2.3代码块的语法Highlightreact-markdown提供了一个renderers属性,用户可以传入一系列renderer组件来自定义文章中某些内容的渲染方式(感兴趣的童鞋可以看包作者的实现)默认渲染器)。例如:自定义md中图片的渲染方式(用法如下)。//渲染器的传入方式//ImageRenderer的实现importReact,{Component}from'react';从'prop-types'导入PropTypes;classImageRendererextendsComponent{staticpropTypes={src:PropTypes.string.isRequired,};render(){return();}}导出默认ImageRenderer;与此类似,我们可以通过传入自定义渲染器来实现文章中代码块的语法高亮。名为CodeBlock的渲染器实现如下:importReact,{Component}from'react';从“prop-types”导入PropTypes;从'prismjs'导入{高亮,语言};从“react-html-parser”导入ReactHtmlParser;导入“prismjs/themes/prism.css”;导出类HtmlComponent扩展组件{staticpropTypes={html:PropTypes.string.isRequired,};render(){返回ReactHtmlParser(this.props.html);}}exportclassCodeBlockextendsComponent{staticpropTypes={literal:PropTypes.string.isRequired,language:PropTypes.string.isRequired,};render(){consthtml=highlight(this.props.literal,languages[this.props.language]);constcls=`language-${this.props.language}`;返回();}}导出默认代码块;这里使用了两个npm包,prismjs和react-html-parser。前者用于将代码文本转换为html文本,后者用于将html文本转换为把它变成一个ReactJSX对象传递给React组件(这比直接使用dangerouslySetInnerHTML属性更安全)3.文章分类一个友好的站点必须有一个导航菜单(或文章分类菜单)。我的实现方式是直接使用文章的“标签”进行分类统计,生成站点的顶部导航。效果如下:为此,需要编写一定的脚本来实现文章的分类统计和打包。我个人的实现方式是将统计结果和文章内容打包成json文件,通过前端组件请求数据并加载。导航栏组件的具体实现如下:importReact,{Component}from'react';importPropTypesfrom'prop-types';import{Link}from'react-router-dom';import{Dropdown,Menu,Icon}from'antd';import{randomId}from'utils';import'./style.css';exportclassHeaderextendsComponent{staticpropTypes={data:PropTypes.array,activeTag:PropTypes.string,};staticdefaultProps={data:[{tag:'前端',count:5}],activeTag:'',};构造函数(道具){超级(道具);this.navTotal=6;}renderMore(){if(this.props.data.length<=this.navTotal){返回假;}constsubNavItems=this.props.data.slice(this.navTotal).map(t=>{t.tag}({t.count}));constSubNav=({subNavItems});constDropDownBtn=(更多分类
);返回DropDownBtn;}renderTop5(){constitems=this.props.data.slice(0,this.navTotal-1).map(t=>{!t.linkTo?`${t.tag}(${t.count})`:t.tag});返回({items}{this.renderMore()}
);}render=()=>this.renderTop5();}exportdefaultHeader;大家可以根据实际需要实现自己的文章打包方式(这个这里就不贴我的脚本了吗?)4.更多功能对于个人博客来说,目前还有很多功能没有实现,这里偷懒了,附上一些相关链接:4.1文章评论都在AddDisquscommentsystemtogithubpagess使用GitHubIssues搭建评论系统4.2关于文章结构树TreeMDownmarkdown-tree最近应该为React实现一个markdown树组件,大家不妨期待一下??5.发表你的个人静态站点5.1部署到githubpages(基于gh-pages)CRA特别推荐githubpages的包:gh-pages,使用方法如下:(1)修改项目的package.json文件,添加homepage属性:"homepage":"https://parksben.github.io",(2)安装gh-pages依赖后修改项目,在package.json中添加如下配置:"scripts":{+"predeploy":"npmrunbuild",+"deploy":"gh-pages-dbuild","start":"react-scriptsstart","build":"react-scriptsbuild",(3)上传本地代码到github博客仓库的一个分支(只要不是master分支),然后执行:yarndeploygh-pages会把CRA项目构建到仓库的master分支,然后就可以访问你的站点了(看这里CRA项目部署到github页面的详细说明)。5.2如何兼容React的客户端路由(比较hacky的方法)单页应用一般需要设置服务端路由,将应用的所有页面路径重定向到index.html,但是githubpages没有这样的默认设置。因此,当你使用React的客户端路由时(React的createBrowserHistory方法创建前端路由),github对于根路径以外的页面会返回自己的404页面。为此,CRA项目提供了一种hack方法来支持React的客户端路由(通过操作window.history来强制匹配url)。也算是个奇葩技能吧??。(1)在CRA项目的public目录下添加一个404.html,内容如下:Short每天都紧|parksben的博客(2)在index.html的头部添加如下代码:大功告成,你的github站点支持React客户端除了路由之外,还可以使用createHashHistory方法创建客户端路由,这样前端路由几乎没有做服务器路由,但是url中的哈希字符串毕竟不够优雅。有兴趣了解奇技淫技的童鞋可以点这里。5.3部署到自己的服务和CRA项目的生产环境部署方法一样:在线执行yarnbuild命令,站点的所有静态资源都会打包到build目录下。配置你站点的入口到构建目录6.项目参考(这里是源代码)这是我的github博客(基于以上过程的静态站点)。感兴趣的小伙伴可以点击此处查看项目源代码。如果你觉得它有用,你可以fork或star它。