前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >Electron集成Vue Cli3创建项目

Electron集成Vue Cli3创建项目

作者头像
码客说
发布2020-05-09 14:54:19
2.5K0
发布2020-05-09 14:54:19
举报
文章被收录于专栏:码客

Vue CLi3环境配置

卸载旧版本

代码语言:javascript
复制
npm uninstall vue-cli -g# OR yarn global remove vue-cli

安装新版本

代码语言:javascript
复制
npm install -g @vue/cli# ORyarn global add @vue/cli

检查其版本是否正确 (3.x)

代码语言:javascript
复制
vue --version

创建项目后添加依赖

代码语言:javascript
复制
vue ui

安装插件

vue-cli-plugin-electron-builder

插件官网地址: https://nklayman.github.io/vue-cli-plugin-electron-builder/

选择Electron版本为5.0.0

Electron5.06.0的语法变化不大 选用5.0是因为node-ffi第三方修改版也只能支持到5.0

运行报错

INFO Launching Electron… Failed to fetch extension, trying 4 more times Failed to fetch extension, trying 3 more times Failed to fetch extension, trying 2 more times Failed to fetch extension, trying 1 more times Failed to fetch extension, trying 0 more times Vue Devtools failed to install: Error: net::ERR_CONNECTION_TIMED_OUT

注释掉src/background.js中的以下代码就行了

代码语言:javascript
复制
if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
        await installVueDevtools();
    } catch (e) {
        console.error("Vue Devtools failed to install:", e.toString());
    }
}

虽然还是会报错 但是不用等它尝试下载那么多次了 不用管这个错误即可

旧项目添加依赖

开发依赖添加

代码语言:javascript
复制
"devDependencies": {
	"electron": "5.0.0",
	"vue-cli-plugin-electron-builder": "^1.4.0"
}

运行脚本添加

代码语言:javascript
复制
"scripts": {
    "electron:build": "vue-cli-service electron:build",
    "electron:serve": "vue-cli-service electron:serve",
    "postinstall": "electron-builder install-app-deps",
    "postuninstall": "electron-builder install-app-deps"
},
"main": "background.js",

入口变成了background.js

在src目录下创建background.js

代码语言:javascript
复制
"use strict";

import { app, protocol, BrowserWindow } from "electron";
import {
  createProtocol,
  installVueDevtools
} from "vue-cli-plugin-electron-builder/lib";
const isDevelopment = process.env.NODE_ENV !== "production";

// Keep a global reference of the window object, if you don't, the window will
// be closed automatically when the JavaScript object is garbage collected.
let win;

// Scheme must be registered before the app is ready
protocol.registerSchemesAsPrivileged([
  { scheme: "app", privileges: { secure: true, standard: true } }
]);

function createWindow() {
  // Create the browser window.
  win = new BrowserWindow({
    width: 800,
    height: 600,
    webPreferences: {
      nodeIntegration: true
    }
  });

  if (process.env.WEBPACK_DEV_SERVER_URL) {
    // Load the url of the dev server if in development mode
    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
    if (!process.env.IS_TEST) win.webContents.openDevTools();
  } else {
    createProtocol("app");
    // Load the index.html when not in development
    win.loadURL("app://./index.html");
  }

  win.on("closed", () => {
    win = null;
  });
}

// Quit when all windows are closed.
app.on("window-all-closed", () => {
  // On macOS it is common for applications and their menu bar
  // to stay active until the user quits explicitly with Cmd + Q
  if (process.platform !== "darwin") {
    app.quit();
  }
});

app.on("activate", () => {
  // On macOS it's common to re-create a window in the app when the
  // dock icon is clicked and there are no other windows open.
  if (win === null) {
    createWindow();
  }
});

// This method will be called when Electron has finished
// initialization and is ready to create browser windows.
// Some APIs can only be used after this event occurs.
app.on("ready", async () => {
  if (isDevelopment && !process.env.IS_TEST) {
    // Install Vue Devtools
    try {
      await installVueDevtools();
    } catch (e) {
      console.error("Vue Devtools failed to install:", e.toString());
    }
  }
  createWindow();
});

