帮助你简易起步一个BLOG(博客搭建)项目

Blog项目

  • 后端
    • 项目结构
    • 1. 项目初始化
    • 2. 详细步骤
    • 3.postman测试
  • 前端
    • 1. 项目初始化
    • 2. 详细步骤

本章节是为了帮助你起步一个完整的前后端分离项目。
前端技术栈: react、vite、mantine、tailwind CSS、zustand、rxjs、threejs

后端技术栈:nodemon、nodejs、vite

后端

项目结构

blog-backend/
│
├── server/
│   ├── index.js
│   └── routes/
│       └── posts.js
├── package.json
└── vite.config.js

1. 项目初始化

  • 创建项目文件夹并初始化 Node.js 项目。
  • 安装必要的依赖项。

2. 详细步骤

  1. 创建项目文件夹并初始化 Node.js 项目
mkdir blog-backend
cd blog-backend
npm init -y
  1. 安装必要的依赖项
    安装 Express.js 作为我们的 web 框架,安装 Nodemon 作为开发依赖,用于监控文件变化并自动重启服务器。
npm install express
npm install --save-dev nodemon
  1. 创建 Express.js 服务器
    在 server 文件夹中创建 index.js 入口文件。
// server/index.js
const express = require('express');
const path = require('path');
const postsRouter = require('./routes/posts');

const app = express();
const PORT = process.env.PORT || 3000;

// 中间件
app.use(express.json());
app.use(express.urlencoded({ extended: true }));

// 路由
app.use('/api/posts', postsRouter);

// 启动服务器
app.listen(PORT, () => {
  console.log(`Server is running on http://localhost:${PORT}`);
});
  1. 创建路由文件
    在 server/routes 文件夹中创建 posts.js 路由文件。
// server/routes/posts.js
const express = require('express');
const router = express.Router();

// 模拟的博客帖子数据
let posts = [
  { id: 1, title: 'First Post', content: 'This is the first post.' },
  { id: 2, title: 'Second Post', content: 'This is the second post.' }
];

// 获取所有博客帖子
router.get('/', (req, res) => {
  res.json(posts);
});

// 获取单个博客帖子
router.get('/:id', (req, res) => {
  const post = posts.find(p => p.id === parseInt(req.params.id));
  if (post) {
    res.json(post);
  } else {
    res.status(404).json({ message: 'Post not found' });
  }
});

// 创建新的博客帖子
router.post('/', (req, res) => {
  const newPost = {
    id: posts.length + 1,
    title: req.body.title,
    content: req.body.content
  };
  posts.push(newPost);
  res.status(201).json(newPost);
});

// 更新博客帖子
router.put('/:id', (req, res) => {
  const post = posts.find(p => p.id === parseInt(req.params.id));
  if (post) {
    post.title = req.body.title || post.title;
    post.content = req.body.content || post.content;
    res.json(post);
  } else {
    res.status(404).json({ message: 'Post not found' });
  }
});

// 删除博客帖子
router.delete('/:id', (req, res) => {
  posts = posts.filter(p => p.id !== parseInt(req.params.id));
  res.status(204).end();
});

module.exports = router;
  1. 更新 package.json 脚本
    在 package.json 中更新脚本,以便在开发过程中使用 Nodemon 监控文件变化。
{
  "name": "blog-backend",
  "version": "1.0.0",
  "description": "A blog backend using Node.js and Express.js",
  "main": "server/index.js",
  "scripts": {
    "start": "node server/index.js",
    "dev": "nodemon server/index.js"
  },
  "dependencies": {
    "express": "^4.17.1"
  },
  "devDependencies": {
    "nodemon": "^2.0.7"
  }
}
  1. 运行项目
    运行以下命令启动开发服务器:
npm run dev

通过以上步骤,我们已经创建了一个基本的博客后端项目,使用 Node.js 和 Express.js 提供 API 接口。这个后端支持获取、创建、更新和删除博客帖子。你可以在前端使用任何框架或工具与这个 API 进行交互。
a. 为这些 API 添加单元测试来验证其功能。
b. 增加用户认证和授权,以保护博客帖子数据。

