跳到主要内容

Feathers.js 快速上手 - 15分钟搭建你的第一个API

· 阅读需 9 分钟
一介布衣
全栈开发者

发布时间:2024-05-06
作者:一介布衣
标签:Feathers.js, 快速上手, API开发, 实战教程

前言

上一篇文章我们了解了 Feathers.js 的基本概念和优势,今天咱们就来动手实践,真正体验一下 Feathers.js 的魅力。说实话,当我第一次用 Feathers.js 搭建 API 的时候,那种"哇,这也太简单了吧"的感觉至今还记得。

我记得以前用 Express 搭建一个带实时功能的 API,光是配置 Socket.io 就要折腾半天,更别说处理各种边界情况了。但是用 Feathers.js,真的是几分钟就能搞定一个功能完整的 API。

今天我就带大家从零开始,15分钟内搭建一个完整的 API,包含 REST 接口和实时功能。

环境准备

系统要求

  • Node.js 16+ (推荐 18+)
  • npm 或 yarn
  • 代码编辑器(推荐 VS Code)

检查环境

# 检查 Node.js 版本
node --version
# 应该显示 v16.0.0 或更高版本

# 检查 npm 版本
npm --version
# 应该显示 8.0.0 或更高版本

如果版本不够,建议使用 nvm 来管理 Node.js 版本:

# 安装最新的 LTS 版本
nvm install --lts
nvm use --lts

安装 Feathers CLI

Feathers.js 提供了强大的命令行工具,能够快速生成项目结构:

# 全局安装 Feathers CLI
npm install -g @feathersjs/cli

# 验证安装
feathers --version

如果你不想全局安装,也可以使用 npx:

npx @feathersjs/cli --version

创建第一个项目

1. 生成项目

# 创建新项目
feathers generate app

# 或者使用 npx
npx @feathersjs/cli generate app

CLI 会问你一系列问题,我们按照下面的选择:

? Project name: my-feathers-app
? Description: My first Feathers.js application
? What folder should the source files live in? src
? Which package manager are you using? npm
? What type of API are you making? REST, Realtime via Socket.io
? Which testing framework do you prefer? Jest
? This app uses authentication: Yes
? What authentication methods do you want to use? Email + Password
? What is the source of your database? SQL (PostgreSQL, MySQL, MariaDB, SQLite, MSSQL)
? Which database are you connecting to? SQLite
? Does your app require users to verify their email? No

2. 项目结构解析

生成的项目结构如下:

my-feathers-app/
├── config/ # 配置文件
│ ├── default.json # 默认配置
│ └── production.json # 生产环境配置
├── src/ # 源代码
│ ├── services/ # 服务目录
│ ├── hooks/ # 钩子目录
│ ├── models/ # 数据模型
│ ├── app.js # 应用入口
│ └── index.js # 服务器启动文件
├── test/ # 测试文件
├── package.json
└── README.md

3. 启动项目

# 进入项目目录
cd my-feathers-app

# 安装依赖
npm install

# 启动开发服务器
npm run dev

如果一切正常,你会看到:

info: Feathers application started on http://localhost:3030

测试基础功能

1. 访问 API

打开浏览器访问 http://localhost:3030,你会看到 Feathers.js 的欢迎页面。

2. 测试用户注册

# 使用 curl 注册新用户
curl -X POST http://localhost:3030/users \
-H "Content-Type: application/json" \
-d '{
"email": "test@example.com",
"password": "password123"
}'

你会得到类似这样的响应:

{
"id": 1,
"email": "test@example.com",
"createdAt": "2024-05-06T10:00:00.000Z",
"updatedAt": "2024-05-06T10:00:00.000Z"
}

3. 测试用户登录

# 登录获取 JWT token
curl -X POST http://localhost:3030/authentication \
-H "Content-Type: application/json" \
-d '{
"strategy": "local",
"email": "test@example.com",
"password": "password123"
}'

响应会包含访问令牌:

{
"accessToken": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
"authentication": {
"strategy": "local"
},
"user": {
"id": 1,
"email": "test@example.com"
}
}

