15天零成本搭建靜態博客,託管於Github Page

博客地址

技術棧概覽

  1. 前臺:Umi(路由) + Antd(視圖) + TypeScript(增長項目可維護性以及規範性)
  2. 後臺:Umi(路由) + Antd(視圖) + TypeScript(增長項目可維護性以及規範性) + Rematch(數據管理)
  3. 服務:Egg.js(基於koa的下一代企業級應用框架) + MongoDB

搭建思路

啓動本地Mongo以及Egg服務,隨後啓動博客後臺,編輯文章,將文章數據保存在本地Mongo數據庫。將本地Mongo數據導出爲JSON,前臺頁面用靜態JSON渲染,經過webpack將前臺工程打包成靜態頁,全部靜態資源託管於github page。經過github page提供的映射域名便可訪問靜態頁index.html。css

優勢

  1. 不須要購買域名以及服務器
  2. 能夠經過issue參與文章評論互動
  3. 整個搭建流程有利於提升對項目的理解與認知

缺點

  1. github服務器響應速度慢,致使頁面響應速度慢
  2. 域名晦澀難記
  3. 沒法實現登陸註冊留言等交互功能,缺少互動性

總結

該靜態博客搭建適合有必定基礎,須要項目練手的初級前端開發工程師。博客搭建省時省力,堪稱居家必備良品。一方面有利用提高自身綜合實力,另外一方面不用爲域名和服務器的到期而堪憂。當文章質量獲得保證時,有利於提升github知名度。html

搭建流程

1、 前臺

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

  • markdown語法的渲染

我首先採用了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到項目中,搞定!

  • 動畫的設計。博客採用Antd Animotion來實現動畫效果。該博客的動畫花費了博主大量的時間去設計和實現。
  • 簡歷模塊採用react-fullpage來實現單頁滾動效果。其中,第三板塊的技術棧詳情彈窗採用了antd的modal,彈窗實例化後,改變了body的overflow值,致使單頁滾動失效。博主經過按鈕的點擊事件手動設置body的overflow樣式得以解決該問題。
  • md引用語法不生效。經過手動設置blockquote元素的css樣式。
    blockquote {
      padding: 0 1rem;
      margin-left: 0;
      color: #819198;
      border-left: .3rem solid #dce6f0;
    }
    複製代碼

2、 後臺

模塊設計

最終效果

代理配置

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' }} />
複製代碼
  • 圖片資源的存放 博客選用ipic第三方軟件來存放圖片資源庫。
    經過簡單的拖拽就能夠實現圖片的上傳,上傳成功後返回圖片地址。

3、服務

經過官方腳手架叫快速生成

$ 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);
};

複製代碼

技術難點

  • 導出本地mongo數據爲JSON
/**
   * @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語法也能夠同步到知乎,掘金等社區。對博主以及博主的文章有什麼意見建議,歡迎聯繫博主。

  • QQ:996578843
相關文章
相關標籤/搜索