3.postman测试

3.1 获取所有博客帖子

方法: GET
URL: http://localhost:3000/api/posts

点击 “Send” 按钮,你应该会看到类似下面的响应:

[
  { "id": 1, "title": "First Post", "content": "This is the first post." },
  { "id": 2, "title": "Second Post", "content": "This is the second post." }
]

3.2. 获取单个博客帖子

方法: GET
URL: http://localhost:3000/api/posts/1

点击 “Send” 按钮,你应该会看到类似下面的响应:

{ "id": 1, "title": "First Post", "content": "This is the first post." }

3.3. 创建新的博客帖子

方法: POST
URL: http://localhost:3000/api/posts

Body: 选择 raw 和 JSON,然后输入以下内容:

{
  "title": "New Post",
  "content": "This is a new post."
}

点击 “Send” 按钮,你应该会看到类似下面的响应:

{
  "id": 3,
  "title": "New Post",
  "content": "This is a new post."
}

3.4. 更新博客帖子

方法: PUT
URL: http://localhost:3000/api/posts/1

Body: 选择 raw 和 JSON,然后输入以下内容:

{
  "title": "Updated First Post",
  "content": "This is the updated first post."
}

点击 “Send” 按钮,你应该会看到类似下面的响应:

{
  "id": 1,
  "title": "Updated First Post",
  "content": "This is the updated first post."
}

3.5. 删除博客帖子

方法: DELETE
URL: http://localhost:3000/api/posts/1

点击 “Send” 按钮,你应该会看到类似下面的响应:

{}

你已经使用 Postman 成功地测试了这个博客 API 的所有基本功能,包括获取所有帖子、获取单个帖子、创建新帖子、更新帖子和删除帖子。

a. 在 API 请求中添加身份验证以保护博客内容。

b. 为 API 添加更多的功能,例如评论功能或者用户管理功能

前端

1. 项目初始化

  • 创建一个新的 Vite 项目并选择 React 作为框架。
  • 安装必要的依赖项。

2. 详细步骤

  1. 创建项目文件夹并初始化 Vite 项目
    首先,创建项目文件夹并初始化 Vite 项目:
mkdir blog-frontend
cd blog-frontend
npm init vite@latest

选择 react 作为模板:

# Project name: blog-frontend
# Select a framework: react
# Select a variant: react

然后安装项目依赖:

cd blog-frontend
npm install
  1. 安装必要的依赖项
    安装 Mantine、Tailwind CSS、Zustand、RxJS 和 Three.js:
npm install @mantine/core @mantine/hooks @emotion/react @emotion/styled zustand rxjs three
npm install -D tailwindcss postcss autoprefixer
npx tailwindcss init -p
npm install react-router-dom
  1. 配置 Tailwind CSS
    编辑 tailwind.config.js 文件以包含所有文件:
/** @type {import('tailwindcss').Config} */
export default {
  content: [
    "./index.html",
    "./src/**/*.{js,ts,jsx,tsx}",
  ],
  theme: {
    extend: {},
  },
  plugins: [],
}

在 src 文件夹中创建 index.css 文件,并添加 Tailwind 的基本样式:

/* src/index.css */
@tailwind base;
@tailwind components;
@tailwind utilities;

确保在 main.jsx 中导入 index.css 文件:

// src/main.jsx
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';

ReactDOM.render(
  <React.StrictMode>
    <App />
  </React.StrictMode>,
  document.getElementById('root')
);
  1. 创建主要组件和结构
    在 src 文件夹中创建以下文件和文件夹结构:
src/
├── components/
│   ├── Header.jsx
│   ├── PostList.jsx
│   └── Post.jsx
├── hooks/
│   └── usePosts.js
├── pages/
│   ├── Home.jsx
│   └── PostDetail.jsx
├── App.jsx
└── main.jsx

