啓動本地Mongo以及Egg服務,隨後啓動博客後臺,編輯文章,將文章數據保存在本地Mongo數據庫。將本地Mongo數據導出爲JSON,前臺頁面用靜態JSON渲染,經過webpack將前臺工程打包成靜態頁,全部靜態資源託管於github page。經過github page提供的映射域名便可訪問靜態頁index.html。css
該靜態博客搭建適合有必定基礎,須要項目練手的初級前端開發工程師。博客搭建省時省力,堪稱居家必備良品。一方面有利用提高自身綜合實力,另外一方面不用爲域名和服務器的到期而堪憂。當文章質量獲得保證時,有利於提升github知名度。html
UI設計前端
因爲博主本人對設計領域着實沒有建樹,因此該博客的UI設計借鑑了一位小姐姐的博客UInode
路由設計react
搭建工程目錄webpack
├── config
│ ├── config.js
│ └── proxyConfig.js
├── package.json
├── src
│ ├── assets
│ ├── common
│ ├── components
│ ├── global.less
│ ├── layouts
│ ├── pages
│ ├── plugins
│ │ └── rematchPlugin
│ │ ├── createPlugin.d.ts
│ │ ├── createPlugin.js
│ │ ├── index.js
│ │ ├── runtime.ts
│ │ ├── template
│ │ │ ├── RematchContainer.tsx
│ │ │ └── Store.ts
│ │ └── ulits.js
│ ├── services
│ ├── store.ts
│ ├── types
│ └── utils
├── tsconfig.json
├── tslint.json
├── typings.d.ts
複製代碼
響應式設計git
博客響應式設計主要採用了Antd的柵格化系統以及enquire-js來判斷瀏覽設備窗口大小github
封裝工具類:web
/**
* @name 判斷瀏覽設備
*/
export function distingIsMobile<T>(): boolean {
let isMobile = false;
enquireScreen(value => {
isMobile = value;
});
return isMobile;
}
複製代碼
技術難點mongodb
我首先採用了react-markdown來渲染markdown語法。可是該組件存在必定的問題:
code代碼塊語法高亮沒法實現,網上的一些解決辦法並不生效。 因而我放棄了使用這個組件。轉向了markdown-it。同時結合markdown-it-highlightjs實現code語法高亮,以此作了一個簡單的封裝,實現本身的markdown組件。
import React, { Component, Fragment } from 'react';
import { Basic } from 'src/types';
const marked = require('markdown-it')().use(require('markdown-it-highlightjs'));
interface Props extends Basic.BaseProps {
source: string;
}
export default class ReactMarkdown extends Component<Props> {
renderMarkdown = () => {
const source = this.props.source;
return <div dangerouslySetInnerHTML={{ __html: marked.render(source) }} />;
};
render() {
return <Fragment>{this.renderMarkdown()}</Fragment>;
}
}
複製代碼
一切搞定以後,發現code標籤內的代碼已經成功分割爲獨立的標籤,可是css並未生效,是由於還未定義高亮的css樣式,因而我找到highlight.js官網,選了一箇中意的高亮樣式,而後在github中找到這個樣式的css文件,copy到項目中,搞定!
blockquote {
padding: 0 1rem;
margin-left: 0;
color: #819198;
border-left: .3rem solid #dce6f0;
}
複製代碼
模塊設計
最終效果
代理配置
const devPath = 'http://127.0.0.1:7001'; // 代理地址指向本地egg服務運行地址
export default {
'/api/': {
target: devPath,
changeOrigin: false
}
};
複製代碼
技術難點
MarkDown編輯器選型
博主最終採用SimpleMDE。
效果圖:
實例化:
componentDidMount() {
this.renderContEditorNode(); // 實例化內容編輯器
this.renderSumEditorNode(); // 實例化摘要編輯器
}
renderContEditorNode() {
this.contEditNode = new SimpleMDE({
element: document.getElementById('contEditor').childElementCount,
...simpleMdConfig
});
}
renderSumEditorNode() {
this.sumEditNode = new SimpleMDE({
element: document.getElementById('sumEditor').childElementCount,
...simpleMdConfig
});
}
複製代碼
編輯器simpleMdConfig配置:
/**
* @name SimpleMDE配置
*/
export const simpleMdConfig = {
autofocus: true,
autosave: true,
shortcuts: {
drawTable: 'Cmd-Alt-T'
},
showIcons: ['code', 'table'],
tabSize: 4,
placeholder: '在這裏編輯',
toolbar: [
'bold',
'italic',
'strikethrough',
'heading',
'code',
'quote',
'unordered-list',
'ordered-list',
'clean-block',
'link',
'image',
'table',
'horizontal-rule',
'preview',
'side-by-side',
'fullscreen',
'guide'
],
previewRender(plainText) {
return marked(plainText, {
renderer: new marked.Renderer(),
gfm: true,
pedantic: false,
sanitize: false,
tables: true,
breaks: true,
smartLists: true,
smartypants: true,
highlight(code) {
return highlight.highlightAuto(code).value; // 採用highlight.js實現代碼塊語法高亮
}
});
}
};
複製代碼
碰見的問題:
{
key: 'summary',
label: '摘要 - 內容',
node: (
<textarea
style={{ maxHeight: '300px', overflow: 'auto' }}
id="sumEditor"
/>
)
},
{
key: 'content',
node: (
<textarea
id="contEditor"
style={{ maxHeight: '300px', overflow: 'auto' }}
/>
)
},
複製代碼
因爲我採用了本身封裝的表單組件,組件內部存在必定的異步渲染,所以在頁面渲染結束時,沒法找到實例化的textarea元素,所以報錯。
解決辦法:
在render函數內寫入兩個隱藏的textarea元素,保障組件實例化後可以找到對應的dom元素,從而成功實例化編輯器。
<textarea id="contEditor" style={{ display: 'none', maxHeight: '300px', overflow: 'auto' }} />
<textarea id="sumEditor" style={{ display: 'none', maxHeight: '300px', overflow: 'auto' }} />
複製代碼
經過官方腳手架叫快速生成
$ npm i egg-init -g
$ egg-init egg-example --type=simple
$ cd egg-example
$ npm i
複製代碼
修改配置
'use strict';
module.exports = appInfo => {
const config = (exports = {});
// use for cookie sign key, should change to your own and keep security
config.keys = appInfo.name + '_1544961945990_6105';
// add your config here
config.middleware = [];
/**
* @name mongo配置,經過egg-mongoose鏈接mongo
*/
config.mongoose = {
url: 'mongodb://127.0.0.1:27017/MingShined',
options: {
useMongoClient: true,
autoReconnect: true,
reconnectTries: Number.MAX_VALUE,
bufferMaxEntries: 0
}
};
/**
* @name 關閉csrf
*/
config.security = {
csrf: {
enable: false
}
};
return config;
};
複製代碼
啓動項目
$ npm run dev
$ open localhost:7001
複製代碼
數據庫設計
restfulApi風格的路由設計
'use strict';
module.exports = app => {
const { router, controller } = app;
/**
* @name 新增文章
*/
router.post('/api/article', controller.article.article.createArticle);
/**
* @name 導出文章
*/
router.get(
'/api/article/download',
controller.article.article.downloadArticle
);
/**
* @name 獲取文章列表
*/
router.get('/api/article', controller.article.article.queryArticleList);
/**
* @name 編輯文章
*/
router.put('/api/article', controller.article.article.updateArticle);
/**
* @name 獲取文章詳情
*/
router.get('/api/article/:id', controller.article.article.findArticle);
/**
* @name 獲取文章詳情
*/
router.delete('/api/article/:id', controller.article.article.deleteArticle);
/**
* @name 獲取關於我
*/
router.get('/api/about', controller.article.article.getAbout);
/**
* @name 保存關於我
*/
router.post('/api/about', controller.article.article.createAbout);
/**
* @name 下載關於我
*/
router.get('/api/about/download', controller.article.article.downloadAbout);
};
複製代碼
技術難點
/**
* @name 下載文章
*/
async downloadArticle() {
const json = await this.service.article.queryArticleList();
this.ctx.attachment('article.json');
this.ctx.set('Content-Type', 'application/json');
this.ctx.body = JSON.stringify(json);
}
複製代碼
總的來講,純手擼一個靜態博客仍是挺有成就感。整個過程遇到種種問題,在這個過程當中,不斷總結進步,提高較大。搭建成功後,也爲本身開拓了一個屬於本身的平臺,通用的md語法也能夠同步到知乎,掘金等社區。對博主以及博主的文章有什麼意見建議,歡迎聯繫博主。