前端开发学习blog搭建学习day1
中生代为什么要搭建在服务器上,为了24小时可以查看你的博客
准备工作:先购买一台服务器作为博客的准备
如何使用vscode远程连接服务器
注意:服务器出问题可以看看端口是否打开
https://zhuanlan.zhihu.com/p/667236864?s_r=0
1. 第一步环境搭建
后端环境选择与搭建
- 后端选择Python环境与fastapi搭建
- 环境搭建检测 (环境通常在服务器上已经安装好)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配置前端
进入前端目录
使用Vite创建React项目
下面的命令会自动生成一个现代化的React项目结构。
1 2 3
| # `.` 表示在当前目录(frontend)下创建项目 # `-- --template react` 是告诉Vite我们想使用React模板 npm create vite@latest . -- --template react
|
安装项目依赖
项目创建后,package.json 文件中已经列出了所有基础依赖,我们用npm来安装它们。
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 FastAPI1 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; }
|
现在博客的基本框架已经全部搭建完毕可以尝试更多其他的操作