f2e-server3
v1.13.10
Published
f2e-server 3.0
Readme
F2E-Server 3.0
基于 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 压缩、缓存控制、流式传输
📦 安装
全局安装(推荐)
npm install f2e-server3 -g项目依赖安装
npm install f2e-server3 --save-dev🚀 快速开始
方式一:使用 CLI 工具(推荐)
# 创建新项目
npx f2e-server3 create my-app
cd my-app
npm install
npm run dev方式二:手动配置
创建启动文件 start.mjs:
// @ts-check
import { createServer, logger } from 'f2e-server3'
// 设置日志级别
logger.setLevel('DEBUG')
// 启动服务器
createServer({
mode: 'dev',
port: 2850,
livereload: true
})启动服务器:
# 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 | 生产模式 | 仅启动服务器,开启缓存 |
createServer({ mode: 'dev' })基础配置
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)
自动监听文件变化并刷新浏览器:
{
livereload: {
// 注入热更新脚本的文件类型
reg_inject: /\.(html|md)$/,
// 心跳超时时间
heartBeatTimeout: 100000
}
}支持环境:
- Windows: 默认使用 Node.js API,安装
chokidar后自动升级 - 其他系统: 需要安装
chokidar - Deno: 使用内置 API
2. ESBuild 构建
现代化的 JavaScript 构建工具:
{
esbuild: {
// 配置文件路径
esbuildrc: './.esbuildrc.js',
// 构建外部依赖
build_external: true,
// esbuild 构建选项,会合并到 .esbuildrc.js 中每个配置项
esbuildOptions: {
minify: true,
sourcemap: true,
// 更多 esbuild 选项...
}
}
}配置说明:
esbuildOptions: 可选的 esbuild 构建选项,这些选项会合并到.esbuildrc.js配置文件中定义的每个构建配置项中,方便统一设置全局构建选项(如minify、sourcemap等)
热模块更新:
// .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 预处理器支持:
{
less: {
entryPoints: [
// 同路径输出
'css/style.less',
// 自定义输出路径
{ in: 'css/style2.less', out: 'static/bundle.css' }
]
}
}4. PostCSS 处理
CSS 后处理器,支持 Tailwind CSS:
import TailwindPlugin from '@tailwindcss/postcss'
{
postcss: {
entryPoints: {
in: 'css/main.css',
out: 'static/main.css'
},
plugins: [
TailwindPlugin({
optimize: mode === 'build'
})
]
}
}5. HTTP 代理
支持 API 转发和站点下载:
{
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. 身份认证
内置登录系统:
import { UserStore } from 'f2e-server3'
{
auth: {
redirect: true,
white_list?: [
"^publish"
];
store: new UserStore('.f2e_cache/auth.db')
}
}更多配置参考 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 类
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 函数
import { addRoute, queryparams } from 'f2e-server3'
// 全局路由注册
addRoute('api/status', async (body, ctx) => {
return {
status: 'ok',
timestamp: Date.now(),
query: queryparams(ctx.location.search)
}
})方式3: 装饰器方式
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: '[email protected]' }
}
}
/**
* 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 属性配置:
// 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 路由过滤器
支持路由级别的过滤和路径重写:
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 中间件集成
路由系统可以轻松集成到中间件中:
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 完整示例
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 最佳实践
路由组织
// 按功能模块组织路由
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 }
}
}错误处理
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. 路径别名
资源路径映射,支持文件和目录别名(from v1.13.3-alpha):
{
alias: {
// 本地文件
'css/reset.css': 'node_modules/antd/dist/reset.css',
// 本地目录(递归复制所有文件)
'assets/images/': 'src/images/**',
'lib/': 'node_modules/lodash/**',
// 远程资源
'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' }
}
}
}
}别名类型说明:
- 文件别名: 直接映射单个文件
- 目录别名: 使用
/**后缀,递归复制目录下所有文件 - 远程资源: 支持 HTTP/HTTPS 协议,自动下载并缓存
- 自定义选项: 支持自定义请求头等HTTP选项
9. 文件包含
HTML 模板包含功能:
<!-- 在 HTML 中使用 -->
<f2e:include src="./header.htm" />{
include: {
entryPoints: ['index.html'],
recursive: true
}
}10. 默认首页
类似 Nginx 的 try_files 功能:
{
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'
]
}🏗️ 中间件开发
中间件接口
{
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 是获取登录用户信息的推荐方式,它封装了复杂的认证逻辑,使用简单且安全:
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 }
}
}中间件链式调用
// 创建多个中间件,按顺序执行
const middlewares = [
auth_middleware, // 认证中间件
rate_limit_middleware, // 限流中间件
user_routes, // 用户路由
blog_routes, // 博客路由
error_handler // 错误处理中间件
]
createServer({
// ... 其他配置
middlewares
})Pipeline 事件流程
- 构建流程:
onMemoryInit→buildFilter→onSet→onMemoryLoad→outputFilter→onGetonMemoryInit执行后开启资源编译,先递归的检索目录下所有资源buildFilter过滤需要构建的文件或目录,减少不必要的资源编译onSet根据文件路径和内容生成编译结果信息存入内存,主要编译工作在这里完成onMemoryLoad资源编译完成后执行outputFilter根据过滤条件进行过滤输出onGet正式输出前执行
- 监听流程:
watchFilter→buildWatcher- 开启资源监听
watchFilter过滤需要监听的文件或目录,如果监听到有效修改触发一套编译流程buildWatcher一套编译流程完成后触发
- 请求流程:
beforeRoute→onRoute→onGetbeforeRoute请求到达后最开始执行onRoute处理完成前置操作(如:POST请求数据接收完成)后执行onGet如果onRoute执行完成匹配对应资源,则将执行onGet通过http响应输出资源
📚 示例项目
推荐
React 应用 create 命令使用模板,长期维护
- f2e-create-template - 基于 esbuild 的 React 基础应用
Vue 应用 简单vue构建模板,不定期维护
- f2e-app-vue3 - Vue3 模板应用
🔧 开发环境
系统要求
- Node.js >= 18.0.0
- TypeScript >= 5.4.5
- 支持 Bun、Deno 运行时(可选)
开发依赖
# 核心依赖
npm install -D esbuild less postcss
# 可选依赖
npm install -D chokidar uWebSockets.js
# Tailwind CSS
npm install -D tailwindcss @tailwindcss/postcss本地开发
# 克隆项目
git clone https://gitee.com/f2e-server/f2e-server-3.git
cd f2e-server-3
# 安装依赖
npm install
# 运行测试
npm test
# 构建项目
npm run build📖 API 参考
主要接口
createServer(options): 创建并启动服务器createBuilder(options): 仅构建资源
配置接口
详细配置参考:src/interface.ts
🤝 贡献指南
- Fork 项目
- 创建特性分支 (
git checkout -b feature/AmazingFeature) - 提交更改 (
git commit -m 'Add some AmazingFeature') - 推送到分支 (
git push origin feature/AmazingFeature) - 打开 Pull Request
📄 许可证
本项目基于 Apache License 2.0 开源协议。
🙏 致谢
感谢所有为这个项目做出贡献的开发者和用户!
F2E-Server 3.0 - 让前端开发更简单、更高效!