App.jsx:

import React from 'react';
import { BrowserRouter as Router, Route, Routes } from 'react-router-dom';
import { MantineProvider } from '@mantine/core';
import Home from './pages/Home';
import PostDetail from './pages/PostDetail';
import Header from './components/Header';

function App() {
  return (
    <MantineProvider withGlobalStyles withNormalizeCSS>
      <Router>
        <Header />
        <Routes>
          <Route path="/" element={<Home />} />
          <Route path="/post/:id" element={<PostDetail />} />
        </Routes>
      </Router>
    </MantineProvider>
  );
}

export default App;

Header.jsx:

import React from 'react';
import { Link } from 'react-router-dom';

function Header() {
  return (
    <header className="bg-blue-600 p-4 text-white">
      <nav className="container mx-auto">
        <Link to="/" className="text-lg font-bold">My Blog</Link>
      </nav>
    </header>
  );
}

export default Header;

Home.jsx:

import React from 'react';
import PostList from '../components/PostList';

function Home() {
  return (
    <div className="container mx-auto p-4">
      <h1 className="text-3xl font-bold mb-4">Blog Posts</h1>
      <PostList />
    </div>
  );
}

export default Home;

PostDetail.jsx:

import React from 'react';
import { useParams } from 'react-router-dom';

function PostDetail() {
  const { id } = useParams();
  // Fetch post detail using id
  return (
    <div className="container mx-auto p-4">
      <h1 className="text-3xl font-bold mb-4">Post Detail</h1>
      {/* Render post detail here */}
    </div>
  );
}

export default PostDetail;

PostList.jsx:

import React from 'react';
import { Link } from 'react-router-dom';
import usePosts from '../hooks/usePosts';

function PostList() {
  const posts = usePosts();
  return (
    <div>
      {posts.map(post => (
        <div key={post.id} className="mb-4 p-4 border rounded">
          <h2 className="text-2xl font-bold">
            <Link to={`/post/${post.id}`}>{post.title}</Link>
          </h2>
          <p>{post.content}</p>
        </div>
      ))}
    </div>
  );
}

export default PostList;

usePosts.js:

import { useEffect, useState } from 'react';

function usePosts() {
  const [posts, setPosts] = useState([]);

  useEffect(() => {
    fetch('/api/posts')
      .then(response => response.json())
      .then(data => setPosts(data));
  }, []);

  return posts;
}

export default usePosts;
  1. 配置 Vite 代理
    在 vite.config.js 文件中配置代理,以将 API 请求转发到后端服务器:
import { defineConfig } from 'vite';
import react from '@vitejs/plugin-react';

export default defineConfig({
  plugins: [react()],
  server: {
    proxy: {
      '/api': 'http://localhost:3000'
    }
  }
});
  1. 运行前端项目
    在项目根目录下运行以下命令启动开发服务器:
npm run dev

通过以上步骤,我们已经创建了一个使用 React、Vite、Mantine、Tailwind CSS、Zustand、RxJS 和 Three.js 的博客前端。这个前端项目通过 Vite 开发服务器代理 API 请求,并与之前创建的 Node.js 和 Express.js 后端进行交互。

a. 在前端添加更多组件,例如博客详情页和评论功能。

b. 使用 Three.js 创建炫酷的 3D 动画效果,并将其集成到博客前端中。

前后端都起起来,就可以在浏览器中访问前端页面了。
在这里插入图片描述
这一章主要是帮助小伙伴迅速起一个前后端分离的blog项目,后续可以自行diy。
后续我可能会继续更新自己的项目。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/751353.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

平面点云格网过程及可视化介绍(python)

1、背景介绍 实际人工构造物中&#xff0c;很多物体表面为平面结构&#xff0c;因此将点云投影在二维平面上进行处理&#xff0c;如进行点云面积计算、点云边缘提取等。 具体案例可以参考博客&#xff1a;详解基于格网法统计平面点云面积_点云格网法计算xy投影面积-CSDN博客、点…

