Git Product home page Git Product logo

mingshined.github.io's Introduction

技术栈概览

  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。

优点

  1. 不需要购买域名以及服务器
  2. 可以通过issue参与文章评论互动
  3. 整个搭建流程有利于提高对项目的理解与认知

缺点

  1. github服务器响应速度慢,导致页面响应速度慢
  2. 域名晦涩难记
  3. 无法实现登录注册留言等交互功能,缺乏互动性

总结

该静态博客搭建适合有一定基础,需要项目练手的初级前端开发工程师。博客搭建省时省力,堪称居家必备良品。一方面有利用提升自身综合实力,另一方面不用为域名和服务器的到期而堪忧。当文章质量得到保证时,有利于提高github知名度。

搭建流程

一、 前台

UI设计

由于博主本人对设计领域着实没有建树,所以该博客的UI设计借鉴了一位小姐姐的博客UI

路由设计

搭建工程目录

├── 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

响应式设计

博客响应式设计主要采用了Antd的栅格化系统以及enquire-js来判断浏览设备窗口大小

封装工具类:

/**
 * @name 判断浏览设备
 */
export function distingIsMobile<T>(): boolean {
  let isMobile = false;
  enquireScreen(value => {
    isMobile = value;
  });
  return isMobile;
}

技术难点

  • 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;
    }
    

二、 后台

模块设计

最终效果

代理配置

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第三方软件来存放图片资源库。 通过简单的拖拽就可以实现图片的上传,上传成功后返回图片地址。

三、服务

通过官方脚手架叫快速生成

$ 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

mingshined.github.io's People

Contributors

mingshined avatar

Stargazers

 avatar  avatar  avatar  avatar

Watchers

 avatar

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.