blog搭建学习day1

为什么要搭建在服务器上,为了24小时可以查看你的博客
准备工作:先购买一台服务器作为博客的准备
如何使用vscode远程连接服务器
注意:服务器出问题可以看看端口是否打开
https://zhuanlan.zhihu.com/p/667236864?s_r=0

1. 第一步环境搭建

后端环境选择与搭建

  1. 后端选择Python环境与fastapi搭建
  2. 环境搭建检测 (环境通常在服务器上已经安装好)Python 3 和 pip (python3 --version, pip3 --version)

2. 第二步创建项目结构

服务器输入代码:

# 在你喜欢的位置创建一个项目主目录
mkdir my-blog

#进入该目录
cd my-blog

#分别为后端和前端创建目录
mkdir backend
mkdir frontend
现在你的目录结构看起来是这样的:

my-blog/
├── backend/
└── frontend/

2.1配置后端

创建虚拟后端

1
2
3
4
5
# 进入后端目录
cd backend

# 使用 python3 创建一个名为 venv 的虚拟环境
python3 -m venv venv

激活虚拟环境

1
2
# 激活 venv 环境
source venv/bin/activate

安装依赖包

1
2
# 使用 pip 安装所有必需的库
pip install fastapi "uvicorn[standard]" sqlalchemy psycopg2-binary passlib[bcrypt] python-jose

我们来解释一下每个库的作用:

  • fastapi: 核心Web框架。

  • uvicorn[standard]: 高性能的ASGI服务器,用于运行你的FastAPI应用。[standard]会附带一些推荐的性能优化库。

  • sqlalchemy: ORM(对象关系映射)库,让你用Python类来操作数据库。

  • psycopg2-binary: 连接PostgreSQL数据库所需要的驱动。

  • passlib[bcrypt]: 用于处理密码哈希,[bcrypt]是推荐的加密算法。

  • python-jose: 用于创建和验证JWT(JSON Web Tokens)认证令牌。
    创建第一个API并测试运行
    创建一个名为 main.py 的文件: touch main.py
    输入以下内容:

    1
    2
    3
    4
    5
    from fastapi import FastAPI
    app = FastAPI()
    @app.get("/")
    def read_root():
    return {"Hello": "Backend"}

    在命令行中启动开发服务器:

    1
    2
    3
    4
    # 启动 uvicorn 服务器
    # main:app 指的是 "运行 main.py 文件中的 app 实例"
    # --reload 会在代码变动时自动重启服务,非常适合开发
    uvicorn main:app --reload

    验证: 服务器启动后,你会看到类似下面的输出:

    1
    INFO:     Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)

    2.2配置前端

    进入前端目录

    1
    cd my-blog/frontend

    使用Vite创建React项目
    下面的命令会自动生成一个现代化的React项目结构。

1
2
3
# `.` 表示在当前目录(frontend)下创建项目
# `-- --template react` 是告诉Vite我们想使用React模板
npm create vite@latest . -- --template react

安装项目依赖
项目创建后,package.json 文件中已经列出了所有基础依赖,我们用npm来安装它们。

1
npm install

npm命令下载慢解决办法

1
2
# 建议不要直接使用 cnpm 安装依赖,会有各种诡异的 bug。可以通过如下操作解决 npm 下载速度慢的问题
npm install --registry=https://registry.npmmirror.com

nodejs版本过低

warn EBADENGINE 不支持的引擎 {
1
2
3
4
5
6
7
8

npm warn EBADENGINE 包:'vite@7.0.2',

npm warn EBADENGINE required: { node: '^20.19.0 || >=22.12.0' },

npm warn EBADENGINE current: { node: 'v18.20.4', npm: '10.7.0' }

npm warn EBADENGINE }

解决办法

1
2
3
4
5
6
7
8
9
10
1. 安装 NVM

要解决这个问题,首先需要安装 nvm。你可以使用以下命令通过 curl 安装 nvm
1:

curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.3/install.sh | bash
安装完成后,重新启动终端或运行以下命令以加载 nvm
2:

source ~/.nvm/nvm.sh

安装额外的库
我们需要 来和后端API通信,以及 来管理页面跳转。axiosreact-router-dom

1
npm install axios react-router-dom

启动前端开发服务器

1
2
# 启动 Vite 的开发服务器
npm run dev

现在前后端环境搭建完毕

3.制作blog的demo展示前后端可交互

1.改造后端:创建一个能返回真实(模拟)数据的API接口,并解决“跨域”问题。

目前你的后端只有一个返回 {“Hello”: “Backend”} 的根路径。现在我们要创建一个新的接口 /api/posts 来返回博客文章列表。

1.1 解决跨域 (CORS) 问题###

