1578 字
8 分钟
Windsurf 保姆级教程:从零开始构建一个完整的博客网站

今天我将带你从零开始,使用 Windsurf 框架构建一个完整的博客网站。无论你是编程新手还是有一定经验的开发者,这篇教程都将一步一步地引导你完成整个项目。我们的目标是让你在阅读完这篇教程后,能够独立使用 Windsurf 构建自己的 Web 应用程序。

目录#

  1. 项目介绍
  2. 环境准备
  3. 创建 Windsurf 项目
  4. 项目结构
  5. 构建博客首页
  6. 用户注册与登录
  7. 创建博客文章
  8. 查看博客文章
  9. 编辑与删除博客文章
  10. 部署项目
  11. 总结

1. 项目介绍#

我们将构建一个简单的博客网站,用户可以注册、登录,创建、查看、编辑和删除博客文章。这个项目将涵盖 Windsurf 的核心功能,包括路由、中间件、模板引擎、数据库集成等。

2. 环境准备#

在开始之前,请确保你的开发环境已经配置好:

  • Node.js:从 Node.js 官网 下载并安装。
  • npm:Node.js 自带 npm,用于安装依赖包。
  • 代码编辑器:推荐使用 Visual Studio Code。

安装完成后,打开终端并运行以下命令,确保 Node.js 和 npm 已经正确安装:

node -v
npm -v

3. 创建 Windsurf 项目#

首先,创建一个新的项目目录,并在该目录下初始化一个 Node.js 项目:

mkdir my-blog
cd my-blog
npm init -y

接下来,安装 Windsurf 和一些必要的依赖:

npm install windsurf ejs mongoose bcrypt express-session express-validator

4. 项目结构#

我们的项目结构如下:

my-blog/
├── app.js
├── package.json
├── public/
│   ├── css/
│   └── js/
├── views/
│   ├── layout.ejs
│   ├── home.ejs
│   ├── login.ejs
│   ├── register.ejs
│   ├── create-post.ejs
│   ├── edit-post.ejs
│   └── post.ejs
└── models/
    └── Post.js

5. 构建博客首页#

5.1 配置 Windsurf#

首先,在 app.js 中配置 Windsurf:

const Windsurf = require('windsurf');
const app = Windsurf();

// 设置模板引擎
app.set('view engine', 'ejs');
app.set('views', './views');

// 静态文件服务
app.use(Windsurf.static('public'));

// 启动服务器
const port = 3000;
app.listen(port, () => {
  console.log(`Server is running on http://localhost:${port}`);
});

5.2 创建首页路由#

app.js 中添加首页路由:

app.get('/', (req, res) => {
  res.render('home', { title: 'My Blog' });
});

5.3 创建首页模板#

views 目录下创建 home.ejs 文件:

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <h1>Welcome to My Blog</h1>
  <p>This is the home page of our blog.</p>
</body>
</html>

5.4 添加样式#

public/css 目录下创建 style.css 文件:

body {
  font-family: Arial, sans-serif;
  margin: 20px;
}

h1 {
  color: #333;
}

5.5 启动服务器#

在终端中运行以下命令启动服务器:

node app.js

打开浏览器,访问 http://localhost:3000,你应该会看到博客的首页。

6. 用户注册与登录#

6.1 配置会话#

app.js 中配置 express-session

const session = require('express-session');

app.use(session({
  secret: 'your-secret-key',
  resave: false,
  saveUninitialized: true
}));

6.2 创建用户模型#

models 目录下创建 User.js 文件:

const mongoose = require('mongoose');

const userSchema = new mongoose.Schema({
  username: String,
  password: String
});

module.exports = mongoose.model('User', userSchema);

6.3 连接数据库#

app.js 中连接 MongoDB:

const mongoose = require('mongoose');

mongoose.connect('mongodb://localhost:27017/myblog', { useNewUrlParser: true, useUnifiedTopology: true });

6.4 用户注册#

app.js 中添加注册路由:

const { body, validationResult } = require('express-validator');
const bcrypt = require('bcrypt');
const User = require('./models/User');

app.get('/register', (req, res) => {
  res.render('register', { title: 'Register' });
});

app.post('/register', [
  body('username').isEmail(),
  body('password').isLength({ min: 6 })
], async (req, res) => {
  const errors = validationResult(req);
  if (!errors.isEmpty()) {
    return res.status(400).json({ errors: errors.array() });
  }

  const { username, password } = req.body;
  const hashedPassword = await bcrypt.hash(password, 10);
  const user = new User({ username, password: hashedPassword });
  await user.save();
  res.redirect('/login');
});

6.5 用户登录#

app.js 中添加登录路由:

app.get('/login', (req, res) => {
  res.render('login', { title: 'Login' });
});

app.post('/login', async (req, res) => {
  const { username, password } = req.body;
  const user = await User.findOne({ username });
  if (user && await bcrypt.compare(password, user.password)) {
    req.session.user = user;
    res.redirect('/');
  } else {
    res.send('Invalid username or password.');
  }
});