创建第一个服务

现在我们来创建一个消息服务,体验 Feathers.js 的强大功能:

1. 生成服务

# 生成消息服务
feathers generate service

# 按照提示选择:
? What kind of service is it? KnexJS (SQL)
? What is the name of the service? messages
? Which path should the service be registered on? /messages
? What is the database table name? messages
? Does the service require authentication? Yes

2. 查看生成的文件

CLI 会生成以下文件:

src/
├── services/
│ └── messages/
│ ├── messages.class.js # 服务类
│ ├── messages.hooks.js # 钩子配置
│ └── messages.service.js # 服务注册
└── models/
└── messages.model.js # 数据模型

3. 查看消息模型

打开 src/models/messages.model.js

module.exports = function (app) {
const db = app.get('knexClient');
const tableName = 'messages';

db.schema.hasTable(tableName).then(exists => {
if (!exists) {
db.schema.createTable(tableName, table => {
table.increments('id');
table.string('text').notNullable();
table.integer('userId').unsigned().notNullable();
table.timestamp('createdAt').defaultTo(db.fn.now());
table.timestamp('updatedAt').defaultTo(db.fn.now());

table.foreign('userId').references('id').inTable('users');
})
.then(() => console.log(`Created \${tableName} table`))
.catch(e => console.error(`Error creating \${tableName} table`, e));
}
});

return db;
};

4. 重启服务器

# 重启服务器以应用更改
npm run dev

测试消息服务

1. 创建消息

首先需要获取认证令牌(使用之前登录获得的 token):

# 创建新消息
curl -X POST http://localhost:3030/messages \
-H "Content-Type: application/json" \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN" \
-d '{
"text": "Hello, Feathers.js!"
}'

2. 获取消息列表

# 获取所有消息
curl -X GET http://localhost:3030/messages \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

3. 获取特定消息

# 获取 ID 为 1 的消息
curl -X GET http://localhost:3030/messages/1 \
-H "Authorization: Bearer YOUR_ACCESS_TOKEN"

实时功能测试

Feathers.js 的一大亮点就是实时功能。让我们创建一个简单的 HTML 页面来测试:

1. 创建测试页面

在项目根目录创建 public/index.html

<!DOCTYPE html>
<html>
<head>
<title>Feathers.js 实时测试</title>
<script src="//unpkg.com/@feathersjs/client@^5.0.0/dist/feathers.js"></script>
<script src="/socket.io/socket.io.js"></script>
</head>
<body>
<h1>Feathers.js 实时消息</h1>

<div id="login-form">
<h3>登录</h3>
<input type="email" id="email" placeholder="邮箱" value="test@example.com">
<input type="password" id="password" placeholder="密码" value="password123">
<button onclick="login()">登录</button>
</div>

<div id="app" style="display: none;">
<h3>发送消息</h3>
<input type="text" id="messageText" placeholder="输入消息">
<button onclick="sendMessage()">发送</button>

<h3>消息列表</h3>
<div id="messages"></div>
</div>

<script>
// 连接到 Feathers.js 服务器
const socket = io();
const client = feathers();

client.configure(feathers.socketio(socket));
client.configure(feathers.authentication());

// 登录函数
async function login() {
try {
const email = document.getElementById('email').value;
const password = document.getElementById('password').value;

await client.authenticate({
strategy: 'local',
email,
password
});

document.getElementById('login-form').style.display = 'none';
document.getElementById('app').style.display = 'block';

// 监听实时消息
client.service('messages').on('created', (message) => {
addMessageToList(message);
});

// 加载现有消息
const messages = await client.service('messages').find();
messages.data.forEach(addMessageToList);

} catch (error) {
alert('登录失败: ' + error.message);
}
}

// 发送消息函数
async function sendMessage() {
const text = document.getElementById('messageText').value;
if (!text) return;

try {
await client.service('messages').create({ text });
document.getElementById('messageText').value = '';
} catch (error) {
alert('发送失败: ' + error.message);
}
}

