記一次 React + Koa + Mysql 構建個人部落格

_Gong發表於2019-04-01

前言

由於一直在用 vue 寫業務,為了熟悉下 react 開發模式,所以選擇了 react。資料庫一開始用的是 mongodb,後來換成 mysql 了,一套下來感覺 mysql 也挺好上手的。react-router、koa、mysql 都是從0開始接觸開發的,期間遇到過很多問題,印象最深的是 react-router 參考官方文件配置的,楞是跑不起來,花費了好幾個小時,最後才發現看的文件是v1.0, 而專案中是v4.3, 好在可參考的資料比較多,問題都迎刃而解了。

部落格介紹

  • 前端專案通過 create-react-app 構建,server端通過 koa-generator 構建
  • 前後端分離,部落格頁、後臺管理都在 blog-admin 裡,對含有 /admin 的路由進行登入攔截
  • 前端: react + antd + react-router4 + axios
  • server端: koa2 + mysql + sequelize
  • 部署:server端 執行在 3000 埠,前端 80 埠,nginx設定代理

預覽地址

web端原始碼

server端原始碼

喜歡或對你有幫助,歡迎 star

功能

  • 登入
  • 分頁
  • 查詢
  • 標籤列表
  • 分類列表
  • 收藏列表
  • 文章列表
  • 釋出文章時間軸
  • 文章訪問次數統計
  • 回到頂部
  • 部落格適配移動端
  • 後臺適配移動端
  • 對文章訪問次數進行視覺化
  • 留言評論
  • 渲染優化、打包優化

效果

標籤

記一次 React + Koa + Mysql 構建個人部落格

分類

記一次 React + Koa + Mysql 構建個人部落格

收藏

記一次 React + Koa + Mysql 構建個人部落格

文章

記一次 React + Koa + Mysql 構建個人部落格

編輯

記一次 React + Koa + Mysql 構建個人部落格

部落格頁

記一次 React + Koa + Mysql 構建個人部落格

響應式

記一次 React + Koa + Mysql 構建個人部落格
記一次 React + Koa + Mysql 構建個人部落格

執行專案

前端

git clone https://github.com/gzwgq222/blog-admin.git
cd blog-admin
npm install
複製程式碼

localhost:2019

server 端

本地安裝 mysql,新建 dev 資料庫

git clone https://github.com/gzwgq222/blog-server.git
cd blog-server
npm install
複製程式碼

server 端

前端 react + antd 開發,較為平緩,在此就不再敘述。主要記錄下 koa + mysql 相關事宜

全域性安裝 koa-generator

npm install -g koa-generato
複製程式碼

建立 node-server 專案

koa node-server 
複製程式碼

安裝依賴

cd node-server 
npn install
複製程式碼

執行

npm dev
複製程式碼

出現 Hello Koa 2! 表示執行成功

記一次 React + Koa + Mysql 構建個人部落格
先看routes檔案

index.js

const router = require('koa-router')()
router.get('/', async (ctx, next) => {
  await ctx.render('index', {
    title: 'Hello Koa 2!'
  })
})
router.get('/string', async (ctx, next) => {
  ctx.body = 'koa2 string'
})
router.get('/json', async (ctx, next) => {
  ctx.body = {
    title: 'koa2 json'
  }
})
module.exports = router
複製程式碼

users.js

const router = require('koa-router')()
router.prefix('/users')
router.get('/', function (ctx, next) {
  ctx.body = 'this is a users response!'
})
router.get('/bar', function (ctx, next) {
  ctx.body = 'this is a users/bar response'
})
module.exports = router
複製程式碼

分別訪問下列路由

localhost:3000/string localhost:3000/users localhost:3000/bar

大概你已經猜到了,koa-router 定義路由訪問時返回相應的內容,那我們只需要把相應的 data 返回去就行了,只是我們的資料得從資料庫查詢出來。

本地安裝 mysql

專案安裝 mysql

npm install mysql --save
複製程式碼

專案安裝 sequelize

sequelize 是 ORM node框架,對SQL查詢語句的封裝,讓我們可以用OOP的方式運算元據庫

npm install --save sequelize
複製程式碼

新建 sequelize.js,建立連線池

const Sequelize = require('sequelize');
const sequelize = new Sequelize('dev', 'root', '123456', {
  host: 'localhost',
  dialect: 'mysql',
  operatorsAliases: false,
  pool: {
    max: 5,
    min: 0,
    acquire: 30000,
    idle: 10000
  }
})
sequelize
  .authenticate()
  .then(() => {
    console.log('MYSQL 連線成功......');
  })
  .catch(err => {
    console.error('連結失敗:', err);
  });