// Exit cleanly on request from parent process in development mode.
if (isDevelopment) {
  if (process.platform === "win32") {
    process.on("message", data => {
      if (data === "graceful-exit") {
        app.quit();
      }
    });
  } else {
    process.on("SIGTERM", () => {
      app.quit();
    });
  }
}

就项目中的Electron中的静态页面建议放在public文件夹中

打包配置

我们使用的vue-cli-plugin-electron-builder内部也是用electron-builder打包的,但是配置的位置不能像之前那样配置了

官方:https://nklayman.github.io/vue-cli-plugin-electron-builder/guide/configuration.html

旧配置

之前的配置 build在根节点上

代码语言:javascript
复制
"build": {
    "appId": "cn.psvmc",
    "productName": "互动课堂",
    "icon":"build/app.ico",
    "files": [
      "**/*",
      "static/*"
    ],
    "asar": true,
    "mac": {
      "icon":"build/app.ico",
      "target": [
        "dmg",
        "zip"
      ]
    },
    "win": {
      "icon":"build/app.ico",
      "target": [
        "zip"
      ]
    },
    "nsis": {
      "oneClick": false,
      "allowElevation": true,
      "allowToChangeInstallationDirectory": true,
      "installerIcon": "build/app.ico",
      "uninstallerIcon": "build/app.ico",
      "installerHeaderIcon": "build/app.ico",
      "createDesktopShortcut": true,
      "createStartMenuShortcut": true,
      "license": "LICENSE.txt"
    }
  },

新配置

在项目的根目录中的vue.config.js中添加以下配置

如果没有该文件的话创建即可

代码语言:javascript
复制
module.exports = {
  pluginOptions: {
    electronBuilder: {
      builderOptions: {
        appId: "cn.psvmc",
        productName: "星火智慧课堂",
        icon: "./app.ico",
        files: ["**/*", "static/*"],
        asar: true,
        mac: {
          icon: "./app.ico",
          target: ["zip", "dmg"]
        },
        win: {
          icon: "./app.ico",
          target: ["zip", "nsis"]
        },
        nsis: {
          oneClick: false,
          allowElevation: true,
          allowToChangeInstallationDirectory: true,
          installerIcon: "./app.ico",
          uninstallerIcon: "./app.ico",
          installerHeaderIcon: "./app.ico",
          createDesktopShortcut: true,
          createStartMenuShortcut: true,
          license: "./LICENSE.txt"
        }
      }
    }
  }
};

注意事项

  • 图标的路径是相对于vue.config.js所在目录的相对位置,也就是说图标要放在项目的根目录,不是构建生成后目录的路径。
  • LICENSE.txt文件的编码必须为GBK编码

页面加载方式

之前直接用Electron写的代码,后来要结合Vue Cli3创建的项目,本来想的是直接把Electron的代码放在Vue的public目录中,加载的时候用下面的方式

代码语言:javascript
复制
if (process.env.WEBPACK_DEV_SERVER_URL) {
    // 开发环境
    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
    pptWindow.loadFile("../public/classtools/ppt/ppt.html");
} else {
    // 正式发布
    createProtocol("app");
    win.loadURL("app://./index.html");
    pptWindow.loadURL("app://./classtools/ppt/ppt.html");
}

但是发现开发环境中完全没问题,打包后就各种找不到依赖

所以这种方式是行不通的,只能把Electron中的静态页面用Vue的方式在写一遍

但是问题是Electron中用的Node,包导入导出用的CommonJS规范,而Vue用的是ES6的规范,所以代码也要微改。

原写法

代码语言:javascript
复制
exports.mydb = mydb;

改为

代码语言:javascript
复制
export default mydb;

加载页面方式改为

代码语言:javascript
复制
if (process.env.WEBPACK_DEV_SERVER_URL) {
    // 根页面
    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
    // 内页
    toolbarWindows.loadURL(
        process.env.WEBPACK_DEV_SERVER_URL + "#toolbar"
    );
} else {
    createProtocol("app");
    // 根页面
    win.loadURL("app://./index.html");
    // 内页
    toolbarWindows.loadURL("app://./index.html#toolbar");
}

loadFile全部改为了loadURL

调用二进制文件(FFMPEG)

Electron默认是开启asar的,导致二进制文件也被打在了asar文件中,就不能再被调用,所以我们要让二进制文件不被处理。

