f2e-server3
Version:
f2e-server 3.0
795 lines (619 loc) • 20.1 kB
Markdown
# F2E-Server 3.0
[](LICENSE)
[](https://nodejs.org/)
[](https://www.typescriptlang.org/)
> 基于 Node.js 的现代化前端开发服务器,支持多运行时环境,集成了完整的开发工具链
## 🚀 项目简介
**F2E-Server 3.0** 是一个基于 Node.js 开发的高性能 HTTP 服务器,专为前端开发而设计。它支持多种运行时环境(Node.js、Bun、Deno、uWebSockets.js),并集成了现代前端开发所需的核心功能。
### ✨ 核心特性
- 🌐 **多运行时支持**: Node.js、Bun、Deno、uWebSockets.js
- 🔥 **热更新**: 基于 EventSource 的实时页面刷新
- 🏗️ **构建工具**: 集成 esbuild、Less、PostCSS、Tailwind CSS
- 🔒 **身份认证**: 内置登录系统和 RBAC 权限管理
- 📡 **代理服务**: HTTP/HTTPS 代理和站点下载功能
- 🛣️ **路由系统**: 服务端 API 开发和路由管理
- 📁 **文件服务**: 静态文件服务、目录浏览、404/500 页面
- ⚡ **性能优化**: Gzip 压缩、缓存控制、流式传输
## 📦 安装
### 全局安装(推荐)
```bash
npm install f2e-server3 -g
```
### 项目依赖安装
```bash
npm install f2e-server3 --save-dev
```
## 🚀 快速开始
### 方式一:使用 CLI 工具(推荐)
```bash
# 创建新项目
npx f2e-server3 create my-app
cd my-app
npm install
npm run dev
```
### 方式二:手动配置
创建启动文件 `start.mjs`:
```javascript
// @ts-check
import { createServer, logger } from 'f2e-server3'
// 设置日志级别
logger.setLevel('DEBUG')
// 启动服务器
createServer({
mode: 'dev',
port: 2850,
livereload: true
})
```
启动服务器:
```bash
# Node.js
node start.mjs
# Bun
bun start.mjs
# Deno
deno --allow-env --allow-read --allow-write --allow-net --allow-run --allow-sys start.mjs
```
## ⚙️ 配置说明
### 运行模式
F2E-Server 提供三种运行模式:
| 模式 | 说明 | 适用场景 |
|------|------|----------|
| `dev` | 开发模式 | 开启服务器、热更新、资源编译 |
| `build` | 构建模式 | 仅编译资源,不启动服务器 |
| `prod` | 生产模式 | 仅启动服务器,开启缓存 |
```javascript
createServer({ mode: 'dev' })
```
### 基础配置
```javascript
createServer({
// 服务器配置
port: 2850,
host: '0.0.0.0',
root: process.cwd(),
// 功能开关
gzip: true,
ssl: false,
// 页面模板
page_404: './templates/404.html',
page_500: './templates/500.html',
page_dir: './templates/directory.html'
})
```
## 🔧 核心功能
### 1. 热更新 (LiveReload)
自动监听文件变化并刷新浏览器:
```javascript
{
livereload: {
// 注入热更新脚本的文件类型
reg_inject: /\.(html|md)$/,
// 心跳超时时间
heartBeatTimeout: 100000
}
}
```
**支持环境**:
- Windows: 默认使用 Node.js API,安装 `chokidar` 后自动升级
- 其他系统: 需要安装 `chokidar`
- Deno: 使用内置 API
### 2. ESBuild 构建
现代化的 JavaScript 构建工具:
```javascript
{
esbuild: {
// 配置文件路径
esbuildrc: './.esbuildrc.js',
// 构建外部依赖
build_external: true
}
}
```
**热模块更新**:
```javascript
// .esbuildrc.js
module.exports = {
hot_modules: ['@/Hello']
}
// React 组件中使用
const [Hello, setHello] = useState(() => require('@/Hello').default)
useEffect(() => {
if (import.meta.hot) {
import.meta.hot.accept('@/Hello', (newModule) => {
setHello(() => newModule.default)
})
}
}, [])
```
### 3. Less 编译
CSS 预处理器支持:
```javascript
{
less: {
entryPoints: [
// 同路径输出
'css/style.less',
// 自定义输出路径
{ in: 'css/style2.less', out: 'static/bundle.css' }
]
}
}
```
### 4. PostCSS 处理
CSS 后处理器,支持 Tailwind CSS:
```javascript
import TailwindPlugin from '@tailwindcss/postcss'
{
postcss: {
entryPoints: {
in: 'css/main.css',
out: 'static/main.css'
},
plugins: [
TailwindPlugin({
optimize: mode === 'build'
})
]
}
}
```
### 5. HTTP 代理
支持 API 转发和站点下载:
```javascript
{
proxies: [
// 简单代理
{
location: '/api',
origin: 'http://api.server.com/'
},
// 正则匹配代理
{
location: /^\/?api1/,
origin: 'http://api1.server.com/',
pathname: '/api/v1'
},
// 站点下载
{
location: '/',
origin: 'https://www.example.com/',
saver: {
pathBodyDir: '/tmp/body',
pathHeaders: '/tmp/headers'
}
}
]
}
```
### 6. 身份认证
内置登录系统:
```javascript
import { UserStore } from 'f2e-server3'
{
auth: {
redirect: true,
white_list?: [
"^publish"
];
store: new UserStore('.f2e_cache/auth.db')
}
}
```
更多配置参考 [auth/interface.ts](src/middlewares/auth/interface.ts)
**用户文件格式** (`.f2e_cache/auth.db`):
```
admin:e10adc3949ba59abbe56e057f20f883e:管理员
user:e10adc3949ba59abbe56e057f20f883e:用户
```
### 7. 路由系统
F2E-Server 3.0 提供了强大的服务端 API 开发能力,支持多种路由注册方式和响应类型。
#### 7.1 核心概念
- **Route**: 核心路由类,管理路由注册和匹配
- **RouteItem**: 路由项配置,包含路径、处理器、响应类型等
- **RouterDecorator**: 装饰器方式注册路由
- **addRoute**: 函数式路由注册
#### 7.2 路由注册方式
##### 方式1: 直接使用 Route 类
```javascript
import { Route, queryparams } from 'f2e-server3'
export const app_base = {
name: 'app_base',
mode: ['dev', 'prod'],
execute: (conf) => {
const route = new Route(conf)
// 基础 JSON API
route.on('api/time', async (body, ctx) => {
const data = queryparams(ctx.location.search)
return {
data,
post: body,
time: Date.now()
}
})
// 支持正则表达式路径
route.on(/^auth\/user\/(\d+)$/, async (body, ctx) => {
const userId = ctx.pathname.match(/^auth\/user\/(\d+)$/)[1]
return { userId, authenticated: true }
})
return { onRoute: route.execute }
}
}
```
##### 方式2: 使用 addRoute 函数
```javascript
import { addRoute, queryparams } from 'f2e-server3'
// 全局路由注册
addRoute('api/status', async (body, ctx) => {
return {
status: 'ok',
timestamp: Date.now(),
query: queryparams(ctx.location.search)
}
})
```
##### 方式3: 装饰器方式
```javascript
import { RouterDecorator, RouterContext } from 'f2e-server3'
class UserAPI {
/**
* 获取用户信息
* @demo /api/user/123/profile
*/
@RouterDecorator('api/user/:id/profile')
getUserProfile(body: any, ctx: RouterContext<'id'>) {
return {
userId: ctx.params.id,
profile: { name: 'John Doe', email: 'john@example.com' }
}
}
/**
* JSONP 接口
* @demo /api/user/123?callback=jQuery123456789
*/
@RouterDecorator('api/user/:id', { type: 'jsonp' })
getUserJSONP(body: any, ctx: RouterContext<'id'>) {
return { userId: ctx.params.id, name: 'John Doe' }
}
}
```
#### 7.3 响应类型
路由系统支持多种响应类型,通过 `type` 属性配置:
```javascript
// JSON 响应 (默认)
route.on('api/data', handler, { type: 'json' })
// JSONP 响应,支持 callback 参数
route.on('api/data.js', handler, { type: 'jsonp' })
// Server-Sent Events,支持实时推送
route.on('sse/events', handler, {
type: 'sse',
interval: 1000, // 轮询间隔 (ms)
interval_beat: 30000, // 心跳间隔 (ms)
default_content: 'ping' // 心跳数据
})
// 原始响应,自动设置 MIME 类型
route.on('api/file.txt', handler, {
type: 'raw',
sourceType: 'txt' // 文件后缀,自动设置 Content-Type
})
// 自定义响应处理
route.on('api/custom', handler, { type: 'none' })
```
#### 7.4 路由过滤器
支持路由级别的过滤和路径重写:
```javascript
import { Route } from 'f2e-server3'
const route = new Route(conf, async (pathname, ctx) => {
// 权限检查
if (pathname.startsWith('/admin') && !ctx.user?.isAdmin) {
ctx.resp.writeHead(403, { 'Content-Type': 'text/plain' })
ctx.resp.end('Access Denied')
return false // 阻止继续处理
}
// 路径重写
if (pathname.startsWith('/legacy')) {
return pathname.replace('/legacy', '/api/v1') // 重写路径
}
// 正常处理
return undefined
})
```
#### 7.5 中间件集成
路由系统可以轻松集成到中间件中:
```javascript
export const api_middleware = {
name: 'api',
mode: ['dev', 'prod'],
execute: (conf) => {
const route = new Route(conf)
// 注册各种 API 路由
route.on('api/users', userHandler)
route.on('api/posts', postHandler)
route.on('api/comments', commentHandler)
return {
onRoute: route.execute
}
}
}
```
#### 7.6 完整示例
```javascript
import { Route, addRoute, RouterDecorator, RouterContext } from 'f2e-server3'
// 全局路由
addRoute('api/health', async () => ({ status: 'ok' }))
// 装饰器路由
class BlogAPI {
@RouterDecorator('api/posts/:id')
getPost(body: any, ctx: RouterContext<'id'>) {
return { postId: ctx.params.id, title: 'Sample Post' }
}
}
// 中间件路由
export const blog_middleware = {
name: 'blog',
mode: ['dev', 'prod'],
execute: (conf) => {
const route = new Route(conf)
// SSE 实时更新
route.on('sse/blog-updates', async (body, ctx) => {
return { message: 'New blog post available!' }
}, { type: 'sse', interval: 5000 })
// 文件上传处理
route.on('api/upload', async (body, ctx) => {
// 处理文件上传逻辑
return { success: true, filename: 'uploaded.jpg' }
}, { type: 'none' })
return { onRoute: route.execute }
}
}
```
#### 7.7 最佳实践
##### 路由组织
```javascript
// 按功能模块组织路由
export const user_routes = {
name: 'user',
mode: ['dev', 'prod'],
execute: (conf) => {
const route = new Route(conf)
// 用户认证相关
route.on('api/auth/login', authHandler.login)
route.on('api/auth/logout', authHandler.logout)
route.on('api/auth/register', authHandler.register)
// 用户信息相关
route.on('api/user/profile', userHandler.getProfile)
route.on('api/user/profile', userHandler.updateProfile, { method: 'POST' })
return { onRoute: route.execute }
}
}
```
##### 错误处理
```javascript
route.on('api/data', async (body, ctx) => {
try {
const result = await processData(body)
return { success: true, data: result }
} catch (error) {
// 记录错误日志
logger.error('API Error:', error)
// 返回错误信息
ctx.resp.writeHead(500, { 'Content-Type': 'application/json' })
ctx.resp.end(JSON.stringify({
success: false,
error: error.message
}))
return false // 阻止默认响应处理
}
})
```
### 8. 路径别名
资源路径映射:
```javascript
{
alias: {
// 本地资源
'css/reset.css': 'node_modules/antd/dist/reset.css',
// 远程资源
'highlight/highlight.js': 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/highlight.min.js',
// 自定义请求头
'highlight/highlight.css': {
url: 'https://cdnjs.cloudflare.com/ajax/libs/highlight.js/11.9.0/styles/github.min.css',
options: {
headers: { Referer: 'https://cdnjs.cloudflare.com' }
}
}
}
}
```
### 9. 文件包含
HTML 模板包含功能:
```html
<!-- 在 HTML 中使用 -->
<f2e:include src="./header.htm" />
```
```javascript
{
include: {
entryPoints: ['index.html'],
recursive: true
}
}
```
### 10. 默认首页
类似 Nginx 的 try_files 功能:
```javascript
{
try_files: [
// 重定向
{ test: /redirect/, location: '/package.json' },
// 条件首页
{
test: /^profile/,
match: (pathname, ctx) => {
return /^profile/.test(pathname) &&
ctx.location.searchParams.get('toindex') != 'false'
},
index: 'profile.html'
},
// 默认首页
'index.html'
]
}
```
## 🏗️ 中间件开发
### 中间件接口
```javascript
{
middlewares: [
{
// 支持的模式
mode: ['dev', 'build', 'prod'],
// 中间件名称
name: 'myapp',
// 执行函数
execute: async (conf) => {
return {
// Pipeline 事件处理函数
onSet, onGet, onRoute, onMemoryInit, onMemoryLoad,
beforeRoute, buildWatcher, buildFilter, watchFilter, outputFilter
}
}
}
]
}
```
### 在中间件中获取登录账户信息
F2E-Server 3.0 提供了身份认证系统,中间件可以通过 `createAuthHelper` 函数轻松获取当前登录用户的信息。
#### 使用认证辅助函数
`createAuthHelper` 是获取登录用户信息的推荐方式,它封装了复杂的认证逻辑,使用简单且安全:
```javascript
import { createAuthHelper } from 'f2e-server3'
export const protected_middleware = {
name: 'protected',
mode: ['dev', 'prod'],
execute: (conf) => {
// 创建认证辅助函数实例
const authHelper = createAuthHelper(conf.auth)
const route = new Route(conf)
// 受保护的 API 路由
route.on('api/user/profile', async (body, ctx) => {
// 获取当前登录用户信息
const loginInfo = authHelper.getLoginUser(ctx)
if (!loginInfo || !loginInfo.user) {
return {
success: false,
error: '未登录或登录已过期,请重新登录'
}
}
return {
success: true,
data: {
username: loginInfo.user.username,
nickname: loginInfo.user.nickname,
lastVisit: loginInfo.last_url,
loginTime: new Date(loginInfo.expire - 24 * 60 * 60 * 1000).toISOString()
}
}
})
// 管理员专用接口
route.on('api/admin/users', async (body, ctx) => {
const loginInfo = authHelper.getLoginUser(ctx)
if (!loginInfo?.user) {
return { error: '请先登录' }
}
// 检查用户权限(这里可以扩展权限系统)
if (loginInfo.user.username !== 'admin') {
return { error: '权限不足,需要管理员权限' }
}
return {
success: true,
message: '获取用户列表成功',
admin: loginInfo.user.username
}
})
return { onRoute: route.execute }
}
}
```
### 中间件链式调用
```javascript
// 创建多个中间件,按顺序执行
const middlewares = [
auth_middleware, // 认证中间件
rate_limit_middleware, // 限流中间件
user_routes, // 用户路由
blog_routes, // 博客路由
error_handler // 错误处理中间件
]
createServer({
// ... 其他配置
middlewares
})
```
### Pipeline 事件流程
1. **构建流程**: `onMemoryInit` → `buildFilter` → `onSet` → `onMemoryLoad` → `outputFilter` → `onGet`
1. `onMemoryInit` 执行后开启资源编译,先递归的检索目录下所有资源
2. `buildFilter` 过滤需要构建的文件或目录,减少不必要的资源编译
3. `onSet` 根据文件路径和内容生成编译结果信息存入内存,主要编译工作在这里完成
4. `onMemoryLoad` 资源编译完成后执行
5. `outputFilter` 根据过滤条件进行过滤输出
6. `onGet` 正式输出前执行
2. **监听流程**: `watchFilter` → `buildWatcher`
1. 开启资源监听
2. `watchFilter` 过滤需要监听的文件或目录,如果监听到有效修改触发一套编译流程
3. `buildWatcher` 一套编译流程完成后触发
3. **请求流程**: `beforeRoute` → `onRoute` → `onGet`
1. `beforeRoute` 请求到达后最开始执行
2. `onRoute` 处理完成前置操作(如:POST请求数据接收完成)后执行
3. `onGet` 如果 `onRoute` 执行完成匹配对应资源,则将执行 `onGet` 通过http响应输出资源
## 📚 示例项目
### React 应用
- [f2e-react-app](https://gitee.com/f2e-server/f2e-react-app) - 基于 esbuild 的 React 单页应用
### Vue 应用
- [f2e-app-vue3](https://gitee.com/f2e-server/f2e-app-vue3) - Vue3 模板应用
## 🔧 开发环境
### 系统要求
- Node.js >= 18.0.0
- TypeScript >= 5.4.5
- 支持 Bun、Deno 运行时(可选)
### 开发依赖
```bash
# 核心依赖
npm install -D esbuild less postcss
# 可选依赖
npm install -D chokidar uWebSockets.js
# Tailwind CSS
npm install -D tailwindcss @tailwindcss/postcss
```
### 本地开发
```bash
# 克隆项目
git clone https://gitee.com/f2e-server/f2e-server-3.git
cd f2e-server-3
# 安装依赖
npm install
# 运行测试
npm test
# 构建项目
npm run build
```
## 📖 API 参考
### 主要接口
[src/index.ts](src/index.ts)
- `createServer(options)`: 创建并启动服务器
- `createBuilder(options)`: 仅构建资源
### 配置接口
详细配置参考:[src/interface.ts](src/interface.ts)
## 🤝 贡献指南
1. Fork 项目
2. 创建特性分支 (`git checkout -b feature/AmazingFeature`)
3. 提交更改 (`git commit -m 'Add some AmazingFeature'`)
4. 推送到分支 (`git push origin feature/AmazingFeature`)
5. 打开 Pull Request
## 📄 许可证
本项目基于 [Apache License 2.0](LICENSE) 开源协议。
## 🙏 致谢
感谢所有为这个项目做出贡献的开发者和用户!
---
**F2E-Server 3.0** - 让前端开发更简单、更高效!