// 根據模型自動建立表
sequelize.sync()
module.exports = sequelize
複製程式碼

建立 model、controllers 資料夾 定義model:定義表結構;controller:定義對資料庫的查詢方法

記一次 React + Koa + Mysql 構建個人部落格

以 tag.js 為例

model => tag.js

const sequelize = require('../sequelize ')
const Sequelize = require('sequelize')
const moment = require('moment') // 日期處理庫
// 定義表結構
const tag = sequelize.define('tag', { 
  id: {
    type: Sequelize.INTEGER(11), // 設定欄位型別
    primaryKey: true, // 設定為主建
    autoIncrement: true // 自增
  },
  name: {
    type: Sequelize.STRING,
    unique: { // 唯一
      msg: '已新增'
    }
  },
  createdAt: {
    type: Sequelize.DATE,
    defaultValue: Sequelize.NOW,
    get() {
      // this.getDataValue 獲取當前欄位value
      return moment(this.getDataValue('createdAt')).format('YYYY-MM-DD HH:mm')
    }
  },
  updatedAt: {
    type: Sequelize.DATE,
    defaultValue: Sequelize.NOW,
    get() {
      return moment(this.getDataValue('updatedAt')).format('YYYY-MM-DD HH:mm')
    }
  }
},
{
  // sequelize會自動使用傳入的模型名(define的第一個引數)的複數做為表名 設定true取消預設設定
  freezeTableName: true
})
module.exports = tag
複製程式碼

controller => tag.s 定義了 create、findAll、findAndCountAll、destroy 方法

const Tag = require('../model/tag')
const Op = require('sequelize').Op
const listAll = async (ctx) => {
  const data = await Tag.findAll()
  ctx.body = {
    code: 1000,
    data
  }
}
const list = async (ctx) => {
  const query = ctx.query
  const where = {
    name: {
      [Op.like]: `%${query.name}%`
    }
  }
  const {rows:data, count: total } = await Tag.findAndCountAll({
    where,
    offset: (+query.pageNo - 1) * +query.pageSize,
    limit: +query.pageSize,
    order: [
      ['createdAt', 'DESC']
    ]
  })
  ctx.body = {
    data,
    total,
    code: 1000,
    desc: 'success'
  }
}
const create = async (ctx) => {
  const params = ctx.request.body
  if (!params.name) {
    ctx.body = {
      code: 1003,
      desc: '標籤不能為空'
    }
    return false
  }
  try {
    await Tag.create(params)
    ctx.body = {
      code: 1000,
      data: '建立成功'
    }
  }
  catch(err) {
    const msg = err.errors[0]
    ctx.body = {
      code: 300,
      data: msg.value + msg.message
    }
  }
}
const destroy = async ctx => {
  await Tag.destroy({where: ctx.request.body})
  ctx.body = {
    code: 1000,
    desc: '刪除成功'
  }
}
module.exports = {
  list,
  create,
  listAll,
  destroy

複製程式碼

在 routers 資料夾 index.js 中引入定義好的 tag controller ,定義路由

const router = require('koa-router')()
const Tag = require('../controllers/tag')
// tag
router.get('/tag/list', Tag.list)
router.get('/tag/list/all', Tag.listAll)
router.post('/tag/create', Tag.create)
router.post('/tag/destroy', Tag.destroy)
module.exports = router
/* 如每個 route 是單獨的檔案,可以使用 router.prefix 定義路由字首
router.prefix('/tag')
router.get('/list', Tag.list)
router.get('/list/all', Tag.listAll)
router.post('/create', Tag.create)
router.post('/destroy', Tag.destroy)
*/
複製程式碼

因為 app 中 已經引入 routers 中的 index.js 呼叫了 app.use了,所以此處不需再引入 在瀏覽器裡輸入 localhost:3000/tag/list 就可以看到返回的資料結構了,只不過 data 為空陣列,因為我們還沒新增進去任何資料 到這裡,model 定義表結構、sequelize運算元據庫、koa-router 定義路由 這一套流程算是完成了,其他表結構,介面 都是一樣定義的

總結

之前沒有寫過 node server 和 react,算是從零搭建該部落格,踩了一些坑,也學到了很多東西,譬如react 開發模式、react-router、sequelize 操作mysql的crud、koa、nginx的配置等等。

麻雀雖小,也是一次完整的前後端開發體驗,脫離了瀏覽器的限制,像海賊王一樣,開啟了新世界的大門,尋找 onepiece ......

web端原始碼

server端原始碼

詳細的 server 端說明

後續會在個人部落格中新增關於此次部署文章

Links

初嘗 react + Node,錯誤之處還望斧正,歡迎提 issue

相關文章