开发环境
Vue3 + Vite
需求
我司有个项目,要求前端同时适配Nginx服务器和electron桌面端。可是vue打包后已经无法修改参数。
第一阶段
这个阶段是想着能否利用electron拦截功能,做出和Nginx反向代理相同的功能,于是经过和ChatGPT的友好交流,就有了利用electron session的拦截功能的代码:
//main.js
const { app, BrowserWindow, session } = require('electron')
const path = require('path')
const url = require('url')
const auth_path = "/auth/api";
const data_path = "/api/v1";
const ws_path = "/websocket";
const proxy_map = {
"/api/v1": "http://xxxx:xxxx", //主接口,
"/auth/api": "http://xxxx:xxxxx", // 认证接口
"/websocket": "http://xxxx:xxxxx", // websocket接口
};
const createWindow = () => {
// 创建浏览窗口
const mainWindow = new BrowserWindow({
width: 1400,
height: 800,
webPreferences: {
preload: path.join(__dirname, 'preload.js')
},
icon: path.join(__dirname, './assert/favicon.ico'),
})
mainWindow.loadFile(path.join(__dirname, './dist/index.html'))
mainWindow.maximize()
// 打开开发工具
// mainWindow.webContents.openDevTools();
}
app.whenReady().then(() => {
createWindow()
session.defaultSession.webRequest.onBeforeRequest((details, callback) => {
const parsedUrl = url.parse(details.url)
if (parsedUrl.protocol === 'http:' || parsedUrl.protocol === 'https:') {
callback({});
return
}
let auth_pos = details.url.indexOf(auth_path)
if (auth_pos >= 0) {
let real_path = details.url.substring(auth_pos);
callback({ redirectURL: proxy_map[auth_path] + real_path });
return;
}
let data_pos = details.url.indexOf(data_path)
if (data_pos >= 0) {
let real_path = details.url.substring(data_pos);
callback({ redirectURL: proxy_map[data_path] + real_path });
return;
}
let ws_pos = details.url.indexOf(ws_path)
if (ws_pos >= 0) {
let real_path = details.url.substring(ws_pos);
callback({ redirectURL: proxy_map[ws_path] + real_path });
return;
}
callback({});
});
})
app.on('window-all-closed', () => {
if (process.platform !== 'darwin') app.quit()
})
这段代码就是拦截非HTTP的请求。因为安装Nginx的代理写法,Electron会认为是文件请求。拦截下的请求安装map转向真正的http请求。
结果
就是成功了一半。这样搞能成功拦截http请求,但是无法重定向websocket。还是那个GPT,他说像websocket这种长链接一般是无法重定向的,比较好的办法是建立一个websocket服务器进行转发,我觉得太麻烦就放弃了。
第二阶段
于是转向了针对vue的配置文件的操作。
1 直接引入
事实上,直接引入JSON
import Settings from "../../public/settings.json";
是可以实现的,而且也能正确识别。可是打包的时候,Vite会直接把JSON文件内容值当成一个变量打包,打包后无论如何改变配置文件都无法改变dist包内的变量值。
2 axios 引入
这个方案主要需要考虑axios是异步操作,只有等结果到达之后才能初始化vue。
//main.js
import { createApp } from 'vue';
import { createPinia } from 'pinia';
import App from './App.vue';
import router from './router';
import axios from "axios";
axios.get("/settings.json").then((data)=>{
let settings = data.data;
const app = createApp(App)
app.config.globalProperties.settings = settings;
app.provide("settings", settings);
app.use(createPinia())
app.use(router)
app.mount('#app');
}).catch((error)=>{
console.log(error)
});
在这里,提供了两种使用setting的方式: globalProperties 和 provide ,个人比较建议使用 provide 方式。
setting 参数使用
//app_settings.js
class AppSettings {
constructor() {
//...
}
set_settings(settings) {
//...
}
}
const app_settings = new AppSettings();
export default app_settings;
个人比较建议参数统一在某个类中进行管理和使用。
<script setup>
//App.vue
import {ref, nextTick, provide, inject} from "vue";
import app_settings from "./app_settings";
const settings = inject("settings");
app_settings.set_settings(settings);
</script>
然后在App.vue中重新设置参数。
现在,你就可以在别的各个组件中引入app_settings ,然后愉快的使用可配置参数拉!enjoy!!!!