UNPKG

mixone

Version:

MixOne is a Node scaffolding tool implemented based on Vite, used for compiling HTML5, JavasCript, Vue, React and other codes. It supports packaging Web applications with multiple HTML entry points (BS architecture) and desktop installation packages (CS a

369 lines (278 loc) 15 kB
<div align="center"> <img width="100" src="logo2.png" alt="MixOne logo"></a> # MixOne **🚀 一套代码,同时生成 Web(BS)多入口页面+桌面(CS)安装包,无需切换工具。** *让软件开发回归简单* [![npm version](https://img.shields.io/npm/v/mixone.svg)](https://www.npmjs.com/package/mixone) [![license](https://img.shields.io/npm/l/mixone.svg)](https://github.com/mixone/mixone/blob/main/LICENSE) [![downloads](https://img.shields.io/npm/dm/mixone.svg)](https://www.npmjs.com/package/mixone) [![stars](https://img.shields.io/github/stars/qew4/mixone-example.svg)](https://github.com/qew4/mixone-example) </div> --- ## ✨ 项目简介 MixOne是一个Node脚手架工具,基于Vite实现,用于编译HTML5、JavasCript,Vue,React等代码,支持打包多HTML入口的(BS架构)Web应用和打包(CS架构)桌面端安装包。桌面端的目前基于Electron实现,MixOne有自己的语法糖来访问Electron的API和NodeJS的功能,这种语法糖完全可以取代Electron的IPC通讯代码。 ### 🎯 核心特性 - **🎭 双模式+跨平台部署** - 独创 BS/CS 双模式,一套代码同时支持 Web打包 和 桌面应用构建。以前常听到的是跨平台,现在还要跨CS/BS模式。 - **🧠 语法糖代替IPC** - MinOne创建的项目以Main、NodeJS、PJS开始的语法可以访问原生功能。弱化主进程/渲染进程概念。保持vue、react原来的项目结构下使用。 - **🔒 源代码保护** - 编译为 V8 字节码以保护源代码。 - **⚡ 零配置启动** - 开箱即用,无需复杂配置 - **🔥 全栈热重载** - 主进程和渲染进程代码变更实时生效。 - **🔧 桌面多窗口管理** - 提供统一窗口管理类,提供窗口创建、关闭、通讯等方案。支持子模态窗口。自适应浏览器和桌面环境。 - **📱 多页面支持** - 多页面+SPA兼顾,可打包多HTML入口的web产物。 - **🛠️ 现代工具链** - 集成 Vite、支持 Vue/React/TypeScript。 ## 🌟 为什么选择 MixOne ### 🏗️ 基于成熟生态 - **继承 Electron 优势** - 完全兼容 Electron 生态系统 - **丰富的 NPM 生态** - 直接使用海量 Web 开发资源 - **跨平台支持** - Windows、macOS、Linux 全平台覆盖 ### 💡 开发体验革新 - **学习成本极低** - Web 开发者零门槛上手 - **开发效率提升** - 减少 80% 的样板代码 - **调试体验优化** - 控制台可视化日志,告别命令行调试 - **实时开发反馈** - 代码变更实时监听和应用,提升开发效率 ### 🚀 技术创新 - **智能进程通信** - 框架自动处理 IPC,开发者无感知 - **统一开发模式** - 一套技术栈解决 Web 和桌面应用开发需求 - **预加载脚本智能合并** - 自动创建和合并 preload.js ## 📊 技术对比 ### 🆚 MixOne vs 原生 Electron | 特性 | MixOne | 原生 Electron | |------|--------|---------------| | **学习曲线** | 🟢 低,去概念化设计 | 🟡 中等,需理解进程模型 | | **进程通信** | 🟢 框架自动处理 | 🔴 手动编写 IPC 代码 | | **系统API访问** | 🟢 任意位置直接调用 | 🟡 需要预加载脚本 | | **项目结构** | 🟢 精简直观 | 🟡 相对复杂 | | **热重载** | 🟢 主进程+渲染进程全覆盖 | 🟡 仅渲染进程 | | **多页面支持** | 🟢 原生支持 | 🟡 需要额外配置 | | **双端部署** | 🟢 一键切换 Web/Desktop | 🔴 不支持 | ### 🆚 MixOne vs Qt | 对比维度 | MixOne | Qt | |----------|--------|----| | **技术栈** | HTML5 + JavaScript | C++ (主要) | | **开发门槛** | 🟢 Web 开发者友好 | 🔴 需要 C++ 基础 | | **UI 开发** | 🟢 Web 技术,灵活度高 | 🟡 QML/Widget,学习成本高 | | **生态系统** | 🟢 NPM 生态丰富 | 🟡 相对封闭 | | **包体积** | 🟡 较大(61MB~) | 🟢 较小 | | **性能** | 🟡 Web 技术限制 | 🟢 原生性能 | ### 🆚 MixOne vs 其他 Electron 框架 <div align="center"> <img width="80%" src="new_old_grammer2.png" alt="语法对比图"> </div> | 核心特性 | MixOne | 其他 Electron 框架 | |----------|--------|--------------------| | **🎯 双端部署** | ✅ 独创 BS/CS 双模式 | ❌ 仅桌面应用 | | **🧠 学习成本** | ✅ 去IPC概念,零门槛 | 🔴 需理解进程模型 | | **🔧 系统API** | ✅ 任意位置直接调用 | 🟡 需 IPC 或预加载暴露 | | **🔥 热重载** | ✅ 主进程+渲染进程 | 🟡 仅渲染进程 | | **📱 多页面** | ✅ 多页面+SPA | 🟡 主要是 SPA | | **🖼️ 窗口管理** | ✅ 多窗口+子模态 | 🔴 主要是单窗口 | | **📊 调试体验** | ✅ 控制台可视化日志 | 🔴 命令行查看 | > **核心优势**:MixOne 真正实现了"去IPC概念化"设计,让开发者专注业务逻辑,无需关注底层实现细节。 ## 🚀 快速开始 ### 📦 安装 MixOne 需要Node版本在v20及以上的版本上安装。 ```bash # 全局安装 MixOne CLI npm install -g mixone ``` ### 🆕 创建新项目 ```bash # 创建项目 mixone create my-mixone-app cd my-mixone-app # 安装依赖 npm install # 启动开发服务器 npm run dev ``` > 🎉 **就是这么简单!** 你的 Web 应用现在已经具备了桌面应用的能力。 ## 📁 项目结构 - Vue为框架的目录结构。 ``` mixone-vue-app/ ├── 📂 assets/ # 🎨 全局静态资源 │ └── 📄 favicon.ico # 应用图标 ├── 📂 components/ # 🧩 全局组件库 │ ├── 📄 Button.vue # 按钮组件 │ └── 📄 Dialog.vue # 对话框组件 ├── 📂 windows/ # 🖼窗口目录(以 -window 结尾,windows是根窗口目录) │ ├── 📄 Index.page.vue # 主窗口入口页面组件 │ ├── 📂 other-window/ # 其他窗口 │ │ ├── 📄 Index.page.vue # 入口页面组件 │ │ ├── 📄 Second.page.vue # 页面组件(自动路由) │ │ ├── 📄 Second.vue # 普通组件 │ │ ├── 📄 preload.js # 窗口预加载脚本(可选) │ │ └── 📄 window.json # 窗口配置 │ └── 📂 setting-window/ # 设置窗口 │ ├── 📄 Index.page.vue # 入口页面组件 │ ├── 📄 main.ts # Vue 入口(可选) │ ├── 📄 App.vue # 顶层组件(可选) │ └── 📄 router.js # 路由配置(可选) ├── 📂 main/ # ⚡ 主进程代码 │ ├── 📄 main.js # 主进程入口 │ └── 📄 *.fn.js # 原生插件(PJS 访问) ├── 📂 utils/ # 🔧 工具函数 │ ├── 📄 request.js # 请求工具 │ └── 📄 common.js # 通用工具 ├── 📂 out/ # 📦 编译输出 └── 📄 package.json # 项目配置 ``` - React为框架的目录结构 ``` mixone-react-app/ ├── 📂 assets/ # 🎨 全局静态资源 │ └── 📄 favicon.ico # 应用图标 ├── 📂 components/ # 🧩 全局组件库 │ ├── 📄 Button.tsx # 按钮组件 │ └── 📄 Dialog.tsx # 对话框组件 ├── 📂 windows/ # 🖼窗口目录(以 -window 结尾,windows是根窗口目录) │ ├── 📄 Index.page.tsx # 主窗口入口页面组件 │ ├── 📂 other-window/ # 其他窗口 │ │ ├── 📄 Index.page.tsx # 入口页面组件 │ │ ├── 📄 Second.page.tsx # 页面组件(自动路由) │ │ ├── 📄 Second.tsx # 普通组件 │ │ ├── 📄 preload.js # 窗口预加载脚本(可选) │ │ └── 📄 window.json # 窗口配置 │ └── 📂 setting-window/ # 设置窗口 │ ├── 📄 Index.page.tsx # 入口页面组件 │ ├── 📄 main.tsx # React 入口(可选) │ ├── 📄 App.tsx # 顶层组件(可选) │ └── 📄 router.tsx # 路由配置(可选) ├── 📂 main/ # ⚡ 主进程代码 │ ├── 📄 main.js # 主进程入口 │ └── 📄 *.fn.js # 原生插件(PJS 访问) ├── 📂 utils/ # 🔧 工具函数 │ ├── 📄 request.tsx # 请求工具 │ └── 📄 common.tsx # 通用工具 ├── 📂 out/ # 📦 编译输出 └── 📄 package.json # 项目配置 ``` > 👍 迄今为止!!!开发Electron桌面 **项目结构** 最合理的工具,没有任何冗余目录。 ### 📋 根目录详解 | 目录/文件 | 说明 | 别名 | |-----------|------|------| | `windows/` | 🪟 窗口目录,以 `-window` 结尾的为窗口 | 以"@/windows"别名访问 | `components/` | 🧩 全局组件,所有窗口共享 | 以"@/components"别名访问 | `assets/` | 🎨 全局静态资源,所有窗口共享 | 以"@/assets"别名访问 | `main/` | ⚡ 主进程代码,应用启动入口 | 以"@/main"别名访问 | `utils/` | 🛠️ 工具函数,全局共享 | 以"@/utils"别名访问 | `store/` | 📦 全局状态存储,全局共享 | 以"@/store"别名访问 ### 每一个窗口目录详解(windows目录下以"-window"结尾的目录) | 文件 | 说明 | 是否可省略 | |-----------|------|------| | `*.page.vue(tsx)` | 📄 页面组件,自动加入路由 | 至少有Index.page.vue(tsx) | | `preload.js` | 🔗 窗口预加载脚本 | 可省略 | | `main.js(tsx)` | 🚀 html引入的入口脚本 | 可省略 | | `App.vue` | 🎯 全局组件 | 可省略 | | `router.js(tsx)` | 🧭 路由文件 | 可省略 | | `window.json` | ⚙️ 窗口配置 | 可省略 | ## 📖 使用指南 ### 🔧 语法糖代替IPC示例 ```javascript // @mainProcess 注释声明函数访问系统API async function openFile() { // @mainProcess const result = await Main.dialog.showOpenDialog({ title: '选择文件', filters: [{ name: '所有文件', extensions: ['*'] }] }); return result; } // 直接访问 Node.js API const path = await NodeJS.path.join(__dirname, 'file.txt'); // 访问原生插件 const result = await PJS.customPlugin.doSomething(); ``` ### 🖼️ 窗口管理 ```javascript // 创建新窗口 const win = await openWindow('/index.html', { width: 800, height: 600, modal: true }); //向指定窗口发消息 window.windowManager.sendToWindow(winId, eventName, data) //向所有窗口发送广播 window.windowManager.broadcast(channel, data, excludeWinIds) window.windowManager.on(channel, (data) => { }) // 监听窗口事件 win.on('closed', () => { console.log('窗口已关闭'); }); ``` ### 📦 构建部署 ```bash # 开发模式 npm run dev #桌面预览,也可在浏览器手动打开 npm run dev:web #仅在浏览器中预览,如果仅开发web # 构建 Web 版本 npm run build:web # 打包为可执行文件 npm run build:win # Windows npm run build:mac # macOS npm run build:linux # Linux # 预览build后效果 npm run preview:desktop # 预览桌面 npm run preview:web # 预览web ``` ## ❓ 常见问题 <details> <summary><strong>🔧 安装和启动问题</strong></summary> **Q: 创建项目后运行 `npm run dev` 启动了 Vite 服务但没有打开桌面窗口?** A: 这通常是 Electron 依赖未完全安装导致的,可以进入node_modules/electron目录确实是否有dist目录,若否则确认是electron安装失败。解决方案: ```bash cd node_modules/electron node install.js ``` **Q: 遇到未知问题怎么办?** A: 尝试重启开发服务器 `npm run dev`,这能解决大部分问题。如果仍无法解决,请在 [GitHub Issues](https://github.com/qew4/mixone-example/issues) 提交问题。 </details> <details> <summary><strong>🛠️ 技术支持</strong></summary> **Q: 支持 React、Vue 吗?** A: 完全支持!Vue 支持 2.7 和 3.x 版本,React 支持最新版本。 **Q: 支持 TypeScript 吗?** A: Vue 3 和 React 项目完全支持 TypeScript。 **Q: 如何访问 Electron API?** A: 使用 `Main` 标识符直接访问,记得在函数前添加 `// @mainProcess` 注释。 **Q: 如何访问 Node.js 包?** A: 内置包通过 `NodeJS.包名` 访问(如 `NodeJS.fs`),第三方包需要先安装。 </details> <details> <summary><strong>🖥️ 平台兼容性</strong></summary> **Q: 支持 Windows 7 吗?** A: 支持!创建项目时选择 Electron v21 即可。 **Q: 支持 macOS 和 Linux 吗?** A: 理论上支持,但尚未充分测试。欢迎反馈测试结果。 </details> <details> <summary><strong>⚡ 开发技巧</strong></summary> **Q: 修改 Main、NodeJS、PJS 相关代码需要重启吗?** A: 通常不需要,框架会自动监听并刷新。如果失效,请重启开发服务器。 **Q: Main、NodeJS、PJS 语法必须使用 await 吗?** A: 是的,必须使用 `await`,且所在函数必须是 `async` 函数。 **Q: 可以使用路径别名吗?** A: 支持!可用别名:`@/utils`、`@/store`、`@/assets`、`@/windows`、`@/components`、`@/main` ```javascript // 使用示例 import { getDocumentsPath } from '@/utils/api/utils.js'; ``` </details> ## 🔒 安全性 MixOne 是一个编译工具,所有渲染进程访问主进程 API 的代码都按照 Electron 安全机制实现和编译,确保应用安全性。 ### ⚠️ 注意事项 - 使用 `// @mainProcess` 注释的函数内不要使用 Main、NodeJS、PJS 语法 - Main、NodeJS、PJS 调用的函数内部不能再嵌套使用这些语法作为参数 - preload.js 和 main/main.js 中不能使用路径别名 ## 📄 许可证 - **永久免费使用** - 个人和商业项目均可免费使用 - **开源协议** - MIT + Commons Clause - **版权保留** - 使用时请保留版权信息 --- <div align="center"> **🌟 如果 MixOne 对你有帮助,请给我们一个 Star!** [📖 文档](https://github.com/qew4/mixone-example/blob/main/doc/MixOne_document_chinese.md) • [🐛 报告问题](https://github.com/qew4/mixone-example/issues) • [💬 发布日志](./Changelog.md) Made with ❤️ by MixOne Team </div>