什么是跨域? 出于安全原因,浏览器默认禁止网页(例如运行在 localhost:5173 的前端)向不同源(origin,即不同域名或端口,例如 localhost:8000 的后端)发送请求。我们必须在后端明确声明:“我允许来自 localhost:5173 的请求”,浏览器才会放行。

停止当前后端服务:在运行uvicorn的后端终端里,按 Ctrl + C。

安装FastAPI的CORS中间件:FastAPI已经内置了这个功能。

修改backend/main.py文件:

用你的编辑器打开 backend/main.py,然后替换成下面的内容:

fastapi import FastAPI
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
from fastapi.middleware.cors import CORSMiddleware # 导入CORS中间件

app = FastAPI()

# --- 配置CORS ---
# 定义允许的源(你的前端应用的地址)
origins = [
"http://localhost:5173",
"http://127.0.0.1:5173",
]

app.add_middleware(
CORSMiddleware,
allow_origins=origins, # 允许访问的源
allow_credentials=True, # 支持 cookie
allow_methods=["*"], # 允许所有方法
allow_headers=["*"], # 允许所有标头
)
# --- CORS配置结束 ---


# 创建一些模拟的博客文章数据
dummy_posts = [
{"id": 1, "title": "FastAPI入门", "content": "这是关于FastAPI的第一篇文章..."},
{"id": 2, "title": "React Hooks详解", "content": "useState和useEffect是必学的..."},
{"id": 3, "title": "前后端分离架构", "content": "为什么我们需要前后端分离?"},
]

@app.get("/")
def read_root():
return {"Hello": "Backend"}

# 创建一个新的API端点来返回文章列表
@app.get("/api/posts")
def get_posts():
return dummy_posts

1.2 重启后端服务

修改并保存好 main.py 文件后,在后端的终端中,用和之前完全一样的命令重新启动服务:

1
uvicorn main:app --reload

2.改造前端:编写React组件,使用axios来请求后端接口,并将返回的数据渲染出来。

接下来,我们修改前端React应用,让它去请求刚刚创建的 /api/posts 接口。

2.1 修改 frontend/src/App.jsx

打开 frontend/src/App.jsx 文件,用下面的代码完全替换掉原来的内容。我会通过注释解释每一部分的作用。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
import React, { useState, useEffect } from 'react';
import axios from 'axios'; // 导入axios
import './App.css'; // 保留一些基础样式

function App() {
// --- State管理 ---
// 使用useState创建三个状态变量
// posts: 用于存储从后端获取的文章列表,初始值为空数组
// loading: 用于表示数据是否正在加载中,初始值为true
// error: 用于存储请求过程中发生的任何错误,初始值为null
const [posts, setPosts] = useState([]);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);

// --- 数据请求 ---
// 使用useEffect Hook来在组件加载后执行数据请求
// 第二个参数为空数组[],表示这个effect只在组件第一次挂载时运行一次
useEffect(() => {
// 定义一个异步函数来获取数据
const fetchPosts = async () => {
try {
// 使用axios向后端的/api/posts接口发送GET请求
// 注意:这里使用了完整的URL,因为前端和后端在不同端口上
const response = await axios.get('http://127.0.0.1:8000/api/posts');

// 请求成功后,用返回的数据更新posts状态
setPosts(response.data);
} catch (err) {
// 如果请求过程中发生错误,更新error状态
setError('获取数据失败,请检查后端服务是否开启或CORS配置是否正确。');
console.error(err); // 在控制台打印详细错误
} finally {
// 无论成功还是失败,最后都将loading状态设置为false
setLoading(false);
}
};

fetchPosts(); // 调用这个函数
}, []); // 空依赖数组,确保只运行一次

// --- UI渲染 ---
// 根据loading和error的状态来决定显示什么内容
if (loading) {
return <div>正在努力加载中...</div>;
}

if (error) {
return <div>{error}</div>;
}

// 如果一切正常,渲染文章列表
return (
<div className="App">
<header className="App-header">
<h1>我的博客</h1>
</header>
<main>
{posts.map(post => (
<article key={post.id} className="post-item">
<h2>{post.title}</h2>
<p>{post.content}</p>
</article>
))}
</main>
</div>
);
}

export default App;

2.2 添加一些简单样式 (可选)

为了让列表看起来更清晰,可以打开 frontend/src/App.css 并添加一些样式:

1
2
3
4
5
6
7
8
9
10
11
12
13
/* ...保留文件中已有的样式... */

.post-item {
border: 1px solid #ddd;
padding: 1rem;
margin: 1rem;
border-radius: 8px;
text-align: left;
}

.post-item h2 {
margin-top: 0;
}

现在博客的基本框架已经全部搭建完毕可以尝试更多其他的操作