npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2025 – Pkg Stats / Ryan Hefner

mm_machine

v2.1.1

Published

这是超级美眉框架机制构建辅助模块,用于快速构建一个机制,支持动态加载、热更新、模块管理等功能,并具有增强的错误处理和现代JavaScript特性支持。

Readme

mm_machine

一个灵活的Node.js插件化机制系统,用于动态加载、管理和执行模块。

快速开始

安装

npm install mm_machine --save

目录结构

推荐的项目结构:

my_project/
├── index.js           # 主应用入口
├── app/               # 默认模块目录
│   ├── module1/       # 模块1
│   │   ├── config_demo.json  # 配置文件 (注意命名规则)
│   │   └── index.js          # 模块实现
│   └── module2/       # 模块2
│       ├── config_demo.json  # 配置文件
│       └── main.js           # 模块实现 (可以使用index.js或main.js)
└── package.json

使用示例

const $ = require('mm_expand');
const Machine = require('mm_machine');

// 创建引擎实例
const engine = new Machine();

// 初始化并加载模块
async function init() {
    // 更新配置(可选)
    engine.update_config_all({
        searchPath: './app/'  // 默认路径,可自定义
    });
    
    // 加载所有模块
    await engine.loads();
    
    // 执行所有模块的main方法
    const results = await engine.execute('main');
    $.log.debug('执行结果:', results);
    
    // 获取特定模块
    const demo1 = engine.get('demo1');
    if (demo1) {
        $.log.debug('找到模块:', demo1.name);
    }
    
    $.log.debug(`已加载 ${engine.list.length} 个模块`);
}

// 启动应用
init().catch(err => {
    $.log.error('初始化失败:', err);
});

创建模块

1. 创建配置文件

在模块目录中创建 config_demo.json 文件(注意命名规则):

{
    "name": "demo1",
    "title": "测试模块1",
    "description": "这是第一个测试模块",
    "sort": 10,
    "state": 1,
    "show": 1,
    "config": {
        "debug": true,
        "timeout": 3000
    }
}

2. 创建模块实现

在同一目录中创建 index.jsmain.js 文件:

const $ = require('mm_expand');

/**
 * 主方法
 */
async function main() {
    $.log.info(`[${this.name}] 测试模块执行`);
    
    // 访问模块配置
    const debug = this.config.debug;
    if (debug) {
        $.log.debug(`[${this.name}] 调试模式已启用`);
    }
    
    return {
        success: true,
        message: `${this.name} 执行成功`
    };
}

// 导出方法
module.exports = {
    main
};

重要:文件命名规则

配置文件必须按照以下格式命名:

config_{type}.json

其中{type}必须与您在Engine类中设置的this.type属性值完全匹配。例如:

  • 如果this.type = "demo",配置文件必须命名为config_demo.json
  • 如果this.type = "plugin",配置文件必须命名为config_plugin.json

完整使用示例

示例1:创建和管理基础模块

以下是一个完整的示例,展示如何创建和管理基础模块:

1. 项目结构

my_project/
├── index.js           # 主应用入口
├── app/               # 模块目录
│   ├── demo1/         # 模块1
│   │   ├── config_demo.json  # 模块配置文件
│   │   └── index.js          # 模块实现
│   └── demo2/         # 模块2
│       ├── config_demo.json  # 模块配置文件
│       └── main.js           # 模块实现
└── package.json

2. 主应用入口 (index.js)

const $ = require('mm_expand');
const Machine = require('mm_machine');

// 创建引擎实例
const engine = new Machine();

// 初始化引擎
async function init() {
    // 加载模块
    await engine.loads();
    
    // 执行所有模块的main方法
    await engine.execute('main');
    
    // 获取特定模块
    const demo1 = engine.get('demo1');
    if (demo1) {
        $.log.debug('模块1状态:', demo1.state ? '启用' : '禁用');
        
        // 执行特定模块的自定义方法
        const result = await engine.execute('my_custom_method', 'demo1');
        $.log.debug('自定义方法结果:', result);
    }
    
    // 监听文件变化(热更新模式)
    engine.mode = 2;
    engine.watch();
    
    $.log.debug(`已加载 ${engine.list.length} 个模块`);
}

// 启动应用
init().catch(err => {
    $.log.error('初始化失败:', err);
});

3. 模块配置文件示例 (app/demo1/config_demo.json)

{
    "name": "demo1",
    "title": "测试模块1",
    "description": "这是第一个测试模块",
    "sort": 10,
    "state": 1,
    "show": 1,
    "config": {
        "debug": true,
        "timeout": 3000,
        "api_key": "your_api_key_here"
    }
}

4. 模块实现示例 (app/demo1/index.js)

const $ = require('mm_expand');

