# Chanjs **Repository Path**: chancms/Chanjs ## Basic Information - **Project Name**: Chanjs - **Description**: Chan.js 基于express 纯js研发的轻量级mvc框架。基于函数式编程思想,流程清晰,代码易读,可持续维护高。 - **Primary Language**: NodeJS - **License**: Apache-2.0 - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 11 - **Forks**: 11 - **Created**: 2024-01-06 - **Last Updated**: 2026-03-22 ## Categories & Tags **Categories**: webframework **Tags**: None ## README # Chanjs Chanjs 是一个基于 Express 5+ 构建的轻量级 MVC 框架,完全使用 JavaScript 开发。它体现了函数式编程的概念,提供了卓越的性能、清晰的代码和易于遵循的过程,确保了高可维护性。 ## 特点 - **核心架构** - 基于 Express 5+ 构建 - 支持 ES6+ 语法 - 轻量级设计(核心代码精简高效) - **模块化设计** - 多模块化路由(支持模块独立路由) - 模块化 views(模板文件模块化) - 模块化 controllers(控制器模块化) - 模块化 services(服务层模块化) - 模块化 middleware(模块级中间件) - **插件式架构** - 支持插件扩展 - 插件独立 MVC 结构 - 热插拔式插件管理 - **数据库支持** - 多数据库支持(PostgreSQL、MySQL/MariaDB、SQLite3、Oracle、MSSQL) - 数据库连接池管理 - Knex 查询构建器 - 事务支持 - 日期字段自动格式化 - **安全防护** - WAF(Web应用防火墙) - XSS 防护 - 关键词过滤 - 访问限流(Rate Limiting) - 路径白名单 - Cookie 安全处理 - **中间件生态** - CORS 跨域配置 - 请求体解析 - Cookie 处理 - 静态资源管理 - 日志记录 - 模板引擎(Art-template) - **高级特性** - 依赖注入(DI,基于 Map 实现) - 面向切面编程(AOP,支持 before/after/error 切面) - 事件系统(基于 EventEmitter) - 自动控制器加载(loadController) - **开发体验** - 缓存支持(内存缓存) - 统一响应格式 - 全局错误处理(404/500) - 分页查询封装 - 配置文件管理 - 环境变量支持(.env.dev/.env.prd) - **工具函数** - 时间格式化 - 文件操作 - 路径处理 - 树形结构转换 - 代码生成 - 过滤器 ## 约定优于配置 ```code |- app |- common |- helper |- middleware |- modules |- module1 |- controller |- service |- middleware |- router.js |- module2 |- controller |- service |- router.js |- plugins |- plugin1 |- controller |- router.js |- router.js |- config |- data |- doc |- public |- view |- app.js |-.env.dev |-.env.prd |- pm2.json |- package.json ``` ## 初始化过程 ```mermaid graph TD A[初始化] --> B[加载配置] B --> C[加载数据库] C --> D[加载扩展] D --> E[加载中间件] E --> F[设置应用配置] F --> G[加载模块路由] G --> H[加载公共路由] H --> I[应用路由] I --> J[设置错误处理] J --> K[beforeStart钩子] K --> L[run启动服务器] G --> G1[加载服务] G --> G2[加载控制器] G --> G3[加载路由] D --> D1[加载common] D --> D2[加载helper] D --> D3[加载extend] ``` ## 核心功能 ### 1. 依赖注入(DI) Chanjs 提供了轻量级的依赖注入容器,支持 Service 和 Controller 的自动加载。 #### 使用方式 ```javascript import { Service, Controller } from "chanjs"; class UserService extends Service { constructor() { super("user"); } async getUserWithArticles(userId) { const user = await this.findById(userId); // 从依赖注入容器中获取 ArticleService 实例 const articleService = await this.get("article", "Article"); const articles = await articleService.findByUserId(userId); return { user, articles }; } } class UserController extends Controller { constructor() { super(); } async getUser(req, res, next) { try { const { id } = req.params; // 从依赖注入容器中获取 UserService 实例 const userService = await this.get("user", "User"); const result = await userService.findById(id); res.json(this.success({ data: result.data })); } catch (err) { next(err); } } } ``` ### 2. 面向切面编程(AOP) Chanjs 提供了 AOP(面向切面编程)支持,可以在方法执行前后添加切面逻辑。 #### 支持的切面类型 - `before` - 方法执行前 - `after` - 方法执行后 - `error` - 方法执行异常时 #### 使用方式 ```javascript import { aop } from "chanjs"; // 注册切面函数 aop.set("logBefore", async ({ ctx, methodName, args }) => { console.log(`[Before] ${methodName} 被调用,参数:`, args); }); aop.set("logAfter", async ({ ctx, methodName, result }) => { console.log(`[After] ${methodName} 执行完成,结果:`, result); }); aop.set("logError", async ({ ctx, methodName, error }) => { console.error(`[Error] ${methodName} 执行失败:`, error); }); // 绑定切面到实例方法 const controller = new UserController(); aop.wrap(controller, { getUser: [ { type: "before", logBefore: true }, { type: "after", logAfter: true }, { type: "error", logError: true } ] }); // 调用方法时会自动执行切面 await controller.getUser(1); ``` #### 切面配置选项 ```javascript aop.wrap(instance, { methodName: [ { type: "before", enabled: true, customParam: "value" }, { type: "after", enabled: true }, { type: "error", enabled: false } ] }); ``` - `type` - 切面类型(before/after/error) - `enabled` - 是否启用该切面(默认 true) - 其他自定义参数会传递给切面函数 ### 3. 事件系统 Chanjs 提供了基于 Node.js EventEmitter 的事件系统,支持应用内的事件发布订阅。 #### 使用方式 ```javascript import { event } from "chanjs"; // 监听事件 event.on("user.login", (data) => { console.log("用户登录:", data); }); event.on("user.logout", (data) => { console.log("用户退出:", data); }); // 触发事件 event.emit("user.login", { userId: 1, username: "admin" }); // 移除监听器 event.off("user.login", listener); // 移除所有监听器 event.removeAllListeners("user.login"); ``` ### 4. 自动加载控制器 Chanjs 提供了 `loadController` 辅助函数,可以自动加载指定模块下的所有控制器。 #### 使用方式 ```javascript import { helper } from "chanjs"; // 加载 member 模块下的所有控制器 const controller = await helper.loadController("member"); // 使用控制器 controller.Member.getUser(); controller.Comment.getComments(); controller.Favorite.getFavorites(); ``` #### 目录结构 ``` member/ controller/ Member.js Comment.js Favorite.js service/ Member.js Comment.js Favorite.js router.js ``` `loadController("member")` 会自动加载 `member/controller/` 目录下的所有文件,并返回一个对象: ```javascript { Member: MemberController实例, Comment: CommentController实例, Favorite: FavoriteController实例 } ``` ## 运行 ```javascript import Chanjs from "chanjs"; const chan = new Chanjs(); // 前置钩子 chan.beforeStart(fn); // 开始加载 await chan.start(); // 启动服务器 chan.run((port) => { console.log(`ChanCMS is running on ${port}`); }); ``` ## 完整示例 ```javascript import Chanjs from "chanjs"; import { aop, event } from "chanjs"; const app = new Chanjs(); // 注册切面 aop.set("logBefore", async ({ ctx, methodName, args }) => { console.log(`[Before] ${methodName} 被调用`); }); // 监听事件 event.on("app.start", () => { console.log("应用启动"); }); // 启动应用 await app.start(); // 运行 app.run((port) => { event.emit("app.start", { port }); console.log(`Server running on port ${port}`); }); ``` 该框架专为寻求简单与功能之间平衡的开发者设计,为构建 Web 应用程序提供了一个强大的基础。