首先我们要知道程序的打包步骤

webpack打包 => electron-builder打包asar打包 => exe打包

考虑到不同平台需要打入的ffmpeg不同,我们可以在webpack打包过程中筛选使用的文件,过程如下:

如果软件不考虑多平台,那么可以直接下载对应平台的ffmpeg放在项目根目录下的core文件夹中,下面的第一步可以跳过不用配置。

第一步

安装ffmpeg-staticcopy-webpack-plugin

代码语言:javascript
复制
npm install --save-dev ffmpeg-static
npm install --save-dev copy-webpack-plugin

配置vue.config.js

把对应平台的文件放在项目根目录的core文件夹中

代码语言:javascript
复制
const path = require("path");
const CopyWebpackPlugin = require("copy-webpack-plugin");
module.exports = {
  publicPath: process.env.NODE_ENV === "production" ? "./" : "/",
  outputDir: "webapp",
  assetsDir: "assets",
  filenameHashing: false,
  lintOnSave: true,
  productionSourceMap: false,
  configureWebpack: config => {
    const plugins = [];
    // 打包不同平台的 ffmpeg 到 app
    const ffmpegBasePath = "node_modules/ffmpeg-static/bin/"; // ffmpeg-static
    const { platform } = process;
    const ffmpegPathMap = {
      darwin: "darwin/x64/ffmpeg",
      win32: "win32/ia32/ffmpeg.exe",
      win64: "win32/x64/ffmpeg.exe",
      linux32: "linux/ia32/ffmpeg",
      linux64: "linux/x64/ffmpeg"
    };
    const ffmpegPath = ffmpegBasePath + ffmpegPathMap[platform];
    plugins.push(
      new CopyWebpackPlugin([
        {
          from: path.join(__dirname, ffmpegPath),
          to: path.join(__dirname, "core"),
          ignore: [".*"]
        }
      ])
    );
    config.plugins = [...config.plugins, ...plugins];
  }
};

第二步

在配置electron-builder打包过程,让ffmpeg放在指定位置

还是配置vue.config.js

代码语言:javascript
复制
module.exports = {
  pluginOptions: {
    electronBuilder: {
      builderOptions: {
        appId: "cn.psvmc",
        productName: "星火智慧课堂",
        icon: "./app.ico",
        files: ["**/*", "static/*"],
        asar: true,
        win: {
          icon: "./app.ico",
          target: ["nsis"],
          extraResources: {
            from: "./core/",
            to: "./core/",
            filter: ["**/*"]
          }
        },
        nsis: {
          oneClick: false,
          allowElevation: true,
          allowToChangeInstallationDirectory: true,
          installerIcon: "./app.ico",
          uninstallerIcon: "./app.ico",
          installerHeaderIcon: "./app.ico",
          createDesktopShortcut: true,
          createStartMenuShortcut: true,
          license: "./LICENSE.txt"
        }
      }
    }
  }
}

主要就是添加了

代码语言:javascript
复制
extraResources: {
    from: "./core/",
    to: "./core/",
    filter: ["**/*"]
}

第三步

调用时对应的路径

代码语言:javascript
复制
import { resolve } from "path";
let ffmpegPath = "";
// 更新打包后 ffmpeg 路径
if (process.env.NODE_ENV === "production") {
    ffmpegPath = resolve(__dirname, "../core/ffmpeg");
} else {
    const { platform } = process;
    const ffmpegPathMap = {
        darwin: "darwin/x64/ffmpeg",
        win32: "win32/ia32/ffmpeg.exe",
        win64: "win32/x64/ffmpeg.exe",
        linux32: "linux/ia32/ffmpeg",
        linux64: "linux/x64/ffmpeg"
    };
    ffmpegPath = resolve(
        __dirname,
        "../../../../..",
        "ffmpeg-static/bin",
        ffmpegPathMap[platform]
    );
}

获取Windows音视频输入设备

代码语言:javascript
复制
ffmpeg -list_devices true -f dshow -i dummy
本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2019-11-05,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • Vue CLi3环境配置
  • 创建项目后添加依赖
  • 旧项目添加依赖
  • 打包配置
  • 页面加载方式
  • 调用二进制文件(FFMPEG)
  • 获取Windows音视频输入设备
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档