feat(electron): improve electron build configuration
- Add dedicated electron build scripts for each platform - Configure Vite rollup options for electron builds - Update electron-builder configuration with proper app metadata - Add clean script and rimraf dependency - Set proper appId and build settings for production builds - Enable asar packaging for better security
This commit is contained in:
152
package-lock.json
generated
152
package-lock.json
generated
@@ -100,6 +100,7 @@
|
||||
"npm-check-updates": "^17.1.13",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.2.5",
|
||||
"rimraf": "^6.0.1",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "~5.2.2",
|
||||
"vite": "^5.2.0",
|
||||
@@ -2628,6 +2629,66 @@
|
||||
"node": ">=18.0.0"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/cli/node_modules/glob": {
|
||||
"version": "9.3.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz",
|
||||
"integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"minimatch": "^8.0.2",
|
||||
"minipass": "^4.2.4",
|
||||
"path-scurry": "^1.6.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/cli/node_modules/minimatch": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz",
|
||||
"integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/cli/node_modules/minipass": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz",
|
||||
"integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==",
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/cli/node_modules/rimraf": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz",
|
||||
"integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==",
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^9.2.0"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "dist/cjs/src/bin.js"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/@capacitor/core": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@capacitor/core/-/core-6.2.0.tgz",
|
||||
@@ -23165,63 +23226,106 @@
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf": {
|
||||
"version": "4.4.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-4.4.1.tgz",
|
||||
"integrity": "sha512-Gk8NlF062+T9CqNGn6h4tls3k6T1+/nXdOcSZVikNVtlRdYpA7wRJJMoXmuvOnLW844rPjdQ7JgXCYM6PPC/og==",
|
||||
"version": "6.0.1",
|
||||
"resolved": "https://registry.npmjs.org/rimraf/-/rimraf-6.0.1.tgz",
|
||||
"integrity": "sha512-9dkvaxAsk/xNXSJzMgFqqMCuFgt2+KsOFek3TMLfo8NCPfWpBmqwyNn5Y+NX56QUYfCtsyhF3ayiboEoUmJk/A==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"glob": "^9.2.0"
|
||||
"glob": "^11.0.0",
|
||||
"package-json-from-dist": "^1.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"rimraf": "dist/cjs/src/bin.js"
|
||||
"rimraf": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/glob": {
|
||||
"version": "9.3.5",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-9.3.5.tgz",
|
||||
"integrity": "sha512-e1LleDykUz2Iu+MTYdkSsuWX8lvAjAcs0Xef0lNIu0S2wOAzuTxCJtcd9S3cijlwYF18EsU3rzb8jPVobxDh9Q==",
|
||||
"version": "11.0.1",
|
||||
"resolved": "https://registry.npmjs.org/glob/-/glob-11.0.1.tgz",
|
||||
"integrity": "sha512-zrQDm8XPnYEKawJScsnM0QzobJxlT/kHOOlRTio8IH/GrmxRE5fjllkzdaHclIuNjUQTJYH2xHNIGfdpJkDJUw==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"fs.realpath": "^1.0.0",
|
||||
"minimatch": "^8.0.2",
|
||||
"minipass": "^4.2.4",
|
||||
"path-scurry": "^1.6.1"
|
||||
"foreground-child": "^3.1.0",
|
||||
"jackspeak": "^4.0.1",
|
||||
"minimatch": "^10.0.0",
|
||||
"minipass": "^7.1.2",
|
||||
"package-json-from-dist": "^1.0.0",
|
||||
"path-scurry": "^2.0.0"
|
||||
},
|
||||
"bin": {
|
||||
"glob": "dist/esm/bin.mjs"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/jackspeak": {
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/jackspeak/-/jackspeak-4.0.3.tgz",
|
||||
"integrity": "sha512-oSwM7q8PTHQWuZAlp995iPpPJ4Vkl7qT0ZRD+9duL9j2oBy6KcTfyxc8mEuHJYC+z/kbps80aJLkaNzTOrf/kw==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"@isaacs/cliui": "^8.0.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/lru-cache": {
|
||||
"version": "11.0.2",
|
||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-11.0.2.tgz",
|
||||
"integrity": "sha512-123qHRfJBmo2jXDbo/a5YOQrJoHF/GNQTLzQ5+IdK5pWpceK17yRc6ozlWd25FxvGKQbIUs91fDFkXmDHTKcyA==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"engines": {
|
||||
"node": "20 || >=22"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/minimatch": {
|
||||
"version": "8.0.4",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-8.0.4.tgz",
|
||||
"integrity": "sha512-W0Wvr9HyFXZRGIDgCicunpQ299OKXs9RgZfaukz4qAW/pJhcpUfupc9c+OObPOFueNy8VSrZgEmDtk6Kh4WzDA==",
|
||||
"version": "10.0.1",
|
||||
"resolved": "https://registry.npmjs.org/minimatch/-/minimatch-10.0.1.tgz",
|
||||
"integrity": "sha512-ethXTt3SGGR+95gudmqJ1eNhRO7eGEGIgYA9vnPatK4/etz2MEVDno5GMCibdMTuBMyElzIlgxMna3K94XDIDQ==",
|
||||
"dev": true,
|
||||
"license": "ISC",
|
||||
"dependencies": {
|
||||
"brace-expansion": "^2.0.1"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=16 || 14 >=14.17"
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/rimraf/node_modules/minipass": {
|
||||
"version": "4.2.8",
|
||||
"resolved": "https://registry.npmjs.org/minipass/-/minipass-4.2.8.tgz",
|
||||
"integrity": "sha512-fNzuVyifolSLFL4NzpF+wEF4qrgqaaKX0haXPQEdQ7NKAN+WecoKMHV09YcuL/DHxrUsYQOK3MiuDf7Ip2OXfQ==",
|
||||
"license": "ISC",
|
||||
"node_modules/rimraf/node_modules/path-scurry": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/path-scurry/-/path-scurry-2.0.0.tgz",
|
||||
"integrity": "sha512-ypGJsmGtdXUOeM5u93TyeIEfEhM6s+ljAhrk5vAvSx8uyY/02OvrZnA0YNGUrPXfpJMgI1ODd3nwz8Npx4O4cg==",
|
||||
"dev": true,
|
||||
"license": "BlueOak-1.0.0",
|
||||
"dependencies": {
|
||||
"lru-cache": "^11.0.0",
|
||||
"minipass": "^7.1.2"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
"node": "20 || >=22"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://github.com/sponsors/isaacs"
|
||||
}
|
||||
},
|
||||
"node_modules/ripemd160": {
|
||||
|
||||
38
package.json
38
package.json
@@ -1,6 +1,10 @@
|
||||
{
|
||||
"name": "TimeSafari",
|
||||
"version": "0.3.54-beta",
|
||||
"description": "TimeSafari Desktop Application",
|
||||
"author": {
|
||||
"name": "TimeSafari Team"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "vite",
|
||||
"serve": "vite preview",
|
||||
@@ -9,7 +13,14 @@
|
||||
"lint-fix": "eslint --ext .js,.ts,.vue --ignore-path .gitignore --fix src",
|
||||
"prebuild": "eslint --ext .js,.ts,.vue --ignore-path .gitignore src && node sw_combine.js",
|
||||
"test-local": "npx playwright test -c playwright.config-local.ts --trace on",
|
||||
"test-all": "npm run build && npx playwright test -c playwright.config-local.ts --trace on"
|
||||
"test-all": "npm run build && npx playwright test -c playwright.config-local.ts --trace on",
|
||||
"clean:electron": "rimraf dist-electron dist-electron-build",
|
||||
"build:electron": "npm run clean:electron && vite build --mode electron && node scripts/build-electron.js",
|
||||
"build:capacitor": "vite build --mode capacitor",
|
||||
"build:web": "vite build",
|
||||
"electron:build:linux": "npm run build:electron && electron-builder --linux",
|
||||
"electron:build:mac": "npm run build:electron && npx electron-builder --mac",
|
||||
"electron:build:win": "npm run build:electron && npx electron-builder --win"
|
||||
},
|
||||
"dependencies": {
|
||||
"@capacitor/android": "^6.2.0",
|
||||
@@ -104,30 +115,31 @@
|
||||
"npm-check-updates": "^17.1.13",
|
||||
"postcss": "^8.4.38",
|
||||
"prettier": "^3.2.5",
|
||||
"rimraf": "^6.0.1",
|
||||
"tailwindcss": "^3.4.1",
|
||||
"typescript": "~5.2.2",
|
||||
"vite": "^5.2.0",
|
||||
"vite-plugin-pwa": "^0.19.8"
|
||||
},
|
||||
"main": "main.js",
|
||||
"build": {
|
||||
"appId": "com.example.app",
|
||||
"appId": "app.timesafari.app",
|
||||
"productName": "TimeSafari",
|
||||
"directories": {
|
||||
"output": "dist-electron-build"
|
||||
},
|
||||
"files": [
|
||||
"dist-electron/**",
|
||||
"src/electron/**"
|
||||
{
|
||||
"from": "dist-electron",
|
||||
"to": ".",
|
||||
"filter": ["**/*"]
|
||||
}
|
||||
],
|
||||
"mac": {
|
||||
"target": "dmg"
|
||||
},
|
||||
"win": {
|
||||
"target": "nsis"
|
||||
},
|
||||
"linux": {
|
||||
"target": "AppImage"
|
||||
"target": ["AppImage"],
|
||||
"category": "Utility",
|
||||
"icon": "build/icons"
|
||||
},
|
||||
"asar": false
|
||||
"asar": true
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
72
scripts/build-electron.js
Normal file
72
scripts/build-electron.js
Normal file
@@ -0,0 +1,72 @@
|
||||
const fs = require('fs-extra');
|
||||
const path = require('path');
|
||||
|
||||
async function main() {
|
||||
try {
|
||||
console.log('Starting electron build process...');
|
||||
|
||||
// Clean directories
|
||||
const distElectronDir = path.resolve(__dirname, '../dist-electron');
|
||||
const buildDir = path.resolve(__dirname, '../dist-electron-build');
|
||||
await fs.emptyDir(distElectronDir);
|
||||
await fs.emptyDir(buildDir);
|
||||
console.log('Cleaned directories');
|
||||
|
||||
// First build the web app if it doesn't exist
|
||||
const webDist = path.resolve(__dirname, '../dist');
|
||||
if (!await fs.pathExists(webDist)) {
|
||||
console.log('Web dist not found, building web app first...');
|
||||
throw new Error('Please run \'npm run build\' first to build the web app');
|
||||
}
|
||||
|
||||
// Copy web files to www directory
|
||||
const wwwDir = path.join(distElectronDir, 'www');
|
||||
await fs.copy(webDist, wwwDir);
|
||||
console.log('Copied web files to:', wwwDir);
|
||||
|
||||
// Copy and process main.js
|
||||
const mainJsSrc = path.resolve(__dirname, '../src/electron/main.js');
|
||||
const mainJsDest = path.join(distElectronDir, 'main.js');
|
||||
await fs.copy(mainJsSrc, mainJsDest);
|
||||
console.log('Copied main.js to:', mainJsDest);
|
||||
|
||||
// Create the production package.json
|
||||
const devPackageJson = require('../package.json');
|
||||
const prodPackageJson = {
|
||||
name: devPackageJson.name,
|
||||
version: devPackageJson.version,
|
||||
description: devPackageJson.description,
|
||||
author: devPackageJson.author,
|
||||
main: 'main.js',
|
||||
private: true
|
||||
};
|
||||
|
||||
await fs.writeJson(
|
||||
path.join(distElectronDir, 'package.json'),
|
||||
prodPackageJson,
|
||||
{ spaces: 2 }
|
||||
);
|
||||
|
||||
// Verify the structure
|
||||
console.log('\nVerifying build structure:');
|
||||
const printDir = async (dir, prefix = '') => {
|
||||
const items = await fs.readdir(dir);
|
||||
for (const item of items) {
|
||||
const fullPath = path.join(dir, item);
|
||||
const stat = await fs.stat(fullPath);
|
||||
console.log(`${prefix}${item}${stat.isDirectory() ? '/' : ''}`);
|
||||
if (stat.isDirectory()) {
|
||||
await printDir(fullPath, `${prefix} `);
|
||||
}
|
||||
}
|
||||
};
|
||||
await printDir(distElectronDir);
|
||||
|
||||
console.log('\nBuild completed successfully!');
|
||||
} catch (error) {
|
||||
console.error('Build failed:', error);
|
||||
process.exit(1);
|
||||
}
|
||||
}
|
||||
|
||||
main().catch(console.error);
|
||||
@@ -1,46 +1,44 @@
|
||||
const { app, BrowserWindow } = require("electron");
|
||||
const path = require("path");
|
||||
|
||||
let mainWindow;
|
||||
|
||||
app.on("ready", () => {
|
||||
mainWindow = new BrowserWindow({
|
||||
width: 800,
|
||||
height: 600,
|
||||
function createWindow() {
|
||||
// Create the browser window.
|
||||
const mainWindow = new BrowserWindow({
|
||||
width: 1200,
|
||||
height: 800,
|
||||
webPreferences: {
|
||||
//preload: path.join(__dirname, "preload.js"),
|
||||
contextIsolation: true, // Security setting
|
||||
nodeIntegration: true,
|
||||
contextIsolation: false,
|
||||
},
|
||||
});
|
||||
|
||||
const indexPath = path.join(
|
||||
__dirname,
|
||||
"../../",
|
||||
"dist-electron",
|
||||
"index.html",
|
||||
);
|
||||
|
||||
console.log("Loading Vue app from:", indexPath);
|
||||
mainWindow.webContents.openDevTools();
|
||||
|
||||
mainWindow.webContents.on(
|
||||
"did-fail-load",
|
||||
(event, errorCode, errorDescription, validatedURL) => {
|
||||
console.error(
|
||||
"Failed to load:",
|
||||
validatedURL,
|
||||
"Error:",
|
||||
errorDescription,
|
||||
);
|
||||
},
|
||||
);
|
||||
|
||||
mainWindow.webContents.on("console-message", (event, level, message) => {
|
||||
console.log(`[Renderer] ${message}`);
|
||||
});
|
||||
// Log the paths we're trying to load from
|
||||
const appPath = app.getAppPath();
|
||||
const indexPath = path.join(appPath, "www", "index.html");
|
||||
console.log("App path:", appPath);
|
||||
console.log("Trying to load from:", indexPath);
|
||||
|
||||
// Load the index.html file
|
||||
mainWindow.loadFile(indexPath).catch((err) => {
|
||||
console.error("Failed to load index.html:", err);
|
||||
// Try to list directory contents to debug
|
||||
const fs = require("fs");
|
||||
console.log("Directory contents:", fs.readdirSync(appPath));
|
||||
});
|
||||
|
||||
// Open the DevTools in development
|
||||
if (process.env.NODE_ENV === "development") {
|
||||
mainWindow.webContents.openDevTools();
|
||||
}
|
||||
}
|
||||
|
||||
app.whenReady().then(() => {
|
||||
createWindow();
|
||||
|
||||
app.on("activate", () => {
|
||||
if (BrowserWindow.getAllWindows().length === 0) {
|
||||
createWindow();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
@@ -49,3 +47,8 @@ app.on("window-all-closed", () => {
|
||||
app.quit();
|
||||
}
|
||||
});
|
||||
|
||||
// Handle any errors
|
||||
process.on("uncaughtException", (error) => {
|
||||
console.error("Uncaught Exception:", error);
|
||||
});
|
||||
|
||||
@@ -3,6 +3,7 @@ import { VitePWA } from "vite-plugin-pwa";
|
||||
import vue from "@vitejs/plugin-vue";
|
||||
import dotenv from "dotenv";
|
||||
import { loadAppConfig } from "./vite.config.utils";
|
||||
import path from "path";
|
||||
|
||||
// Load environment variables from .env file
|
||||
dotenv.config();
|
||||
@@ -27,7 +28,20 @@ export default defineConfig(({ mode }) => {
|
||||
port: process.env.VITE_PORT || 8080,
|
||||
},
|
||||
build: {
|
||||
outDir, // Dynamically set output directory
|
||||
outDir,
|
||||
rollupOptions: {
|
||||
...(isElectron && {
|
||||
input: {
|
||||
main: path.resolve(__dirname, 'src/electron/main.js'),
|
||||
index: path.resolve(__dirname, 'index.html')
|
||||
},
|
||||
output: {
|
||||
dir: outDir,
|
||||
format: 'cjs',
|
||||
entryFileNames: '[name].js'
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
plugins: [
|
||||
vue(),
|
||||
|
||||
Reference in New Issue
Block a user