文章目录
一. 前言
注意点: node的fs模块应当写入独立的js或ts文件中.
node相关路径以及获取返回值应当使用如下样例:
import path from 'path';
const fs = require('fs')
export function getLogData() {
let rs = fs.readFileSync(path.join(__dirname, './log.json'), 'utf8');
console.log(rs);
return JSON.parse(rs);
};
export function writeLogData(currentLog = {}) {
fs.writeFile(path.join(__dirname, './log.json'), JSON.stringify(currentLog), 'utf8', function (err) {
if (err) {
console.log(err);
}
});
}
export function deleteLogData() {
fs.writeFile(path.join(__dirname, './log.json'), '', 'utf8', function (err) {
if (err) {
ElMessage.error('清空日志失败');
}
});
ElMessage.success('清空日志成功');
}
二. 准备写好的vue项目打包
我使用的是vue3,ts,vite.
构建vue项目
首先使用vite构建工具构建vue3项目
2.1 修改ts打包代码检测.这个比较烦人. 在package.json
中
"scripts": {
"dev": "vite",
"build": "vite build",
"preview": "vite preview"
}
2.2 配置打包参数
用vite+ts构建的配置是vite.config.ts
打包样例模板如下:
打包期间期间会报错,你需要按提示安装相应组件
import { defineConfig } from 'vite'
import { resolve } from "path"; // 主要用于alias文件路径别名
import vue from '@vitejs/plugin-vue'
import vueJsx from "@vitejs/plugin-vue-jsx"; // jsx插件
export default defineConfig({
plugins: [vue(), vueJsx()], // 配置需要使用的插件列表
base: './', // 在生产中服务时的基本公共路径
publicDir: './public', // 静态资源服务的文件夹, 默认"public"
resolve: {
alias: {
"@": resolve(__dirname, './src'), // 这里是将src目录配置别名为 @ 方便在项目中导入src目录下的文件
}
},
// 引入第三方的配置,强制预构建插件包
optimizeDeps: {
include: ['echarts', 'axios', 'mockjs'],
},
css: {
preprocessorOptions: {
scss: {
charset: false, // 关闭编译时 字符编码 报错问题
javascriptEnabled: true,
additionalData: `@import "${resolve(__dirname, 'src/assets/css/var.scss')}";`,
},
},
},
json: {
//是否支持从 .json 文件中进行按名导入
namedExports: true,
//若设置为 true 导入的json会被转为 export default JSON.parse("..") 会比转译成对象字面量性能更好
stringify: false,
},
//继承自 esbuild 转换选项,最常见的用例是自定义 JSX
esbuild: {
jsxFactory: "h",
jsxFragment: "Fragment",
jsxInject: `import Vue from 'vue'`
},
// 打包配置
build: {
target: 'modules', // 设置最终构建的浏览器兼容目标。modules:支持原生 ES 模块的浏览器
outDir: 'dist', // 指定输出路径
assetsDir: 'assets', // 指定生成静态资源的存放路径
assetsInlineLimit: 4096, // 小于此阈值的导入或引用资源将内联为base64编码,设置为0可禁用此项。默认4096(4kb)
cssCodeSplit: true, // 启用/禁用CSS代码拆分,如果禁用,整个项目的所有CSS将被提取到一个CSS文件中,默认true
sourcemap: false, // 构建后是否生成 source map 文件
minify: 'terser', // 混淆器,terser构建后文件体积更小
write: true, //设置为 false 来禁用将构建后的文件写入磁盘
emptyOutDir: true, //默认情况下,若 outDir 在 root 目录下,则 Vite 会在构建时清空该目录。
chunkSizeWarningLimit: 500, //chunk 大小警告的限制
terserOptions: {
compress: {
drop_console: false, // 打包时不删除console.log日志.否则无法调试
drop_debugger: true,
},
} //去除 console debugger
},
// 本地运行配置,及反向代理配置
server: {
host: 'localhost', // 指定服务器主机名
port: 3000, // 指定服务器端口
open: true, // 在服务器启动时自动在浏览器中打开应用程序
strictPort: false, // 设为 false 时,若端口已被占用则会尝试下一个可用端口,而不是直接退出
https: false, // 是否开启 https
cors: true, // 为开发服务器配置 CORS。默认启用并允许任何源
// proxy: { // 为开发服务器配置自定义代理规则
// // 字符串简写写法
// '/foo': 'http://192.168.xxx.xxx:xxxx',
// // 选项写法
// '/api': {
// target: 'http://192.168.xxx.xxx:xxxx', //代理接口
// changeOrigin: true,
// rewrite: (path) => path.replace(/^\/api/, '')
// }
// }
},
})
vite-env.d.ts
declare module '*.vue' {
import { ComponentOptions } from 'vue'
const componentOptions: ComponentOptions
export default componentOptions
}
安装electron相关
npm install electron # 这是原生electron .网上也说可以用vue-cli-pugin-electron-build
npm install electron-packager --save-dev # electron打包插件
npm install terser
npm install @vitejs/plugin-vue-jsx
在package中新增如上配置
"main": "main.ts",
"scripts": {
# 运行客户端命令
"electron:serve": "vite build & electron . ",
# exe打包命令
"packager": "electron-packager ./ App --platform=win32 --arch=x64 --overwrite"
},
接着新建main.ts和src同级
main.ts内容
// Modules to control application life and create native browser window
const { app, BrowserWindow, ipcMain,Menu } = require('electron')
// import './src/store/index'
const path = require('path')
// const winURL = process.env.NODE_ENV === 'development' ? 'http://localhost:8080' : `file://${path.join(__dirname, './dist/index.html')}`
let mainWindow
let textdata
let textBox;
function createWindow() {
// Create the browser window.
mainWindow = new BrowserWindow({
width: 1280,
height: 1024,
minWidth: 600,
minHeight: 600,
title: '局部放电监控中心',
// autoHideMenuBar: true, // 自动隐藏菜单栏
webPreferences: {
// 是否启用Node integration
nodeIntegration: true, // Electron 5.0.0 版本之后它将被默认false
// 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本.默认为 true
contextIsolation: false, // Electron 12 版本之后它将被默认true
nodeIntegrationInWorker: true,
// 禁用同源策略,允许跨域
webSecurity: false,
preload: path.join(__dirname, 'preload.js'),
}
})
// and load the index.html of the app.
mainWindow.loadFile('./dist/index.html')
// Open the DevTools.
mainWindow.webContents.openDevTools({mode:'right'})
// 监听窗口关闭
mainWindow.on('window-close', function () {
mainWindow.close();
})
mainWindow.webContents.on('did-finish-load', () => {
console.log("主进程渲染,主窗口加载完毕")
})
}
// 左上角菜单
const menu = Menu.buildFromTemplate([
{
label: app.name,
submenu: [
{
click: () => textBox.webContents.send('customer-msg', textdata),
label: 'Increment'
},
]
}
])
Menu.setApplicationMenu(menu)
// 监听textBox消息 子窗口
ipcMain.on('textBox', function (event, data) {
console.log("接收")
textBox = new BrowserWindow({
width: 1280,
height: 1024,
minWidth: 600,
minHeight: 600,
parent: mainWindow, // mainWindow是主窗口
frame: true, // 有边框
title: '查看',
autoHideMenuBar: true, // 自动隐藏菜单栏
webPreferences: {
// 是否启用Node integration
nodeIntegration: true, // Electron 5.0.0 版本之后它将被默认false
// 是否在独立 JavaScript 环境中运行 Electron API和指定的preload 脚本.默认为 true
contextIsolation: false, // Electron 12 版本之后它将被默认true
nodeIntegrationInWorker: true,
// 禁用同源策略,允许跨域
webSecurity: false,
preload: path.join(__dirname, 'preload.js'),
}
})
// console.log(data,"---2323---")
// textBox.loadURL('http://127.0.0.1:3000/#/add') // 此处写 你要打开的路由地址
textBox.loadFile('./dist/index.html', {
hash: '#' + data
});
// 监听textBox窗口关闭
textBox.on('closed', () => {
textBox == null;
})
// Open the DevTools.
textBox.webContents.openDevTools({ mode: 'right' })
// textBox.webContents.on('did-finish-load', () => {
// console.log("渲染进程渲染,新窗口加载完毕")
// textBox.webContents.send('customer-msg', textdata)
// })
textBox.webContents.on('did-stop-loading', () => {
console.log("渲染进程渲染,新窗口加载完毕")
textBox.webContents.send('customer-msg', textdata)
})
})
// 监听 product-msg 信道消息
ipcMain.handle('product-msg', async (event, data) =>{
console.log(data, "i am data")
textdata = data
return true;
});
// 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.whenReady().then(createWindow)
app.on('activate', function () {
// 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 (BrowserWindow.getAllWindows().length === 0) createWindow()
})
// Quit when all windows are closed, except on macOS. There, it's common
// for applications and their menu bar to stay active until the user quits
// explicitly with Cmd + Q.
app.on('window-all-closed', function () {
if (process.platform !== 'darwin') app.quit()
})
// In this file you can include the rest of your app's specific main process
// code. You can also put them in separate files and require them here.
新建 preload.ts预加载模块
/**
* The preload script runs before. It has access to web APIs
* as well as Electron's renderer process modules and some
* polyfilled Node.js functions.
*
* https://www.electronjs.org/docs/latest/tutorial/sandbox
*/
const { contextBridge, } = require('electron')
contextBridge.exposeInMainWorld('versions', {
node: () => process.versions.node,
chrome: () => process.versions.chrome,
electron: () => process.versions.electron,
})
2.4 运行客户端vue
做完如上步骤那么我们就可以直接:
npm run electron:serve
至此我们的vue客户端可以正常运行
3.5 运行打包命令
npm run packager
大功告成.
相关报错的坑
vite+vue3+ts中通信报错 使用 ipcRenderer 报错
原因:为了安全性,官方将 electron v12.0.0 的 contextIsolation 的默认值改了
安装@vueuse/electron
npm install @vueuse/electron -D
import { useIpcRenderer } from "@vueuse/electron";
const ipcRenderer = useIpcRenderer();
const send = () => {
ipcRenderer.send('openWindow','/index');
};
const win = new BrowserWindow({
width: 800,
height: 600,
webPreferences: {
nodeIntegration: true,
contextIsolation: false,
}
})