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

news2024/10/6 0:35:19

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。
后续我可能会继续更新自己的项目。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

《数据结构与算法基础 by王卓老师》学习笔记——1.4算法与算法分析

一、算法 1.1算法的研究内容 1.2算法的定义 1.3算法的描述 以下是算法的自然语言描述 以下是算法的传统流程图表示 以下是NS流程图表示 1.4算法和程序的区别与联系 1.5算法的五个特性 1.6算法设计的要求 Robustness也称为鲁棒性 二、算法分析 2.1算法时间效率的度量 2.1.1事…

CS-隐藏防朔源-数据转发-中间件反向代理-Apache

目录 1、代理机安装Apache: 2、中间件设置转发&#xff1a; 添加代理 3、重启Apache服务 4、CS监听器配置转发机IP 实战情况下还是要准备两台外网服务器. --还是做个中转 1、代理机安装Apache: apt-get install apache2 a2enmod proxy proxy_ajp proxy_balancer proxy_co…

VScode远程连接时卡住

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

ScheduledThreadPoolExecutor和时间轮算法比较

最近项目中需要用到超时操作&#xff0c;对于不是特别优秀的timer和DelayQueue没有看。 Timer 是单线程模式。如果某个 TimerTask 执行时间很久&#xff0c;会影响其他任务的调度。Timer 的任务调度是基于系统绝对时间的&#xff0c;如果系统时间不正确&#xff0c;可能会出现…

安装Django Web框架

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 Django是基于Python的重量级开源Web框架。Django拥有高度定制的ORM和大量的API&#xff0c;简单灵活的视图编写&#xff0c;优雅的URL&#xff0c;适…

SyncFolders文件备份—办公人员必备

SyncFolders支持在两个或多个文件夹之间同步文件&#xff0c;用户可以将重要文件同步到多个位置&#xff0c;如备份硬盘、网络共享文件夹或云存储等。通过设定同步规则&#xff0c;可以自动备份和同步更新&#xff0c;减少手动操作的繁琐&#xff0c;确保文件的安全和可访问性。…

C++编程(五)单例模式 友元

文章目录 一、单例模式&#xff08;一&#xff09;概念&#xff08;二&#xff09;实现方式1. 饿汉式2. 懒汉式 二、友元&#xff08;一&#xff09;概念&#xff08;二&#xff09;友元函数1.概念2.语法格式3. 使用示例访问静态成员变量访问非静态成员变量 &#xff08;三&…

vue3集成Echarts,自定义ToolBox时无法监听参数变化

问题描述 在vue中集成echart中自定义ToolBox工具的点击事件&#xff0c;并将里面的typeBar赋给data中的变量&#xff0c;随后用watch监听这个变量的变化&#xff0c;发现监听不到&#xff01;&#xff01;&#xff01;&#xff01; 解决方案&#xff1a;一直以为是watch不能监…

接口自动化测试框架实战(Pytest+Allure+Excel)

&#x1f345; 视频学习&#xff1a;文末有免费的配套视频可观看 &#x1f345; 点击文末小卡片&#xff0c;免费获取软件测试全套资料&#xff0c;资料在手&#xff0c;涨薪更快 1. Allure 简介 Allure 框架是一个灵活的、轻量级的、支持多语言的测试报告工具&#xff0c;它不…

java根据枚举值动态获取对象bean调用方法示例

1.创建操作枚举 Getter AllArgsConstructor public enum CustomerOperatorType {/*** 用户操作记录分类*/ACCOUNT("账户冻结/解冻"),LEVEL("等级记录"),SCORE( "积分记录");private final String desc; } 2.公共基础类 import lombok.AllAr…

word图题表题公式按照章节编号(不用题注)

预期效果&#xff1a; 其中3表示第三章&#xff0c;4表示第3章里的第4个图。标题、公式编号也是类似的。 为了达到这种按照章节编号的效果&#xff0c;原本可以用插入题注里的“包含章节编号” 但实际情况是&#xff0c;这不仅需要一级标题的序号是用“开始->多级列表”自动…