6.6 创建注册与登录模板#

views 目录下创建 register.ejslogin.ejs 文件:

register.ejs:

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <h1>Register</h1>
  <form action="/register" method="POST">
    <label for="username">Username:</label>
    <input type="email" id="username" name="username" required>
    <br>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" required>
    <br>
    <button type="submit">Register</button>
  </form>
</body>
</html>

login.ejs:

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <h1>Login</h1>
  <form action="/login" method="POST">
    <label for="username">Username:</label>
    <input type="email" id="username" name="username" required>
    <br>
    <label for="password">Password:</label>
    <input type="password" id="password" name="password" required>
    <br>
    <button type="submit">Login</button>
  </form>
</body>
</html>

7. 创建博客文章#

7.1 创建文章模型#

models 目录下创建 Post.js 文件:

const mongoose = require('mongoose');

const postSchema = new mongoose.Schema({
  title: String,
  content: String,
  author: String,
  createdAt: { type: Date, default: Date.now }
});

module.exports = mongoose.model('Post', postSchema);

7.2 创建文章路由#

app.js 中添加创建文章的路由:

const Post = require('./models/Post');

app.get('/create-post', (req, res) => {
  res.render('create-post', { title: 'Create Post' });
});

app.post('/create-post', async (req, res) => {
  const { title, content } = req.body;
  const post = new Post({ title, content, author: req.session.user.username });
  await post.save();
  res.redirect('/');
});

7.3 创建文章模板#

views 目录下创建 create-post.ejs 文件:

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <h1>Create Post</h1>
  <form action="/create-post" method="POST">
    <label for="title">Title:</label>
    <input type="text" id="title" name="title" required>
    <br>
    <label for="content">Content:</label>
    <textarea id="content" name="content" required></textarea>
    <br>
    <button type="submit">Create Post</button>
  </form>
</body>
</html>

8. 查看博客文章#

8.1 显示所有文章#

app.js 中添加显示所有文章的路由:

app.get('/', async (req, res) => {
  const posts = await Post.find().sort({ createdAt: -1 });
  res.render('home', { title: 'My Blog', posts });
});

8.2 更新首页模板#

更新 home.ejs 文件以显示所有文章:

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <h1>Welcome to My Blog</h1>
  <ul>
    <% posts.forEach(post => { %>
      <li>
        <h2><%= post.title %></h2>
        <p><%= post.content %></p>
        <p>By: <%= post.author %></p>
      </li>
    <% }) %>
  </ul>
</body>
</html>

9. 编辑与删除博客文章#

9.1 编辑文章#

app.js 中添加编辑文章的路由:

app.get('/edit-post/:id', async (req, res) => {
  const post = await Post.findById(req.params.id);
  res.render('edit-post', { title: 'Edit Post', post });
});

app.post('/edit-post/:id', async (req, res) => {
  const { title, content } = req.body;
  await Post.findByIdAndUpdate(req.params.id, { title, content });
  res.redirect('/');
});

9.2 删除文章#

app.js 中添加删除文章的路由:

app.post('/delete-post/:id', async (req, res) => {
  await Post.findByIdAndDelete(req.params.id);
  res.redirect('/');
});

9.3 创建编辑文章模板#

views 目录下创建 edit-post.ejs 文件:

<!DOCTYPE html>
<html>
<head>
  <title><%= title %></title>
  <link rel="stylesheet" href="/css/style.css">
</head>
<body>
  <h1>Edit Post</h1>
  <form action="/edit-post/<%= post._id %>" method="POST">
    <label for="title">Title:</label>
    <input type="text" id="title" name="title" value="<%= post.title %>" required>
    <br>
    <label for="content">Content:</label>
    <textarea id="content" name="content" required><%= post.content %></textarea>
    <br>
    <button type="submit">Save Changes</button>
  </form>
</body>
</html>

10. 部署项目#

10.1 使用 PM2 部署#

安装 pm2

npm install pm2 -g

使用 PM2 启动应用:

pm2 start app.js

10.2 部署到 Heroku#

如果你有 Heroku 账号,可以将项目部署到 Heroku。首先,安装 Heroku CLI 并登录:

heroku login

创建 Heroku 应用:

heroku create

推送代码到 Heroku:

git push heroku main

11. 最后#

现在,你已经成功使用 Windsurf 构建了一个完整的博客网站。通过这个项目,你学习了如何使用 Windsurf 创建路由、处理表单、管理会话、集成数据库等。希望这篇教程对你有所帮助,祝你在未来的开发旅程中取得更多成就!

如果你有任何问题或需要进一步的帮助,请随时联系我。继续加油!

Windsurf 保姆级教程:从零开始构建一个完整的博客网站
https://xichengai.com/posts/windsurf-step-by-step-tutorial.html
作者
西成歌
发布于
2024-12-24
许可协议
CC BY-NC-SA 4.0