diff --git a/_script/electron-dev.mjs b/_script/electron-dev.mjs index 1c2d67ff15..aa5aec9012 100644 --- a/_script/electron-dev.mjs +++ b/_script/electron-dev.mjs @@ -1,10 +1,8 @@ import { spawn } from 'node:child_process' -import { createRequire } from 'node:module' import process from 'node:process' import { setTimeout as delay } from 'node:timers/promises' const guiDir = process.cwd() -const require = createRequire(import.meta.url) const devServerUrl = 'http://localhost:8080' const state = { @@ -23,12 +21,6 @@ function spawnCommand (entry, args = [], extraEnv = {}) { }) } -function resolveVueCliServiceBin () { - return require.resolve('@vue/cli-service/bin/vue-cli-service.js', { - paths: [guiDir], - }) -} - function resolveElectronBin () { return require('electron') } @@ -68,7 +60,6 @@ async function shutdown (code = 0) { if (state.closing) { return } - state.closing = true stopChild(state.electron) stopChild(state.devServer) @@ -83,10 +74,10 @@ process.on('SIGTERM', () => { }) async function main () { - const vueCliServiceBin = resolveVueCliServiceBin() const electronBin = resolveElectronBin() - state.devServer = spawnCommand(process.execPath, [vueCliServiceBin, 'serve', '--port', '8080']) + // 使用 electron-vite dev 启动开发服务器 + state.devServer = spawnCommand('pnpm', ['exec', 'electron-vite', 'dev', '--watch']) state.devServer.on('exit', (code, signal) => { if (!state.closing) { void shutdown(code ?? (signal ? 1 : 0)) @@ -96,7 +87,7 @@ async function main () { try { await waitForServer(devServerUrl, state.devServer) state.electron = spawnCommand(electronBin, ['.'], { - WEBPACK_DEV_SERVER_URL: devServerUrl, + VITE_DEV_SERVER_URL: devServerUrl, }) state.electron.on('exit', (code, signal) => { void shutdown(code ?? (signal ? 1 : 0)) diff --git a/package.json b/package.json index f9924d4f95..bbb50b3aa0 100644 --- a/package.json +++ b/package.json @@ -7,7 +7,8 @@ "license": "MPL-2.0", "scripts": { "lint": "eslint .", - "lint:fix": "eslint . --fix" + "lint:fix": "eslint . --fix", + "gui:dev": "cd packages/gui && pnpm dev" }, "devDependencies": { "@antfu/eslint-config": "^3.16.0", diff --git a/packages/gui/.env b/packages/gui/.env index 55c49958bf..5c5a6c11b5 100644 --- a/packages/gui/.env +++ b/packages/gui/.env @@ -1,2 +1,2 @@ -VUE_APP_PUBLISH_URL=http://dev-sidecar.docmirror.cn/update/ -VUE_APP_PUBLISH_PROVIDER=generic +VITE_PUBLISH_URL=http://dev-sidecar.docmirror.cn/update/ +VITE_PUBLISH_PROVIDER=generic diff --git a/packages/gui/.gitignore b/packages/gui/.gitignore index a1010b6745..7ebec3d65d 100644 --- a/packages/gui/.gitignore +++ b/packages/gui/.gitignore @@ -1,6 +1,7 @@ .DS_Store node_modules /dist +/out # local env files diff --git a/packages/gui/babel.config.cjs b/packages/gui/babel.config.cjs deleted file mode 100644 index 0a932f18f5..0000000000 --- a/packages/gui/babel.config.cjs +++ /dev/null @@ -1,5 +0,0 @@ -module.exports = { - presets: [ - '@vue/babel-preset-jsx', - ], -} diff --git a/packages/gui/electron-builder.config.cjs b/packages/gui/electron-builder.config.cjs deleted file mode 100644 index 9a860b31e5..0000000000 --- a/packages/gui/electron-builder.config.cjs +++ /dev/null @@ -1,104 +0,0 @@ -const publishUrl = process.env.VUE_APP_PUBLISH_URL -const publishProvider = process.env.VUE_APP_PUBLISH_PROVIDER - -/** @type {import('electron-builder').Configuration} */ -module.exports = { - appId: 'dev-sidecar', - productName: 'dev-sidecar', - artifactName: 'DevSidecar-${version}-${arch}.${ext}', - copyright: 'Copyright © 2020-' + new Date().getFullYear() + ' Greper, WangLiang, CuteOmega', - directories: { - output: 'dist_electron', - buildResources: 'build', - }, - files: [ - { - from: 'dist', - to: 'dist', - filter: [ - '**/*', - '!win-*/**/*', - '!mac-*/**/*', - '!linux-*/**/*', - '!*.zip', - '!*.dmg', - '!*.blockmap', - '!*.exe', - '!*.AppImage', - '!*.deb', - '!*.rpm', - '!*.tar.gz', - '!*.flatpak', - '!builder-*.yml', - '!builder-*.yaml', - ], - }, - 'src/**/*', - 'package.json', - 'extra/**/*', - ], - extraResources: [ - { - from: 'extra', - to: 'extra', - }, - ], - afterPack: './pkg/after-pack.cjs', - afterAllArtifactBuild: './pkg/after-all-artifact-build.cjs', - nsis: { - oneClick: false, - perMachine: true, - allowElevation: true, - allowToChangeInstallationDirectory: true, - }, - win: { - icon: 'build/icons/', - target: [ - { - target: 'nsis', - arch: ['x64', 'ia32', 'arm64'], - }, - ], - }, - linux: { - icon: 'build/mac/', - target: [ - { - target: 'deb', - arch: ['x64', 'arm64', 'armv7l'], - }, - { - target: 'AppImage', - arch: ['x64', 'arm64', 'armv7l'], - }, - { - target: 'tar.gz', - arch: ['x64', 'arm64', 'armv7l'], - }, - { - target: 'rpm', - arch: ['x64', 'arm64', 'armv7l'], - }, - { - target: 'flatpak', - arch: ['x64'], - }, - ], - appId: 'cn.docmirror.DevSidecar', - category: 'System', - }, - mac: { - icon: './build/mac/icon.icns', - target: { - target: 'dmg', - arch: ['x64', 'arm64', 'universal'], - }, - category: 'public.app-category.developer-tools', - }, - publish: publishProvider - ? { - provider: publishProvider, - url: publishUrl, - } - : undefined, -} diff --git a/packages/gui/electron-builder.yml b/packages/gui/electron-builder.yml new file mode 100644 index 0000000000..914ed959d9 --- /dev/null +++ b/packages/gui/electron-builder.yml @@ -0,0 +1,85 @@ +appId: dev-sidecar +productName: dev-sidecar +artifactName: DevSidecar-${version}-${arch}.${ext} +copyright: Copyright © 2020-2026 Greper, WangLiang, CuteOmega + +directories: + output: dist_electron + buildResources: build + +files: + - from: out/main + to: out/main + filter: ['**/*'] + - from: out/renderer + to: out/renderer + filter: ['**/*'] + - from: out/preload + to: out/preload + filter: ['**/*'] + - from: src/main/bridge + to: out/main + filter: ['mitmproxy.js'] + - package.json + - extra/**/* + +extraResources: + - from: extra + to: extra + +afterPack: ./pkg/after-pack.mjs +afterAllArtifactBuild: ./pkg/after-all-artifact-build.mjs + +nsis: + oneClick: false + perMachine: true + allowElevation: true + allowToChangeInstallationDirectory: true + +win: + icon: build/icons/ + target: + - target: nsis + arch: + - x64 + - ia32 + - arm64 + +linux: + icon: build/mac/ + target: + - target: deb + arch: + - x64 + - arm64 + - armv7l + - target: AppImage + arch: + - x64 + - arm64 + - armv7l + - target: tar.gz + arch: + - x64 + - arm64 + - armv7l + - target: rpm + arch: + - x64 + - arm64 + - armv7l + - target: flatpak + arch: + - x64 + appId: cn.docmirror.DevSidecar + category: System + +mac: + icon: ./build/mac/icon.icns + target: + target: dmg + arch: + - x64 + - arm64 + - universal + category: public.app-category.developer-tools diff --git a/packages/gui/electron.vite.config.mjs b/packages/gui/electron.vite.config.mjs new file mode 100644 index 0000000000..da8ef7d32c --- /dev/null +++ b/packages/gui/electron.vite.config.mjs @@ -0,0 +1,108 @@ +import { defineConfig } from "electron-vite"; +import vue from "@vitejs/plugin-vue"; +import vueJsx from "@vitejs/plugin-vue-jsx"; +import { resolve, dirname } from "path"; +import { fileURLToPath } from "url"; +import fs from "fs"; + +const __dirname = dirname(fileURLToPath(import.meta.url)); + +// 读取 package.json 中的 dependencies 作为外部依赖 +const pkg = JSON.parse(fs.readFileSync(resolve(__dirname, "package.json"), "utf8")); +const dependencies = Object.keys(pkg.dependencies || {}); + +// 复制 mitmproxy.js 到输出目录的插件 +function copyMitmproxyPlugin() { + return { + name: "copy-mitmproxy", + closeBundle() { + const src = resolve(__dirname, "src/main/bridge/mitmproxy.js"); + const dest = resolve(__dirname, "out/main/mitmproxy.js"); + if (fs.existsSync(src)) { + fs.copyFileSync(src, dest); + console.log("mitmproxy.js copied to out/main/"); + } + }, + }; +} + +export default defineConfig({ + main: { + build: { + outDir: "out/main", + rollupOptions: { + external: [ + "electron", + ...dependencies, + ], + }, + }, + plugins: [copyMitmproxyPlugin()], + resolve: { + alias: { + "@": resolve(__dirname, "src/main"), + }, + }, + define: { + "global.GENTLY": true, + }, + }, + preload: { + build: { + outDir: "out/preload", + lib: { + entry: resolve(__dirname, "src/preload/index.js"), + formats: ["cjs"], + fileName: () => "index.js", + }, + rollupOptions: { + external: ["electron", ...dependencies], + }, + }, + plugins: [], + }, + renderer: { + root: resolve(__dirname, "src/renderer"), + base: "./", + publicDir: resolve(__dirname, "public"), + build: { + outDir: resolve(__dirname, "out/renderer"), + rollupOptions: { + input: { + index: resolve(__dirname, "src/renderer/index.html"), + }, + output: { + manualChunks(id) { + if (id.includes("node_modules")) { + if ( + id.includes("vue") || + id.includes("vue-router") || + id.includes("ant-design-vue") + ) { + return "vendor"; + } + } + }, + }, + }, + }, + plugins: [vue(), vueJsx()], + resolve: { + alias: { + "@": resolve(__dirname, "src/renderer/src"), + }, + }, + css: { + preprocessorOptions: { + scss: {}, + }, + }, + define: { + "global.GENTLY": true, + }, + server: { + port: 8080, + open: false, + }, + }, +}); diff --git a/packages/gui/linux-arm64.vue.config.js b/packages/gui/linux-arm64.vue.config.js deleted file mode 100644 index 58e4337573..0000000000 --- a/packages/gui/linux-arm64.vue.config.js +++ /dev/null @@ -1,94 +0,0 @@ -const path = require('node:path') -const { defineConfig } = require('@vue/cli-service') -const webpack = require('webpack') - -const publishUrl = process.env.VUE_APP_PUBLISH_URL -const publishProvider = process.env.VUE_APP_PUBLISH_PROVIDER -console.log('Publish url:', publishUrl) - -module.exports = defineConfig({ - pages: { - index: { - entry: 'src/main.js', - title: 'DevSidecar-给开发者的边车辅助工具', - }, - }, - lintOnSave: false, - configureWebpack: { - plugins: [ - new webpack.DefinePlugin({ 'global.GENTLY': true }), - ], - module: { - rules: [ - { - test: /\.json5$/i, - loader: 'json5-loader', - options: { - esModule: false, - }, - type: 'javascript/auto', - }, - ], - }, - }, - pluginOptions: { - electronBuilder: { - mainProcessFile: './src/background.js', - // Ref: https://github.com/nklayman/vue-cli-plugin-electron-builder/issues/1891 - customFileProtocol: './', - externals: [ - '@starknt/sysproxy', - '@starknt/sysproxy-linux-arm64-gnu', - '@starknt/shutdown-handler-napi', - '@starknt/shutdown-handler-napi-linux-arm64-gnu', - ], - nodeIntegration: true, - // Provide an array of files that, when changed, will recompile the main process and restart Electron - // Your main process file will be added by default - mainProcessWatch: ['src/bridge', 'src/*.js', 'node_modules/dev-sidecar/src'], - builderOptions: { - afterPack: './pkg/after-pack.js', - afterAllArtifactBuild: './pkg/after-all-artifact-build.js', - // artifactBuildCompleted: './pkg/artifact-build-completed.js', - // builderOptions: { - // publish: ['github']// 此处写入github 就好,不用添加其他内容 - // }, - extraResources: [ - { - from: 'extra', - to: 'extra', - }, - ], - appId: 'cn.docmirror.DevSidecar', - productName: 'dev-sidecar', - // eslint-disable-next-line no-template-curly-in-string - artifactName: 'DevSidecar-${version}-${arch}.${ext}', - copyright: 'Copyright © 2020-' + new Date().getFullYear() + ' Greper, WangLiang, CuteOmega', - nsis: { - oneClick: false, - perMachine: true, - allowElevation: true, - allowToChangeInstallationDirectory: true, - }, - linux: { - icon: 'build/mac/', - target: [ - { - target: 'flatpak', - arch: ['arm64', 'armv7l'], - }, - ], - category: 'System', - }, - publish: { - provider: publishProvider, - url: publishUrl, - // url: 'http://dev-sidecar.docmirror.cn/update/preview/', - }, - }, - chainWebpackMainProcess (config) { - config.entry('mitmproxy').add(path.join(__dirname, 'src/bridge/mitmproxy.js')) - }, - }, - }, -}) diff --git a/packages/gui/package.json b/packages/gui/package.json index 0790fca76f..d580705f70 100644 --- a/packages/gui/package.json +++ b/packages/gui/package.json @@ -3,7 +3,7 @@ "version": "2.1.0", "private": false, "type": "module", - "main": "src/background.js", + "main": "out/main/index.js", "author": { "email": "xiaojunnuo@qq.com", "name": "Greper" @@ -11,16 +11,17 @@ "license": "MPL-2.0", "homepage": "https://github.com/docmirror/dev-sidecar", "scripts": { - "serve": "pnpm exec vue-cli-service serve", - "build": "pnpm exec vue-cli-service build", - "lint": "pnpm exec vue-cli-service lint", - "electron": "node ../../_script/electron-dev.mjs", - "electron:build": "pnpm run build && pnpm exec electron-builder --config electron-builder.config.cjs", - "postinstall": "pnpm exec electron-builder install-app-deps", - "postuninstall": "pnpm exec electron-builder install-app-deps", - "electron:icons": "pnpm exec electron-icon-builder --input=./public/logo/win.png --output=build --flatten", - "electron:icons-mac": "pnpm exec electron-icon-builder --input=./public/logo/mac.png --output=build --flatten", - "electron:icons-black": "pnpm exec electron-icon-builder --input=./public/logo/win-black.png --output=build/black --flatten" + "dev": "electron-vite dev --watch", + "build": "electron-vite build", + "preview": "electron-vite preview", + "lint": "eslint .", + "electron": "electron-vite dev", + "electron:build": "electron-vite build && electron-builder", + "postinstall": "electron-builder install-app-deps", + "postuninstall": "electron-builder install-app-deps", + "electron:icons": "electron-icon-builder --input=./public/logo/win.png --output=build --flatten", + "electron:icons-mac": "electron-icon-builder --input=./public/logo/mac.png --output=build --flatten", + "electron:icons-black": "electron-icon-builder --input=./public/logo/win-black.png --output=build/black --flatten" }, "dependencies": { "@docmirror/dev-sidecar": "workspace:*", @@ -31,7 +32,6 @@ "adm-zip": "^0.5.17", "ant-design-vue": "^4.2.6", "archiver": "^7.0.1", - "core-js": "^3.49.0", "electron-baidu-tongji": "^1.0.5", "electron-updater": "^6.8.3", "json5": "^2.2.3", @@ -39,27 +39,23 @@ "minimist": "^1.2.8", "request-progress": "^3.0.0", "sass": "^1.99.0", - "sass-loader": "^16.0.7", "tiny-emitter": "^2.1.0", "vue": "^3.5.33", "vue-router": "^4.6.4", "vue3-json-editor": "^1.1.5" }, "devDependencies": { - "@babel/core": "^7.29.0", - "@babel/plugin-syntax-jsx": "^7.28.6", - "@vue/babel-helper-vue-jsx-merge-props": "^1.4.0", - "@vue/babel-preset-jsx": "^1.4.0", - "@vue/cli-plugin-babel": "^5.0.9", - "@vue/cli-service": "^5.0.9", - "concurrently": "^8.2.2", - "cross-env": "^7.0.3", + "@vitejs/plugin-vue": "^6.0.7", + "@vitejs/plugin-vue-jsx": "^5.1.5", "electron": "^41.3.0", "electron-builder": "^26.8.1", "electron-icon-builder": "^2.0.1", - "json5-loader": "^4.0.1", - "path-browserify": "^1.0.1", - "wait-on": "^7.2.0" + "electron-vite": "^5.0.0", + "esbuild": "^0.28.0", + "rollup": "^4.60.4", + "vite": "^8.0.13", + "vite-plugin-electron": "^0.29.1", + "vite-plugin-electron-renderer": "^0.14.7" }, "browserslist": [ "> 1%", diff --git a/packages/gui/pkg/after-all-artifact-build.cjs b/packages/gui/pkg/after-all-artifact-build.mjs similarity index 76% rename from packages/gui/pkg/after-all-artifact-build.cjs rename to packages/gui/pkg/after-all-artifact-build.mjs index 83e70675cd..0e89e5859b 100644 --- a/packages/gui/pkg/after-all-artifact-build.cjs +++ b/packages/gui/pkg/after-all-artifact-build.mjs @@ -1,6 +1,9 @@ -const fs = require('node:fs') -const path = require('node:path') -const pkg = require('../package.json') +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8')) function appendIntro (context, systemType, latest) { const version = pkg.version @@ -20,7 +23,8 @@ function appendIntro (context, systemType, latest) { } }) } -exports.default = async function (context) { + +export default async function (context) { console.log('after-all-artifact-build') appendIntro(context, 'mac', 'latest-mac.yml') appendIntro(context, 'win', 'latest.yml') diff --git a/packages/gui/pkg/after-pack.cjs b/packages/gui/pkg/after-pack.mjs similarity index 84% rename from packages/gui/pkg/after-pack.cjs rename to packages/gui/pkg/after-pack.mjs index 73a0c077e3..49def59ee4 100644 --- a/packages/gui/pkg/after-pack.cjs +++ b/packages/gui/pkg/after-pack.mjs @@ -1,7 +1,10 @@ -const fs = require('node:fs') -const path = require('node:path') -const archiver = require('archiver') -const pkg = require('../package.json') +import fs from 'node:fs' +import path from 'node:path' +import { fileURLToPath } from 'node:url' +import archiver from 'archiver' + +const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const pkg = JSON.parse(fs.readFileSync(path.join(__dirname, '../package.json'), 'utf8')) function writeAppUpdateYmlForLinux (appOutDir) { const publishUrl = process.env.VUE_APP_PUBLISH_URL @@ -17,7 +20,8 @@ updaterCacheDirName: 'dev-sidecar-gui-updater' const filePath = path.join(appOutDir, 'resources', 'app-update.yml') fs.writeFileSync(filePath, fileContent) } -exports.default = async function (context) { + +export default async function (context) { let targetPath let systemType if (context.packager.platform.nodeName === 'darwin') { diff --git a/packages/gui/src/background/powerMonitor.js b/packages/gui/src/main/background/powerMonitor.js similarity index 100% rename from packages/gui/src/background/powerMonitor.js rename to packages/gui/src/main/background/powerMonitor.js diff --git a/packages/gui/src/bridge/api/backend.js b/packages/gui/src/main/bridge/api/backend.js similarity index 93% rename from packages/gui/src/bridge/api/backend.js rename to packages/gui/src/main/bridge/api/backend.js index 2441882d90..10c94fa88e 100644 --- a/packages/gui/src/bridge/api/backend.js +++ b/packages/gui/src/main/bridge/api/backend.js @@ -1,13 +1,11 @@ -import fs from 'node:fs' +import fs, { readFileSync } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import DevSidecar from '@docmirror/dev-sidecar' import { app, ipcMain } from 'electron' import lodash from 'lodash' import jsonApi from '@docmirror/mitmproxy/src/json.js' -import { createRequire } from 'node:module' -const require = createRequire(import.meta.url) -const pk = require('../../../package.json') +const pk = JSON.parse(readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8')) import coreDefaultConfig from '@docmirror/dev-sidecar/src/config/index.js' import configLoader from '@docmirror/dev-sidecar/src/config/local-config-loader.js' import log from '../../utils/util.log.gui.js' @@ -15,8 +13,13 @@ import dateUtil from '@docmirror/dev-sidecar/src/utils/util.date.js' const { configFromFiles } = coreDefaultConfig -const __dirname = path.dirname(fileURLToPath(import.meta.url)) -const mitmproxyPath = path.join(__dirname, '../mitmproxy.js') +const _dirname = path.dirname(fileURLToPath(import.meta.url)) +// 根据环境判断 mitmproxy.js 的路径 +// electron-vite 开发模式下,主进程构建输出在 out/main/,所以 mitmproxy.js 也在同一目录 +const isDev = process.env.NODE_ENV !== 'production' +const mitmproxyPath = isDev + ? path.join(process.cwd(), 'out', 'main', 'mitmproxy.js') + : path.join(app.getAppPath(), 'out', 'main', 'mitmproxy.js') process.env.DS_EXTRA_PATH = path.join(app.getAppPath(), 'extra') let currentWin diff --git a/packages/gui/src/bridge/api/open-enable-loopback.js b/packages/gui/src/main/bridge/api/open-enable-loopback.js similarity index 82% rename from packages/gui/src/bridge/api/open-enable-loopback.js rename to packages/gui/src/main/bridge/api/open-enable-loopback.js index 2ec3f9ace7..6a09e1307e 100644 --- a/packages/gui/src/bridge/api/open-enable-loopback.js +++ b/packages/gui/src/main/bridge/api/open-enable-loopback.js @@ -1,17 +1,17 @@ import { app } from 'electron' import DevSidecar from '@docmirror/dev-sidecar' import sudoPrompt from '@vscode/sudo-prompt' -import { join } from 'node:path' +import path from 'node:path' import log from '../../utils/util.log.gui.js' const isDevelopment = process.env.NODE_ENV !== 'production' -const extraPath = join(process.cwd(), 'extra') +const extraPath = path.join(process.cwd(), 'extra') export default { open () { const options = { name: 'EnableLoopback', - icns: process.platform === 'darwin' ? join(extraPath, 'icons/icon.icns') : undefined, + icns: process.platform === 'darwin' ? path.join(extraPath, 'icons/icon.icns') : undefined, env: { PARAM: 'VALUE' }, } const exeFile = DevSidecar.api.shell.extraPath.getEnableLoopbackPath() diff --git a/packages/gui/src/bridge/auto-start/backend.js b/packages/gui/src/main/bridge/auto-start/backend.js similarity index 100% rename from packages/gui/src/bridge/auto-start/backend.js rename to packages/gui/src/main/bridge/auto-start/backend.js diff --git a/packages/gui/src/bridge/backend.js b/packages/gui/src/main/bridge/backend.js similarity index 100% rename from packages/gui/src/bridge/backend.js rename to packages/gui/src/main/bridge/backend.js diff --git a/packages/gui/src/bridge/file-selector/backend.js b/packages/gui/src/main/bridge/file-selector/backend.js similarity index 100% rename from packages/gui/src/bridge/file-selector/backend.js rename to packages/gui/src/main/bridge/file-selector/backend.js diff --git a/packages/gui/src/bridge/mitmproxy.js b/packages/gui/src/main/bridge/mitmproxy.js similarity index 90% rename from packages/gui/src/bridge/mitmproxy.js rename to packages/gui/src/main/bridge/mitmproxy.js index 69a0635329..4120e1c13e 100644 --- a/packages/gui/src/bridge/mitmproxy.js +++ b/packages/gui/src/main/bridge/mitmproxy.js @@ -5,7 +5,7 @@ import server from '@docmirror/mitmproxy' import jsonApi from '@docmirror/mitmproxy/src/json.js' import log from '@docmirror/mitmproxy/src/utils/util.log.server.js' // 当前脚本是在 server 的进程中执行的,所以使用 mitmproxy 中的logger -const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const _dirname = path.dirname(fileURLToPath(import.meta.url)) const configPath = process.argv[2] const configJson = fs.readFileSync(configPath) log.info('读取 running.json by gui bridge 成功:', configPath) @@ -20,6 +20,6 @@ try { // config.setting.script.defaultDir = path.join(__dirname, scriptDir) // const pacFilePath = '../extra/pac/pac.txt' // config.plugin.overwall.pac.customPacFilePath = path.join(__dirname, pacFilePath) -config.setting.rootDir = path.join(__dirname, '../') +config.setting.rootDir = path.join(_dirname, '../') log.info(`start mitmproxy by gui bridge, configPath: ${configPath}`) server.start(config) diff --git a/packages/gui/src/bridge/tongji/backend.js b/packages/gui/src/main/bridge/tongji/backend.js similarity index 100% rename from packages/gui/src/bridge/tongji/backend.js rename to packages/gui/src/main/bridge/tongji/backend.js diff --git a/packages/gui/src/bridge/update/backend.js b/packages/gui/src/main/bridge/update/backend.js similarity index 95% rename from packages/gui/src/bridge/update/backend.js rename to packages/gui/src/main/bridge/update/backend.js index cb39cb24fd..462127cf35 100644 --- a/packages/gui/src/bridge/update/backend.js +++ b/packages/gui/src/main/bridge/update/backend.js @@ -1,4 +1,4 @@ -import fs from 'node:fs' +import fs, { readFileSync } from 'node:fs' import path from 'node:path' import { fileURLToPath } from 'node:url' import DevSidecar from '@docmirror/dev-sidecar' @@ -8,14 +8,12 @@ import electronUpdater from 'electron-updater' const { autoUpdater } = electronUpdater import request from 'request' import progress from 'request-progress' -import { createRequire } from 'node:module' -const require = createRequire(import.meta.url) -const pkg = require('../../../package.json') +const pkg = JSON.parse(readFileSync(path.join(process.cwd(), 'package.json'), 'utf-8')) import appPathUtil from '../../utils/util.apppath.js' import log from '../../utils/util.log.gui.js' import { isNewVersion } from '@docmirror/dev-sidecar/src/utils/util.version.js' -const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const _dirname = path.dirname(fileURLToPath(import.meta.url)) const isMac = process.platform === 'darwin' const isLinux = process.platform === 'linux' @@ -82,11 +80,11 @@ function updateHandle (app, api, win, beforeQuit, quit, log) { // url: publishUrl // }) if (isMac) { - autoUpdater.updateConfigPath = path.join(__dirname, 'mac/dev-sidecar.app/Contents/Resources/app-update.yml') + autoUpdater.updateConfigPath = path.join(_dirname, 'mac/dev-sidecar.app/Contents/Resources/app-update.yml') } else if (isLinux) { - autoUpdater.updateConfigPath = path.join(__dirname, 'linux-unpacked/resources/app-update.yml') + autoUpdater.updateConfigPath = path.join(_dirname, 'linux-unpacked/resources/app-update.yml') } else { - autoUpdater.updateConfigPath = path.join(__dirname, 'win-unpacked/resources/app-update.yml') + autoUpdater.updateConfigPath = path.join(_dirname, 'win-unpacked/resources/app-update.yml') } } diff --git a/packages/gui/src/background.js b/packages/gui/src/main/index.js similarity index 95% rename from packages/gui/src/background.js rename to packages/gui/src/main/index.js index 5844616ced..b378fed495 100644 --- a/packages/gui/src/background.js +++ b/packages/gui/src/main/index.js @@ -5,6 +5,7 @@ import DevSidecar from '@docmirror/dev-sidecar' import { app, BrowserWindow, dialog, globalShortcut, ipcMain, Menu, nativeImage, nativeTheme, powerMonitor, Tray } from 'electron' import minimist from 'minimist' import backend from './bridge/backend.js' +// Note: bridge, utils, background are now in src/main/ directory import jsonApi from '@docmirror/mitmproxy/src/json.js' import log from './utils/util.log.gui.js' @@ -14,12 +15,17 @@ const isWindows = process.platform === 'win32' const isLinux = process.platform === 'linux' const isMac = process.platform === 'darwin' -const __dirname = path.dirname(fileURLToPath(import.meta.url)) +const _dirname = path.dirname(fileURLToPath(import.meta.url)) const isDevelopment = process.env.NODE_ENV !== 'production' const staticPath = isDevelopment ? path.resolve('public') : path.join(app.getAppPath(), 'dist') +// preload 脚本路径 +const preloadPath = isDevelopment + ? path.join(process.cwd(), 'out/preload/index.cjs') + : path.join(app.getAppPath(), 'out/preload/index.cjs') + let _powerMonitor = powerMonitor // Keep a global reference of the window object, if you don't, the window will @@ -94,7 +100,7 @@ function setTray () { }, ] // 设置系统托盘图标 - const iconRootPath = path.join(__dirname, '../extra/icons/tray') + const iconRootPath = path.join(_dirname, '../extra/icons/tray') let iconPath = path.join(iconRootPath, 'icon.png') const iconWhitePath = path.join(iconRootPath, 'icon-white.png') const iconBlackPath = path.join(iconRootPath, 'icon-black.png') @@ -206,12 +212,10 @@ function createWindow (startHideWindow, autoQuitIfError = true) { height: windowSize.height || 750, title: 'DevSidecar', webPreferences: { - enableRemoteModule: true, - contextIsolation: false, - nativeWindowOpen: true, // ADD THIS - // Use pluginOptions.nodeIntegration, leave this alone - // See nklayman.github.io/vue-cli-plugin-electron-builder/guide/security.html#node-integration for more info - nodeIntegration: true, // process.env.ELECTRON_NODE_INTEGRATION + preload: preloadPath, + contextIsolation: true, + nodeIntegration: false, + nativeWindowOpen: true, }, show: !startHideWindow, icon: path.join(staticPath, 'icon.png'), @@ -234,15 +238,15 @@ function createWindow (startHideWindow, autoQuitIfError = true) { _powerMonitor.setupMainWindow(win) } - if (process.env.WEBPACK_DEV_SERVER_URL) { + if (process.env.VITE_DEV_SERVER_URL) { // Load the url of the dev server if in development mode - win.loadURL(process.env.WEBPACK_DEV_SERVER_URL) + win.loadURL(process.env.VITE_DEV_SERVER_URL) if (!process.env.IS_TEST) { setTimeout(openDevTools, 2000) } } else { // Load the index.html when not in development - win.loadFile(path.join(app.getAppPath(), 'dist', 'index.html')) + win.loadFile(path.join(app.getAppPath(), 'out', 'renderer', 'index.html')) } if (startHideWindow) { @@ -401,7 +405,7 @@ function registerShowHideShortcut (showHideShortcut) { function initApp () { if (isMac) { app.whenReady().then(() => { - app.dock.setIcon(path.join(__dirname, '../extra/icons/512x512-2.png')) + app.dock.setIcon(path.join(_dirname, '../extra/icons/512x512-2.png')) }) } diff --git a/packages/gui/src/utils/util.apppath.js b/packages/gui/src/main/utils/util.apppath.js similarity index 100% rename from packages/gui/src/utils/util.apppath.js rename to packages/gui/src/main/utils/util.apppath.js diff --git a/packages/gui/src/utils/util.log.gui.js b/packages/gui/src/main/utils/util.log.gui.js similarity index 100% rename from packages/gui/src/utils/util.log.gui.js rename to packages/gui/src/main/utils/util.log.gui.js diff --git a/packages/gui/src/preload/index.js b/packages/gui/src/preload/index.js new file mode 100644 index 0000000000..82a7a8d60d --- /dev/null +++ b/packages/gui/src/preload/index.js @@ -0,0 +1,19 @@ +import { contextBridge, ipcRenderer, shell } from 'electron' + +// 通过 contextBridge 暴露安全的 API 给渲染进程 +contextBridge.exposeInMainWorld('electron', { + // ipcRenderer 相关方法 + ipcRenderer: { + send: (channel, ...args) => ipcRenderer.send(channel, ...args), + on: (channel, callback) => ipcRenderer.on(channel, callback), + once: (channel, callback) => ipcRenderer.once(channel, callback), + removeListener: (channel, callback) => ipcRenderer.removeListener(channel, callback), + removeAllListeners: (channel) => ipcRenderer.removeAllListeners(channel), + invoke: (channel, ...args) => ipcRenderer.invoke(channel, ...args), + }, + // shell 相关方法 + shell: { + openExternal: (url) => shell.openExternal(url), + openPath: (path) => shell.openPath(path), + }, +}) diff --git a/packages/gui/public/index.html b/packages/gui/src/renderer/index.html similarity index 64% rename from packages/gui/public/index.html rename to packages/gui/src/renderer/index.html index 1b8de0d375..05f6ed4a49 100644 --- a/packages/gui/public/index.html +++ b/packages/gui/src/renderer/index.html @@ -2,10 +2,9 @@
- - -