AI 开发平台(Coze)搭建《AI女友(多功能版本)》

前言 本文讲解如何从零开始&#xff0c;使用扣子平台去搭建《AI女友&#xff08;多功能版本&#xff09;》 bot直达&#xff1a;AI女友&#xff08;多功能版&#xff09; - 扣子 AI Bot (coze.cn) 欢迎大家前去体验&#xff01;&#xff01;&#xff01; 正文 功能介绍 …

C#串口通信Seriaport和页面传值

串口通信 串口COM&#xff1a;是一种用于连接计算机和外设设备的接口&#xff0c;也叫串行接口&#xff0c;简称com,常见的串口有一半电脑应用的RS-232&#xff08;使用25针或9针的 连接器&#xff09;通俗来讲串口就是usb接口、鼠标串口。键盘串口 串口通讯&#xff1a;是指外…

Spring Clude 是什么?

目录 认识微服务 单体架构 集群和分布式架构 集群和分布式 集群和分布式区别和联系 微服务架构 分布式架构&微服务架构 微服务的优势和带来的挑战 微服务解决方案- Spring Cloud 什么是 Spring Cloud Spring Cloud 版本 Spring Cloud 和 SpringBoot 的关系 Sp…

VScode远程连接时卡住

将报错文件删除 ### 查找文件(base) ~ find /home -name 5c3e652f63e798a5ac2f31ffd0d863669328dc4c /home/cszx/.vscode-server/data/clp/99e4e0e4dad86d47de9777231596fd92.zh-cn/5c3e652f63e798a5ac2f31ffd0d863669328dc4c ### 删除(base) ~ rm -rf /home/cszx/.vscode-ser…

centOS7网络配置_NAT模式设置

第一步&#xff1a;查看电脑网卡 nat模式对应本地网卡的VMnet 8 &#xff0c;查看对应的IP地址。 第二步&#xff1a;虚拟网络编辑器 打开VMWare&#xff0c;编辑--虚拟网络编辑器&#xff0c;整个都默认设置好了&#xff0c;只需要查看对应的DHCP设置中对应的IP的起始&#…

MySQL数据类型、运算符以及常用函数

MySQL数据类型 MySQL数据类型定义了数据的大小范围&#xff0c;因此使用时选择合适的类型&#xff0c;不仅会降低表占用的磁盘空间&#xff0c; 间接减少了磁盘I/O的次数&#xff0c;提高了表的访问效率&#xff0c;而且索引的效率也和数据的类型息息相关。 数值类型 浮点类型…

01.Ambari自定义服务开发-项目初始化

文章目录 基础环境在PyCharm中初始化项目配置项目相关依赖在PyCharm中导入依赖 基础环境 PyCharmPython 2.7已经安装完成的Ambari服务端 在PyCharm中初始化项目 项目名称就是我们要安装服务的名称&#xff0c;要求名称为全大写&#xff0c;如&#xff1a;DORIS创建Python2.7…

AUTOSAR以太网之IPv4

系列文章目录 返回总目录 文章目录 系列文章目录一、IPv4报文格式二、主要函数1.IPv4_Init()2.IPv4_Receive()3.IPv4_Transmit() 一、IPv4报文格式 二、主要函数 1.IPv4_Init() 这个函数除了对模块配置进行初始化&#xff0c;如果有分包和组包使能&#xff0c;则会对一些相关…

【高级篇】分区与分片:MySQL的高级数据管理技术(十三)

引言 在上一章,我们探讨了MySQL的主从复制与高可用性,这是构建健壮数据库架构的基石。现在,让我们深入到更高级的主题——分区与分片,这些技术对于处理大规模数据集和提升数据库性能至关重要。我们将详细介绍表分区的概念、类型及分片技术的应用,为下一章讨论MySQL集群与…

2.5 MAC扫描器