// 模块状态变量
let counter = 0;

/**
 * 初始化方法
 */
async function init() {
    $.log.info(`[${this.name}] 模块初始化中...`);
    counter = 0;
    return true;
}

/**
 * 加载方法
 */
async function load() {
    $.log.info(`[${this.name}] 模块加载中...`);
    // 可以在这里执行加载资源等操作
    return true;
}

/**
 * 主方法
 * @param {Object} params - 传入参数
 */
async function main(params = {}) {
    $.log.info(`[${this.name}] 主方法执行,当前计数: ${counter++}`);
    
    // 访问模块配置
    const debug = this.config.debug;
    if (debug) {
        $.log.debug(`[${this.name}] 调试模式已启用`);
    }
    
    // 返回结果
    return {
        success: true,
        message: `${this.name} 执行成功`,
        count: counter,
        params: params
    };
}

/**
 * 主方法执行前钩子
 */
async function main_before() {
    $.log.info(`[${this.name}] 主方法执行前处理`);
    return true;
}

/**
 * 主方法执行后钩子
 */
async function main_after(result) {
    $.log.info(`[${this.name}] 主方法执行后处理,结果:`, result);
    return result;
}

/**
 * 自定义方法
 */
async function my_custom_method() {
    return {
        custom: "这是一个自定义方法",
        module_name: this.name
    };
}

// 导出方法
module.exports = {
    init,
    load,
    main,
    main_before,
    main_after,
    my_custom_method
};

示例2:使用自定义模块目录

如果需要使用非默认的模块目录,可以按以下方式配置:

const engine = new Machine();

// 使用自定义目录
engine.update_config_all({
    searchPath: './custom_modules/'
});

// 然后加载模块
await engine.loads();

示例3:实现热更新和动态管理

以下示例展示如何实现模块的热更新和动态管理:

const engine = new Machine();

// 设置为热更新模式
engine.mode = 2;

// 初始化
async function setup() {
    // 加载模块
    await engine.loads();
    
    // 开始监听文件变化
    engine.watch();
    
    // 定时检查模块数量
    setInterval(async () => {
        $.log.debug(`当前模块数量: ${engine.list.length}`);
    }, 5000);
    
    // 模拟动态管理模块
    setTimeout(async () => {
        // 重载特定模块
        await engine.reload('demo1');
        $.log.debug('已重载模块 demo1');
    }, 10000);
    
    setTimeout(async () => {
        // 卸载模块
        await engine.unload('demo2');
        $.log.debug('已卸载模块 demo2');
    }, 20000);
}

setup().catch($.log.error);

示例4:错误处理和异常捕获

const engine = new Machine();

async function run() {
    try {
        // 加载模块并捕获可能的错误
        await engine.loads();
        
        // 安全地执行模块方法
        try {
            const result = await engine.execute('main');
            $.log.debug('执行结果:', result);
        } catch (err) {
            $.log.error('执行方法时出错:', err);
            // 继续执行,不会中断整个应用
        }
        
        // 单独执行特定模块并捕获可能的错误
        try {
            const demo1Result = await engine.execute('main', 'demo1');
            $.log.debug('demo1 执行结果:', demo1Result);
        } catch (err) {
            $.log.error('执行 demo1 时出错:', err);
        }
    } catch (err) {
        $.log.error('初始化失败:', err);
    }
}

run();

高级功能

模块生命周期

每个模块支持完整的生命周期方法:

  • init: 模块初始化时调用
  • load: 模块加载时调用
  • main: 主执行方法
  • main_before: 主方法执行前的钩子
  • main_after: 主方法执行后的钩子

运行模式说明

系统支持4种运行模式,可通过mode属性设置:

  1. 生产模式 (mode = 1): 最高性能,文件改变不会触发重新加载
  2. 热更新模式 (mode = 2): 文件改变时自动重新加载配置和代码
  3. 重载模式 (mode = 3): 执行完后重新加载脚本,避免变量污染
  4. 热更新+重载模式 (mode = 4): 结合热更新和重载的特性

模块管理API

// 重载特定模块
await engine.reload("moduleName");

// 卸载模块(保留文件)
await engine.unload("moduleName");

// 卸载并删除模块文件
await engine.unload("moduleName", true);

// 保存模块配置
await engine.save();

// 获取特定模块
const module = engine.get("moduleName");

路径处理

  • 所有相对路径都会基于模块的目录进行解析
  • 使用fullname()方法可以获取绝对路径,避免路径问题

常见问题与故障排除

1. 模块无法加载

检查项目:

  • 确认配置文件命名格式正确 (config_{type}.json)
  • 确认type属性与配置文件前缀匹配
  • 检查模块的state配置是否为1(启用)
  • 检查文件权限是否正确

