如何利用 `Tauri` 或 `Electron`,将 Vue 应用打包为功能强大的桌面应用,并与原生系统 API 交互?

各位观众,欢迎来到今天的 "Vue 应用变身桌面侠" 讲座现场! 今天咱们不聊虚的,直接上手,把 Vue 写的网页应用,摇身一变,变成能在电脑上跑的桌面程序,还能跟系统玩点“亲密互动”。 咱们就拿 TauriElectron 这俩“神器”开刀,手把手教你把 Vue 应用打包成桌面应用,还能调用原生 API,让你的应用“上天入地,无所不能”。

第一节:热身运动:Tauri vs Electron,谁才是你的菜?

先来个小小的“选秀”环节,TauriElectron 都是桌面应用开发的利器,但风格不太一样。

特性 Tauri Electron
技术栈 Rust + WebView (系统自带) JavaScript + Chromium
体积 小巧玲珑 (几 MB) 略显臃肿 (几十 MB 起步)
性能 优秀 (Rust 扛把子) 还可以 (毕竟 JS)
资源占用 低 (省电小能手) 较高 (吃内存小能手)
安全性 高 (Rust 的优势) 相对较低 (JS 的锅)
跨平台 支持 (主流平台) 支持 (主流平台)
学习曲线 稍高 (Rust 需要啃一下) 较低 (JS 老朋友)
生态系统 相对较新,但发展迅速 成熟,社区庞大

简单来说,Tauri 就像一个精简版的跑车,性能好,体积小,但需要你懂点 Rust 的驾驶技巧。 Electron 就像一个舒适的房车,上手容易,功能齐全,但油耗可能稍微高一点。

选哪个,看你的需求和口味。 如果你追求极致性能和安全性,又不怕啃 Rust 这块“硬骨头”,Tauri 绝对是你的不二之选。 如果你只想快速上手,用熟悉的 JavaScript 技术栈搞定一切,Electron 也能满足你的需求。

第二节:Tauri 实战:Vue 应用的华丽变身

