返回

用 hapi.js、MySQL 和 Nuxt.js (Vue SSR) 构筑简书风格的博客项目

前端

项目介绍

本项目将使用以下技术栈:

  • 后端:Hapi.js(Node.js 框架)
  • 数据库:MySQL
  • 前端:Nuxt.js(Vue SSR 框架)

项目主要功能包括:

  • 用户登录、注册、用户资料修改
  • 文章发布、编辑、删除
  • 文章详情页面
  • 类似于简书的文章数量、总字数、收获的喜欢总数

项目搭建

  1. 安装依赖
npm install hapi mysql nuxt
  1. 创建项目结构
├── app
│   ├── controllers
│   ├── models
│   ├── routes
│   └── views
├── config
│   ├── database.js
│   ├── server.js
└── public
  1. 配置数据库

config/database.js 中配置数据库连接信息:

module.exports = {
  host: 'localhost',
  user: 'root',
  password: '',
  database: 'blog'
};
  1. 创建服务器

config/server.js 中创建 Hapi.js 服务器:

const Hapi = require('hapi');

const server = new Hapi.Server({
  host: 'localhost',
  port: 3000
});

server.route({
  method: 'GET',
  path: '/',
  handler: (request, h) => {
    return 'Hello, world!';
  }
});

server.start((err) => {
  if (err) {
    throw err;
  }
  console.log(`Server running at: ${server.info.uri}`);
});
  1. 创建用户模型

app/models/user.js 中创建用户模型:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  username: {
    type: String,
    required: true,
    unique: true
  },
  password: {
    type: String,
    required: true
  },
  email: {
    type: String,
    required: true,
    unique: true
  }
});

const User = mongoose.model('User', userSchema);

module.exports = User;
  1. 创建文章模型

app/models/article.js 中创建文章模型:

const mongoose = require('mongoose');

const articleSchema = new mongoose.Schema({
  title: {
    type: String,
    required: true
  },
  content: {
    type: String,
    required: true
  },
  author: {
    type: mongoose.Schema.Types.ObjectId,
    ref: 'User'
  }
});

const Article = mongoose.model('Article', articleSchema);

module.exports = Article;
  1. 创建控制器

app/controllers/userController.js 中创建用户控制器:

const User = require('../models/user');

exports.register = async (request, h) => {
  const { username, password, email } = request.payload;
  const user = new User({ username, password, email });
  await user.save();
  return h.response(user).code(201);
};

exports.login = async (request, h) => {
  const { username, password } = request.payload;
  const user = await User.findOne({ username });
  if (!user || !(await user.comparePassword(password))) {
    return h.response({ message: 'Invalid username or password' }).code(401);
  }
  return h.response(user).code(200);
};

app/controllers/articleController.js 中创建文章控制器:

const Article = require('../models/article');

exports.create = async (request, h) => {
  const { title, content, author } = request.payload;
  const article = new Article({ title, content, author });
  await article.save();
  return h.response(article).code(201);
};

exports.get = async (request, h) => {
  const articles = await Article.find();
  return h.response(articles).code(200);
};

exports.getById = async (request, h) => {
  const article = await Article.findById(request.params.id);
  if (!article) {
    return h.response({ message: 'Article not found' }).code(404);
  }
  return h.response(article).code(200);
};

exports.update = async (request, h) => {
  const { title, content } = request.payload;
  const article = await Article.findById(request.params.id);
  if (!article) {
    return h.response({ message: 'Article not found' }).code(404);
  }
  article.title = title;
  article.content = content;
  await article.save();
  return h.response(article).code(200);
};

exports.delete = async (request, h) => {
  const article = await Article.findById(request.params.id);
  if (!article) {
    return h.response({ message: 'Article not found' }).code(404);
  }
  await article.remove();
  return h.response({ message: 'Article deleted' }).code(200);
};
  1. 创建路由

app/routes/user.js 中创建用户路由:

const UserController = require('../controllers/userController');

module.exports = [
  {
    method: 'POST',
    path: '/register',
    handler: UserController.register
  },
  {
    method: 'POST',
    path: '/login',
    handler: UserController.login
  }
];

app/routes/article.js 中创建文章路由:

const ArticleController = require('../controllers/articleController');

module.exports = [
  {
    method: 'POST',
    path: '/articles',
    handler: ArticleController.create
  },
  {
    method: 'GET',
    path: '/articles',
    handler: ArticleController.get
  },
  {
    method: 'GET',
    path: '/articles/{id}',
    handler: ArticleController.getById
  },
  {
    method: 'PUT',
    path: '/articles/{id}',
    handler: ArticleController.update
  },
  {
    method: 'DELETE',
    path: '/articles/{id}',
    handler: ArticleController.delete
  }
];
  1. 运行项目
npm start

打开浏览器,访问 http://localhost:3000,即可看到博客项目的首页。

结语

本项目是一个完整的博客系统,可以满足基本的博客功能需求。开发者可以根据自己的需求,对项目进行进一步的扩展和完善。