前言: 用过hexo后,我被其强大的功能惊艳到了,于是便想自己也写一个静态博客生成器,并且可以发布到GitHub托管。
首先我们来看下效果图:
具体是怎么实现的呢?
我们通过create-react-app构建react单页应用后,删除了默认创建的js和jsx,自己建立了布局页(Layout.jsx),其中包含了页头导航(NavBar.jsx)和页尾(Footer.jsx)
export default function Layout(props){
return (
<>
<div className="card bg-base-100 shadow-xl h-container">
<NavBar />
{props.children}
</div>
<Footer />
</>
)
}
这样我们中间内容每次就可以用布局页包裹,例如:
<Layout>
<div style={{
padding: "30px"
}}>
<div dangerouslySetInnerHTML={createMarkup(html)}></div>
</div>
</Layout>
然后我们创建了文章页,分组页,分组下文章,首页
值得关注的是,我通过了axios请求静态markdown文件,再通过Remarkable组件解析成Html,使用react自带属性dangerouslySetInnerHTML显示出来,例如:Article.jsx
import React, {useState, useEffect} from "react"
import Layout from "../widget/Layout"
import axios from "axios"
import {getQueryVariable} from "../utils/commonUtil"
import "../css/typo.css"
import 'highlight.js/styles/atom-one-dark.css';
import "../css/code.css"
const {Remarkable} = require("remarkable");
const hljs = require('highlight.js');
hljs.initHighlighting();
function createMarkup(content) {
return {__html: content};
}
export default function Article() {
const [html, setHtml] = useState(<h5>空空如也</h5>);
useEffect(() => {
let _id = getQueryVariable("id");
const fetchData = async () => {
const posts = (await axios.get("/api/post.json")).data;
let post = posts.find(h => h.id === Number(_id));
if (post && post.url) {
const md = (await axios.get(post.url)).data;
const mdTemplate = new Remarkable({
highlight: function(str, lang) {
if (lang && hljs.getLanguage(lang)) {
try {
return hljs.highlight(lang, str).value;
} catch (err) {}
}
try {
return hljs.highlightAuto(str).value;
} catch (err) {}
return "";
}
});
setHtml(mdTemplate.render(md));
}
}
if (_id && _id >= 0) {
fetchData();
}
}, [])
return (<Layout>
<div style={{
padding: "30px"
}}>
<div dangerouslySetInnerHTML={createMarkup(html)}></div>
</div>
</Layout>)
}
还需要注意的是,react公共静态文件需要放到public目录下,如图:
项目至此,大体就是这样,再通过npm run build
就发布了,我们只需要更改api目录下的json文件和md目录下的markdown文件即可自动检索文章和相关配置,项目我推送github了,详情点击https://github.com/cracker-cn/react-static-blog