咱们先来用 Tauri 把一个简单的 Vue 应用打包成桌面程序。

  1. 准备 Vue 应用

    如果你已经有一个 Vue 应用,可以直接跳到下一步。 如果没有,那就创建一个简单的 Vue 应用:

    vue create my-tauri-app
    cd my-tauri-app

    选择你喜欢的配置,一路回车就好。

  2. 安装 Tauri CLI

    npm install -g @tauri-apps/cli
  3. 初始化 Tauri

    在 Vue 项目根目录下运行:

    tauri init

    根据提示,填写项目名称、窗口标题等信息。 重要的一点,要选择 dist 目录作为你的 Vue 应用构建输出目录。 默认情况下,Vue CLI 会把构建好的文件放在 dist 目录里。

  4. 构建 Vue 应用

    npm run build

    这会在 dist 目录生成你的 Vue 应用。

  5. 运行 Tauri 应用

    tauri dev

    见证奇迹的时刻到了! 你的 Vue 应用现在应该在一个独立的窗口里运行了,这就是你的桌面应用雏形。

  6. 打包 Tauri 应用

    tauri build

    这条命令会把你的 Vue 应用打包成一个可执行文件,放在 src-tauri/target/release/bundle 目录下。 你可以把这个可执行文件分发给你的朋友,让他们也能体验你的桌面应用。

  7. 与原生 API 交互 (Tauri Command)

    Tauri 的强大之处在于它可以让你调用原生系统 API。 咱们来写一个简单的例子,让应用可以读取系统信息。

    • src-tauri/src/main.rs 文件中添加以下代码:
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
       tauri::Builder::default()
           .invoke_handler(tauri::generate_handler![my_custom_command])  // 注册命令
           .run(tauri::generate_context!())
           .expect("error while running tauri application");
    }
    
    use tauri::State;
    use serde::{Serialize, Deserialize};
    
    #[derive(Debug, Serialize, Deserialize)]
    pub struct MyState {
       pub message: String,
    }
    
    #[tauri::command]
    async fn my_custom_command(state: State<'_, MyState>) -> Result<String, String> {
       // 在这里调用原生 API
       // 例如,读取系统信息
       let os_type = std::env::consts::OS;
       let arch = std::env::consts::ARCH;
       let message = format!("Hello from Rust! OS: {}, Arch: {}, State Message: {}", os_type, arch, state.message);
       Ok(message)
    }
    • src-tauri/src/main.rs 中添加状态管理代码
    use tauri::{State};
    use serde::{Serialize, Deserialize};
    
    #[derive(Debug, Serialize, Deserialize)]
    pub struct MyState {
       pub message: String,
    }
    
    #[cfg_attr(mobile, tauri::mobile_entry_point)]
    pub fn run() {
       tauri::Builder::default()
           .manage(MyState { message: "Initial State".to_string() }) // 初始化状态
           .invoke_handler(tauri::generate_handler![my_custom_command])
           .run(tauri::generate_context!())
           .expect("error while running tauri application");
    }
    
    #[tauri::command]
    async fn my_custom_command(state: State<'_, MyState>) -> Result<String, String> {
       let os_type = std::env::consts::OS;
       let arch = std::env::consts::ARCH;
       let message = format!("Hello from Rust! OS: {}, Arch: {}, State Message: {}", os_type, arch, state.message);
       Ok(message)
    }
    • 在 Vue 组件中调用 Tauri 命令:
    <template>
     <button @click="getSystemInfo">获取系统信息</button>
     <p>{{ systemInfo }}</p>
    </template>
    
    <script>
    import { invoke } from '@tauri-apps/api/tauri';
    
    export default {
     data() {
       return {
         systemInfo: '',
       };
     },
     methods: {
       async getSystemInfo() {
         try {
           this.systemInfo = await invoke('my_custom_command'); // 调用 Rust 命令
         } catch (error) {
           console.error('Error invoking command:', error);
           this.systemInfo = 'Error: ' + error;
         }
       },
     },
    };
    </script>

    刷新你的 Tauri 应用,点击按钮,你就能看到系统信息显示在页面上了。 这只是一个简单的例子,你可以用 Tauri 调用各种各样的原生 API,比如读写文件、操作剪贴板、控制窗口等等。

第三节:Electron 上手:JS 老司机也能轻松驾驭