2. 热更新不工作

检查项目:

  • 确认mode设置为2或4(热更新模式)
  • 确认文件确实被修改了(注意编辑器的保存设置)
  • 检查文件路径是否正确

3. 执行方法返回null

检查项目:

  • 确认模块已正确加载 (engine.list.length > 0)
  • 确认方法名拼写正确
  • 检查模块实现中是否正确导出了该方法
  • 检查模块的state是否为1(启用状态)

4. 路径错误

解决方案:

  • 使用绝对路径或确保相对路径正确
  • 利用__dirnamefullname()方法构建可靠的路径

模块系统设计理念与工作流程

设计理念

mm_machine 模块系统基于以下核心设计理念:

  1. 高内聚、低耦合:每个模块独立封装功能,通过明确的接口与其他模块交互
  2. 可插拔架构:模块可以动态加载、卸载,不影响系统整体运行
  3. 配置驱动:通过配置文件控制模块行为,无需修改代码
  4. 生命周期管理:提供完整的模块生命周期钩子,便于资源管理
  5. 热更新支持:无需重启应用即可更新模块功能

工作流程

以下是模块系统的基本工作流程:

初始化引擎 → 扫描模块目录 → 解析配置文件 → 加载模块代码 → 初始化模块 → 执行方法 → 监听文件变化(热更新模式)

详细工作流程说明:

  1. 初始化引擎:创建 Machine 实例,设置配置项
  2. 扫描模块目录:根据 searchPath 扫描目录,查找 config_{type}.json 文件
  3. 解析配置文件:读取并解析配置,验证模块状态
  4. 加载模块代码:根据配置中的信息,动态加载模块的实现文件
  5. 初始化模块:按排序顺序初始化模块,执行 init 和 load 方法
  6. 执行方法:根据应用需求,执行模块的特定方法(如 main)
  7. 监听文件变化:在热更新模式下,监听文件变化并自动重新加载模块

数据流向

模块间的数据流转遵循以下规则:

  1. 引擎将调用参数传递给模块方法
  2. 模块方法处理后返回结果
  3. 钩子方法可以拦截和修改输入/输出数据
  4. 模块可以访问自己的配置,但不能直接访问其他模块的数据

最佳实践与开发建议

模块设计最佳实践

  1. 单一职责原则:每个模块应专注于单一功能领域
  2. 接口一致性:遵循模块生命周期接口约定,确保兼容性
  3. 错误处理:在模块内部实现完善的错误处理机制
  4. 日志记录:使用统一的日志接口记录模块活动
  5. 资源管理:在适当的生命周期钩子中释放资源

配置管理建议

  1. 配置分层:将公共配置和模块特有配置分开
  2. 配置验证:在模块初始化时验证配置有效性
  3. 默认值处理:为重要配置项提供合理的默认值
  4. 敏感信息保护:避免在配置文件中直接存储敏感信息

性能优化建议

  1. 懒加载:对于资源密集型模块,考虑实现懒加载机制
  2. 缓存策略:合理使用缓存减少重复计算
  3. 异步操作:使用 async/await 处理异步操作,避免阻塞
  4. 减少全局状态:尽量减少模块间的状态共享

调试技巧

  1. 日志级别:利用不同级别的日志(debug、info、error)辅助调试
  2. 热更新调试:使用热更新模式(mode=2)进行开发调试
  3. 模块隔离:出现问题时,尝试单独测试特定模块
  4. 配置检查:验证配置文件格式和内容是否正确

部署注意事项

  1. 生产环境模式:部署到生产环境时,设置 mode=1 以获得最佳性能
  2. 配置备份:定期备份模块配置文件
  3. 版本控制:对模块代码和配置进行版本控制
  4. 依赖管理:明确声明和管理模块依赖

贡献指南

如果您有兴趣为 mm_machine 项目贡献代码或改进,请遵循以下步骤:

  1. Fork 项目仓库
  2. 创建您的功能分支 (git checkout -b feature/amazing-feature)
  3. 提交您的更改 (git commit -m 'Add some amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 打开 Pull Request

更新日志

v1.0.0 (初始版本)

  • 基础模块管理功能
  • 配置文件加载和解析
  • 模块生命周期管理
  • 热更新支持
  • 基础错误处理

v1.1.0

  • 改进模块加载逻辑,支持自定义目录
  • 增强错误处理和异常捕获
  • 添加更多生命周期钩子
  • 优化性能和内存使用

依赖

  • mm_config: ^1.1.4
  • mm_hot_reload: ^1.0.5
  • mm_expand: 用于路径处理和文件操作

许可证

ISC

作者信息

本模块由 mm_modules 团队开发和维护。如有问题或建议,请联系我们。