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
Electron
5.0
和6.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
中的以下代码就行了
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
"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
目录中,加载的时候用下面的方式
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-static
和copy-webpack-plugin
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
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