接下来,咱们用 Electron 来做同样的事情。

  1. 创建 Electron 项目

    npm init -y electron-app
    cd electron-app
    npm install electron --save-dev
  2. 安装 Vue CLI

    npm install -g @vue/cli
    vue create my-electron-vue-app
    cd my-electron-vue-app
  3. 集成 Vue 和 Electron

    vue add electron-builder

    这个命令会自动安装 electron-builder,并配置好 Vue 项目,让你可以轻松地把 Vue 应用打包成 Electron 应用。

  4. 修改 main.js (Electron 主进程)

    打开 background.js 文件,这是 Electron 的主进程文件,负责创建窗口、加载 Vue 应用等。

    const { app, BrowserWindow } = require('electron')
    const path = require('path')
    const url = require('url')
    
    let win
    
    function createWindow () {
     win = new BrowserWindow({
       width: 800,
       height: 600,
       webPreferences: {
         nodeIntegration: true,
         contextIsolation: false
       }
     })
    
     // 加载 Vue 应用
     const startUrl = process.env.ELECTRON_START_URL || url.format({
       pathname: path.join(__dirname, '/../dist/index.html'),
       protocol: 'file:',
       slashes: true
     });
     win.loadURL(startUrl);
    
     // 打开开发者工具
     win.webContents.openDevTools()
    
     win.on('closed', () => {
       win = null
     })
    }
    
    app.on('ready', createWindow)
    
    app.on('window-all-closed', () => {
     if (process.platform !== 'darwin') {
       app.quit()
     }
    })
    
    app.on('activate', () => {
     if (win === null) {
       createWindow()
     }
    })
    • nodeIntegration: true 允许你在 Vue 应用中使用 Node.js 的 API。 注意安全风险,在生产环境中谨慎使用。
    • contextIsolation: false 允许在渲染进程中直接访问主进程的变量和函数。 同样注意安全风险。
  5. 运行 Electron 应用

    npm run electron:serve

    你的 Vue 应用现在应该在一个 Electron 窗口里运行了。

  6. 打包 Electron 应用

    npm run electron:build

    这条命令会把你的 Vue 应用打包成一个可执行文件,放在 dist_electron 目录下。

  7. 与原生 API 交互 (Electron ipcRenderer & ipcMain)

    Electron 通过 ipcRenderer (渲染进程) 和 ipcMain (主进程) 进行通信,从而调用原生 API。

    • background.js (主进程) 中添加以下代码:
    const { app, BrowserWindow, ipcMain } = require('electron')
    const path = require('path')
    const url = require('url')
    const os = require('os'); // 引入 Node.js 的 os 模块
    
    let win
    
    function createWindow () {
     win = new BrowserWindow({
       width: 800,
       height: 600,
       webPreferences: {
         nodeIntegration: true,
         contextIsolation: false
       }
     })
    
     const startUrl = process.env.ELECTRON_START_URL || url.format({
       pathname: path.join(__dirname, '/../dist/index.html'),
       protocol: 'file:',
       slashes: true
     });
     win.loadURL(startUrl);
    
     win.webContents.openDevTools()
    
     win.on('closed', () => {
       win = null
     })
    }
    
    app.on('ready', createWindow)
    
    app.on('window-all-closed', () => {
     if (process.platform !== 'darwin') {
       app.quit()
     }
    })
    
    app.on('activate', () => {
     if (win === null) {
       createWindow()
     }
    })
    
    // 监听来自渲染进程的消息
    ipcMain.on('get-system-info', (event) => {
     const systemInfo = {
       osType: os.type(),
       osRelease: os.release(),
       arch: os.arch()
     };
     event.reply('system-info', systemInfo); // 发送消息给渲染进程
    });
    • 在 Vue 组件中调用 Electron API:
    <template>
     <button @click="getSystemInfo">获取系统信息</button>
     <p>{{ systemInfo }}</p>
    </template>
    
    <script>
    const { ipcRenderer } = require('electron'); // 引入 ipcRenderer
    
    export default {
     data() {
       return {
         systemInfo: '',
       };
     },
     methods: {
       getSystemInfo() {
         ipcRenderer.send('get-system-info'); // 发送消息给主进程
    
         ipcRenderer.on('system-info', (event, info) => {
           this.systemInfo = `OS Type: ${info.osType}, OS Release: ${info.osRelease}, Arch: ${info.arch}`;
         });
       },
     },
    };
    </script>

    刷新你的 Electron 应用,点击按钮,你就能看到系统信息显示在页面上了。

第四节:进阶技巧:让你的桌面应用更上一层楼

  • 自定义窗口外观: TauriElectron 都提供了丰富的 API,让你自定义窗口的外观,比如隐藏标题栏、设置窗口大小、添加菜单等等。
  • 使用原生 UI 组件: 如果你想让你的应用看起来更像一个原生应用,可以考虑使用 Tauri 的 Wails 或 Electronremote 模块来调用原生 UI 组件。 不过要注意,这会增加应用的复杂性。
  • 优化性能: 对于大型应用,性能优化至关重要。 可以通过代码优化、资源压缩、懒加载等方式来提升应用的性能。
  • 安全性: 桌面应用的安全问题不容忽视。 要注意防止 XSS 攻击、SQL 注入、代码注入等安全漏洞。 Tauri 在安全性方面有天然的优势,因为它使用 Rust 编写,可以有效防止内存安全问题。 Electron 则需要你更加小心,避免使用不安全的 API,并定期更新 Electron 版本。

第五节:总结与展望

今天咱们一起学习了如何用 TauriElectron 把 Vue 应用打包成桌面应用,并调用原生 API。 希望通过今天的讲座,你能够掌握桌面应用开发的基本技能,创造出更多有趣、实用的桌面应用。

记住,TauriElectron 只是工具,真正重要的是你的创意和想法。 祝你在桌面应用开发的道路上越走越远! 感谢大家的观看,咱们下期再见!

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注