// 添加消息到列表
function addMessageToList(message) {
const messagesDiv = document.getElementById('messages');
const messageDiv = document.createElement('div');
messageDiv.innerHTML = `
<p><strong>用户 \${message.userId}:</strong> \${message.text}</p>
<small>\${new Date(message.createdAt).toLocaleString()}</small>
<hr>
`;
messagesDiv.appendChild(messageDiv);
}
</script>
</body>
</html>

2. 配置静态文件服务

修改 src/app.js,在认证配置之前添加:

// 配置静态文件服务
app.use(express.static(app.get('public')));

确保 config/default.json 中有 public 目录配置:

{
"host": "localhost",
"port": 3030,
"public": "../public/",
// ... 其他配置
}

3. 测试实时功能

  1. 重启服务器:npm run dev
  2. 打开浏览器访问 http://localhost:3030
  3. 使用之前创建的账号登录
  4. 打开多个浏览器标签页,在一个页面发送消息,其他页面会实时收到!

添加消息验证

让我们给消息服务添加一些验证逻辑:

1. 修改消息钩子

编辑 src/services/messages/messages.hooks.js

const { authenticate } = require('@feathersjs/authentication').hooks;

module.exports = {
before: {
all: [ authenticate('jwt') ],
find: [],
get: [],
create: [
// 添加用户ID
context => {
context.data.userId = context.params.user.id;
return context;
},
// 验证消息内容
context => {
const { text } = context.data;

if (!text || text.trim().length === 0) {
throw new Error('消息内容不能为空');
}

if (text.length > 280) {
throw new Error('消息长度不能超过280个字符');
}

// 清理消息内容
context.data.text = text.trim();

return context;
}
],
update: [],
patch: [],
remove: []
},

after: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
},

error: {
all: [],
find: [],
get: [],
create: [],
update: [],
patch: [],
remove: []
}
};

2. 测试验证功能

重启服务器后,尝试发送空消息或超长消息,你会看到相应的错误提示。

项目总结

恭喜!在短短15分钟内,我们完成了:

搭建了完整的 Feathers.js 应用

  • 用户注册和认证系统
  • JWT 令牌管理
  • SQLite 数据库集成

创建了消息服务

  • REST API 接口
  • 数据验证和清理
  • 用户权限控制

实现了实时功能

  • WebSocket 连接
  • 实时消息推送
  • 多客户端同步

添加了前端界面

  • 用户登录
  • 消息发送
  • 实时显示

下一步学习建议

  1. 深入理解核心概念

    • Services 服务架构
    • Hooks 钩子系统
    • Channels 实时频道
  2. 数据库集成

    • MongoDB 适配器
    • 复杂查询和关联
    • 数据迁移
  3. 高级功能

    • 文件上传
    • 邮件发送
    • 第三方认证

常见问题

Q: 为什么选择 SQLite?

A: SQLite 不需要额外安装数据库服务器,非常适合开发和学习。生产环境建议使用 PostgreSQL 或 MySQL。

Q: 如何部署到生产环境?

A: 修改 config/production.json 配置,使用 PM2 或 Docker 部署。

Q: 实时功能的性能如何?

A: Feathers.js 基于 Socket.io,性能很好。对于高并发场景,可以配置 Redis 适配器。

Q: 如何添加更多认证方式?

A: Feathers.js 支持 OAuth、GitHub、Google 等多种认证策略,通过插件即可集成。

总结

通过这个快速上手教程,相信你已经感受到了 Feathers.js 的强大和简洁。仅仅几行代码,我们就实现了一个功能完整的实时 API,这在传统框架中是很难想象的。

Feathers.js 的魅力在于:

  • 约定优于配置 - 遵循最佳实践,减少决策疲劳
  • 实时优先 - 实时功能不是附加品,而是核心特性
  • 渐进式增强 - 可以从简单开始,逐步添加复杂功能

下一篇文章,我们将深入学习 Feathers.js 的核心概念,包括 Services、Hooks 和 Channels 的详细用法。


相关文章推荐:

有问题欢迎留言讨论,我会及时回复大家!