编码注入

Url&#xff1a;http://www.xxxxxxxx/newsdetail.php?idMjgxOA 判断参数Id存在数字型注入,试了报错注入不行&#xff0c;只能去盲注了 验证Poc1&#xff1a;idMTg4OS8x 等同于&#xff1a;id1889/1 poc2&#xff1a;idMTg4OS8w 等同于&#xff1a;id1889/0 /1 /0 用asci…

数据结构与算法笔记:高级篇 - B+树:MySql数据库索引是如何实现的?

概述 作为一名软件开发工程师&#xff0c;你对数据库肯定再熟悉不过了。MySQL 作为主流的数据库存储系统&#xff0c;它在我们的业务开发中&#xff0c;有着举足轻重的地位。在工作中&#xff0c;为了加速数据库中数据的查找速度&#xff0c;我们常用的处理思路是&#xff0c;…

Java基础教程:入门篇Java基础概念Java入门实例

学习总结 1、掌握 JAVA入门到进阶知识(持续写作中……&#xff09; 2、学会Oracle数据库入门到入土用法(创作中……&#xff09; 3、手把手教你开发炫酷的vbs脚本制作(完善中……&#xff09; 4、牛逼哄哄的 IDEA编程利器技巧(编写中……&#xff09; 5、面经吐血整理的 面试技…

Acitity跳转延时10s会导致anr的时序问题讨论

背景&#xff1a; 针对前些天直播时候&#xff0c;主要讲解是launcher启动app&#xff0c;Activity onResume延时10s不会anr&#xff0c;但是Activity内部activity1跳转activity2就会anr问题展开了讨论 https://mp.weixin.qq.com/s/_uA5yKUTUw-9H-tWxGNK9g 这个原因为啥已经在…

Tomcat WEB站点部署

目录 1、使用war包部署web站点 2、自定义默认网站目录 3、部署开源站点&#xff08;jspgou商城&#xff09; 对主机192.168.226.22操作 对主机192.168.226.20操作 上线的代码有两种方式&#xff1a; 第一种方式是直接将程序目录放在webapps目录下面&#xff0c;这种方式…

昇思25天学习打卡营第03天|张量Tensor

何为张量&#xff1f; 张量&#xff08;Tensor&#xff09;是一个可用来表示在一些矢量、标量和其他张量之间的线性关系的多线性函数&#xff0c;这些线性关系的基本例子有内积、外积、线性映射以及笛卡儿积。其坐标在 &#x1d45b;维空间内&#xff0c;有  &#x1d45b;&a…

【LeetCode】六、哈希集合Set相关:存在重复元素判断 + MyHashSet设计

文章目录 1、Set集合2、Java中的Set集合3、leetcode217&#xff1a;存在重复元素4、P705&#xff1a;设计哈希集合 1、Set集合 无序&#xff1a;写进去的顺序和遍历读出来的顺序不一样不重复 主要作用&#xff1a;查看是否有重复元素&#xff08;给一个数组&#xff0c;转为…

WITS核心价值观【创新】篇|从财务中来,到业务中去

「客尊」、「诚信」、「创新」 与「卓越」 是纬创软件的核心价值观。我们秉持诚信态度&#xff0c;致力于成为客户长期且值得信赖的合作伙伴。持续提升服务厚度&#xff0c;透过数字创新实践多市场的跨境交付&#xff0c;助客户保持市场领先地位。以追求卓越的不懈精神&#xf…

Visual Studio 工具使用 之 即时窗口

即时窗口&#xff1a;是Visual Studio中的一个调试工具&#xff0c;它允许开发人员在调试过程中执行代码并查看结果。开发人员可以在即时窗口中输入和执行表达式、调用方法&#xff0c;并查看变量的值。即时窗口通常用于调试过程中的快速测试和验证代码的正确性。 就是下面的这…