MAC扫描器是一款专门用来获取网卡物理地址的网络管理软件&#xff0c;相对于Windows系统的getmac命令&#xff0c;MAC扫描器功能更加强大&#xff0c;它不仅可以获取局域网计算机的MAC地址&#xff0c;还可以获取 Internet 中网卡的MAC地址。MAC扫描器通常被用来管理本地网络中…

22 Shell编程之免交互

目录 22.1 Here Document免交互 22.1.1 Here Document概述 22.1.2 Here Document免交互 22.1.3 Here Document变量设定 22.1.4 Here Document格式控制 22.1.5 Here Document多行注释 22.2 expect免交互 22.2.1 expect概述 22.2.2 expect安装 22.2.3 基本命令介绍 22.2.4expec…

Python操作MySQL数据库--使用pymysql模块

Python操作MySQL数据库--使用pymysql模块 一、新建数据库和数据表1.1 新建book数据库1.2 新建bookprice数据表二、连接数据库2.1 建立数据库连接三、新增数据3.1 新增单条数据3.2 新增多条数据3.3 批量新增四、修改数据4.1 修改单条数据4.2 修改多条数据五、删除数据5.1 删除单…

Java基础(四)——字符串、StringBuffer、StringBuilder、StringJoiner

个人简介 &#x1f440;个人主页&#xff1a; 前端杂货铺 ⚡开源项目&#xff1a; rich-vue3 &#xff08;基于 Vue3 TS Pinia Element Plus Spring全家桶 MySQL&#xff09; &#x1f64b;‍♂️学习方向&#xff1a; 主攻前端方向&#xff0c;正逐渐往全干发展 &#x1…

配置 Cmder 到鼠标右键

win Q 快捷键搜索 cmd&#xff0c;以管理员身份运行 在命令行输入 cmder.exe /REGISTER ALL

浏览器插件利器-allWebPluginV2.0.0.14-beta版发布

allWebPlugin简介 allWebPlugin中间件是一款为用户提供安全、可靠、便捷的浏览器插件服务的中间件产品&#xff0c;致力于将浏览器插件重新应用到所有浏览器。它将现有ActiveX插件直接嵌入浏览器&#xff0c;实现插件加载、界面显示、接口调用、事件回调等。支持谷歌、火狐等浏…

推荐系统三十六式学习笔记:原理篇.模型融合14|一网打尽协同过滤、矩阵分解和线性模型

目录 从特征组合说起FM模型1.原理2.模型训练3.预测阶段4.一网打尽其他模型5.FFM 总结 在上一篇文章中&#xff0c;我们讲到了使用逻辑回归和梯度提升决策树组合的模型融合办法&#xff0c;用于CTR预估&#xff0c;给这个组合起了个名字&#xff0c;叫“辑度组合”。这对组合中&…

Arduino平台软硬件原理及使用——SR04超声波传感器的使用

文章目录&#xff1a; 一、超声波传感器工作原理 二、SR04超声波库的使用 三、SR04超声波传感器在Arduino中的使用 一、超声波传感器工作原理 如上图所示&#xff1a;HCSR04超声波传感器拥有4个针脚&#xff0c;除了VCC接正极、GND接负极外&#xff0c;还有两个引脚“Trig”及“…

SuperCopy解决文档不能复制问题

有一些文档&#xff0c;我们要使用时&#xff0c;总是面临收费的情况&#xff0c;让我们不能复制&#xff0c;让人头疼不已&#xff01;&#xff01;&#xff01; SuperCopy就可以解决这个问题。 获取SuperCopy步骤 1. 打开浏览器&#xff0c;点击右上角的三个点 2. 找到扩…

代码随想录算法训练营:14/60

非科班学习算法day14 | LeetCode266:翻转二叉树 &#xff0c;Leetcode101: 对称二叉树&#xff0c;Leetcode100:相同的的树 &#xff0c;LeetCode572:另一颗树的子树&#xff0c;LeetCode104&#xff1a;二叉树的最大深度&#xff0c;LeetCode559&#xff1a;N叉树的最大深度 目…