mirror of
https://github.com/electron-vite/electron-vite-vue
synced 2025-01-19 11:56:36 +08:00
refactor: better script and vite-config
This commit is contained in:
parent
6e184ad54c
commit
77046fc5b5
@ -1,10 +1,12 @@
|
|||||||
import os from 'os'
|
import { app, BrowserWindow, shell } from 'electron'
|
||||||
import path from 'path'
|
import { release } from 'os'
|
||||||
import { app, BrowserWindow } from 'electron'
|
import { join } from 'path'
|
||||||
|
|
||||||
// https://stackoverflow.com/questions/42524606/how-to-get-windows-version-using-node-js
|
// Disable GPU Acceleration for Windows 7
|
||||||
const isWin7 = os.release().startsWith('6.1')
|
if (release().startsWith('6.1')) app.disableHardwareAcceleration()
|
||||||
if (isWin7) app.disableHardwareAcceleration()
|
|
||||||
|
// Set application name for Windows 10+ notifications
|
||||||
|
if (process.platform === 'win32') app.setAppUserModelId(app.getName())
|
||||||
|
|
||||||
if (!app.requestSingleInstanceLock()) {
|
if (!app.requestSingleInstanceLock()) {
|
||||||
app.quit()
|
app.quit()
|
||||||
@ -15,34 +17,44 @@ let win: BrowserWindow | null = null
|
|||||||
|
|
||||||
async function createWindow() {
|
async function createWindow() {
|
||||||
win = new BrowserWindow({
|
win = new BrowserWindow({
|
||||||
|
title: 'Main window',
|
||||||
webPreferences: {
|
webPreferences: {
|
||||||
preload: path.join(__dirname, '../preload/index.cjs'),
|
preload: join(__dirname, '../preload/index.cjs')
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
if (app.isPackaged) {
|
if (app.isPackaged) {
|
||||||
win.loadFile(path.join(__dirname, '../renderer/index.html'))
|
win.loadFile(join(__dirname, '../renderer/index.html'))
|
||||||
} else {
|
} else {
|
||||||
const pkg = await import('../../package.json')
|
// 🚧 Use ['ENV_NAME'] avoid vite:define plugin
|
||||||
const url = `http://${pkg.env.HOST || '127.0.0.1'}:${pkg.env.PORT}`
|
const url = `http://${process.env['VITE_DEV_SERVER_HOST']}:${process.env['VITE_DEV_SERVER_PORT']}`
|
||||||
|
|
||||||
win.loadURL(url)
|
win.loadURL(url)
|
||||||
win.webContents.openDevTools()
|
win.webContents.openDevTools()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Test active push message to Renderer-process
|
||||||
|
win.webContents.on('did-finish-load', () => {
|
||||||
|
win?.webContents.send('main-process-message', (new Date).toLocaleString())
|
||||||
|
})
|
||||||
|
|
||||||
|
// Make all links open with the browser, not with the application
|
||||||
|
win.webContents.setWindowOpenHandler(({ url }) => {
|
||||||
|
if (url.startsWith('https:')) shell.openExternal(url)
|
||||||
|
return { action: 'deny' }
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
app.whenReady().then(createWindow)
|
app.whenReady().then(createWindow)
|
||||||
|
|
||||||
app.on('window-all-closed', () => {
|
app.on('window-all-closed', () => {
|
||||||
win = null
|
win = null
|
||||||
if (process.platform !== 'darwin') {
|
if (process.platform !== 'darwin') app.quit()
|
||||||
app.quit()
|
|
||||||
}
|
|
||||||
})
|
})
|
||||||
|
|
||||||
app.on('second-instance', () => {
|
app.on('second-instance', () => {
|
||||||
if (win) {
|
if (win) {
|
||||||
// someone tried to run a second instance, we should focus our window.
|
// Focus on the main window if the user tried to open another
|
||||||
if (win.isMinimized()) win.restore()
|
if (win.isMinimized()) win.restore()
|
||||||
win.focus()
|
win.focus()
|
||||||
}
|
}
|
||||||
@ -56,15 +68,3 @@ app.on('activate', () => {
|
|||||||
createWindow()
|
createWindow()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
// @TODO
|
|
||||||
// auto update
|
|
||||||
/* if (app.isPackaged) {
|
|
||||||
app.whenReady()
|
|
||||||
.then(() => import('electron-updater'))
|
|
||||||
.then(({ autoUpdater }) => autoUpdater.checkForUpdatesAndNotify())
|
|
||||||
.catch((e) =>
|
|
||||||
// maybe you need to record some log files.
|
|
||||||
console.error('Failed check update:', e)
|
|
||||||
)
|
|
||||||
} */
|
|
||||||
|
24
packages/main/vite.config.ts
Normal file
24
packages/main/vite.config.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { builtinModules } from 'module'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import pkg from '../../package.json'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist/main',
|
||||||
|
lib: {
|
||||||
|
entry: 'index.ts',
|
||||||
|
formats: ['cjs'],
|
||||||
|
fileName: () => '[name].cjs',
|
||||||
|
},
|
||||||
|
minify: process.env./* from mode option */NODE_ENV === 'production',
|
||||||
|
emptyOutDir: true,
|
||||||
|
rollupOptions: {
|
||||||
|
external: [
|
||||||
|
'electron',
|
||||||
|
...builtinModules,
|
||||||
|
...Object.keys(pkg.dependencies || {}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
@ -1,22 +1,22 @@
|
|||||||
import fs from 'fs'
|
import fs from 'fs'
|
||||||
import { contextBridge, ipcRenderer, IpcRenderer } from 'electron'
|
import { contextBridge, ipcRenderer } from 'electron'
|
||||||
import { domReady } from './utils'
|
import { domReady } from './utils'
|
||||||
import { useLoading } from './loading'
|
import { useLoading } from './loading'
|
||||||
|
|
||||||
const isDev = process.env.NODE_ENV === 'development'
|
const { appendLoading, removeLoading } = useLoading()
|
||||||
const { removeLoading, appendLoading } = useLoading()
|
|
||||||
|
;(async () => {
|
||||||
|
await domReady()
|
||||||
|
|
||||||
domReady().then(() => {
|
|
||||||
appendLoading()
|
appendLoading()
|
||||||
})
|
})()
|
||||||
|
|
||||||
|
// --------- Expose some API to the Renderer process. ---------
|
||||||
// --------- Expose some API to Renderer process. ---------
|
|
||||||
contextBridge.exposeInMainWorld('fs', fs)
|
contextBridge.exposeInMainWorld('fs', fs)
|
||||||
contextBridge.exposeInMainWorld('removeLoading', removeLoading)
|
contextBridge.exposeInMainWorld('removeLoading', removeLoading)
|
||||||
contextBridge.exposeInMainWorld('ipcRenderer', withPrototype(ipcRenderer))
|
contextBridge.exposeInMainWorld('ipcRenderer', withPrototype(ipcRenderer))
|
||||||
|
|
||||||
// `exposeInMainWorld` can not detect `prototype` attribute and methods, manually patch it.
|
// `exposeInMainWorld` can't detect attributes and methods of `prototype`, manually patching it.
|
||||||
function withPrototype(obj: Record<string, any>) {
|
function withPrototype(obj: Record<string, any>) {
|
||||||
const protos = Object.getPrototypeOf(obj)
|
const protos = Object.getPrototypeOf(obj)
|
||||||
|
|
||||||
@ -24,7 +24,7 @@ function withPrototype(obj: Record<string, any>) {
|
|||||||
if (Object.prototype.hasOwnProperty.call(obj, key)) continue
|
if (Object.prototype.hasOwnProperty.call(obj, key)) continue
|
||||||
|
|
||||||
if (typeof value === 'function') {
|
if (typeof value === 'function') {
|
||||||
// Some native API not work in Renderer-process, like `NodeJS.EventEmitter['on']`. Wrap a function patch it.
|
// Some native APIs, like `NodeJS.EventEmitter['on']`, don't work in the Renderer process. Wrapping them into a function.
|
||||||
obj[key] = function (...args: any) {
|
obj[key] = function (...args: any) {
|
||||||
return value.call(obj, ...args)
|
return value.call(obj, ...args)
|
||||||
}
|
}
|
||||||
|
24
packages/preload/vite.config.ts
Normal file
24
packages/preload/vite.config.ts
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import { builtinModules } from 'module'
|
||||||
|
import { defineConfig } from 'vite'
|
||||||
|
import pkg from '../../package.json'
|
||||||
|
|
||||||
|
export default defineConfig({
|
||||||
|
root: __dirname,
|
||||||
|
build: {
|
||||||
|
outDir: '../../dist/preload',
|
||||||
|
lib: {
|
||||||
|
entry: 'index.ts',
|
||||||
|
formats: ['cjs'],
|
||||||
|
fileName: () => '[name].cjs',
|
||||||
|
},
|
||||||
|
minify: process.env./* from mode option */NODE_ENV === 'production',
|
||||||
|
emptyOutDir: true,
|
||||||
|
rollupOptions: {
|
||||||
|
external: [
|
||||||
|
'electron',
|
||||||
|
...builtinModules,
|
||||||
|
...Object.keys(pkg.dependencies || {}),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
},
|
||||||
|
})
|
@ -14,6 +14,7 @@ import HelloWorld from './components/HelloWorld.vue'
|
|||||||
</div>
|
</div>
|
||||||
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
|
<HelloWorld msg="Hello Vue 3 + TypeScript + Vite" />
|
||||||
<div class="static-public">
|
<div class="static-public">
|
||||||
|
asjdfljasldfjasldfjlsdjflskjdf-----------
|
||||||
Place static files into the <code>src/renderer/public</code> folder
|
Place static files into the <code>src/renderer/public</code> folder
|
||||||
<img style="width:90px;" :src="'./images/node.png'" />
|
<img style="width:90px;" :src="'./images/node.png'" />
|
||||||
</div>
|
</div>
|
||||||
|
@ -5,5 +5,10 @@ createApp(App)
|
|||||||
.mount('#app')
|
.mount('#app')
|
||||||
.$nextTick(window.removeLoading)
|
.$nextTick(window.removeLoading)
|
||||||
|
|
||||||
console.log('fs', window.fs)
|
// console.log('fs', window.fs)
|
||||||
console.log('ipcRenderer', window.ipcRenderer)
|
// console.log('ipcRenderer', window.ipcRenderer)
|
||||||
|
|
||||||
|
// Usage of ipcRenderer.on
|
||||||
|
window.ipcRenderer.on('main-process-message', (_event, ...args) => {
|
||||||
|
console.log('[Receive Main-process message]:', ...args)
|
||||||
|
})
|
||||||
|
@ -1,4 +1,3 @@
|
|||||||
import { join } from 'path'
|
|
||||||
import { builtinModules } from 'module'
|
import { builtinModules } from 'module'
|
||||||
import { defineConfig, Plugin } from 'vite'
|
import { defineConfig, Plugin } from 'vite'
|
||||||
import vue from '@vitejs/plugin-vue'
|
import vue from '@vitejs/plugin-vue'
|
||||||
@ -13,11 +12,12 @@ export default defineConfig({
|
|||||||
vue(),
|
vue(),
|
||||||
resolveElectron(
|
resolveElectron(
|
||||||
/**
|
/**
|
||||||
* you can custom other module in here
|
* Here you can specify other modules
|
||||||
* 🚧 need to make sure custom-resolve-module in `dependencies`, that will ensure that the electron-builder can package them correctly
|
* 🚧 You have to make sure that your module is in `dependencies` and not in the` devDependencies`,
|
||||||
|
* which will ensure that the electron-builder can package it correctly
|
||||||
* @example
|
* @example
|
||||||
* {
|
* {
|
||||||
* 'electron-store': 'const Store = require("electron-store"); export defalut Store;',
|
* 'electron-store': 'const Store = require("electron-store"); export default Store;',
|
||||||
* }
|
* }
|
||||||
*/
|
*/
|
||||||
),
|
),
|
||||||
@ -28,17 +28,22 @@ export default defineConfig({
|
|||||||
outDir: '../../dist/renderer',
|
outDir: '../../dist/renderer',
|
||||||
},
|
},
|
||||||
server: {
|
server: {
|
||||||
host: pkg.env.HOST,
|
|
||||||
port: pkg.env.PORT,
|
port: pkg.env.PORT,
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
// ------- For use Electron, NodeJs in Renderer-process -------
|
/**
|
||||||
// https://github.com/caoxiemeihao/electron-vue-vite/issues/52
|
* For usage of Electron and NodeJS APIs in the Renderer process
|
||||||
export function resolveElectron(resolves: Parameters<typeof resolve>[0] = {}): Plugin {
|
* @see https://github.com/caoxiemeihao/electron-vue-vite/issues/52
|
||||||
const builtins = builtinModules.filter(t => !t.startsWith('_'))
|
*/
|
||||||
|
export function resolveElectron(
|
||||||
|
resolves: Parameters<typeof resolve>[0] = {}
|
||||||
|
): Plugin {
|
||||||
|
const builtins = builtinModules.filter((t) => !t.startsWith('_'))
|
||||||
|
|
||||||
// https://github.com/caoxiemeihao/vite-plugins/tree/main/packages/resolve#readme
|
/**
|
||||||
|
* @see https://github.com/caoxiemeihao/vite-plugins/tree/main/packages/resolve#readme
|
||||||
|
*/
|
||||||
return resolve({
|
return resolve({
|
||||||
electron: electronExport(),
|
electron: electronExport(),
|
||||||
...builtinModulesExport(builtins),
|
...builtinModulesExport(builtins),
|
||||||
@ -48,7 +53,7 @@ export function resolveElectron(resolves: Parameters<typeof resolve>[0] = {}): P
|
|||||||
function electronExport() {
|
function electronExport() {
|
||||||
return `
|
return `
|
||||||
/**
|
/**
|
||||||
* All exports module see https://www.electronjs.org -> API -> Renderer Process Modules
|
* For all exported modules see https://www.electronjs.org/docs/latest/api/clipboard -> Renderer Process Modules
|
||||||
*/
|
*/
|
||||||
const electron = require("electron");
|
const electron = require("electron");
|
||||||
const {
|
const {
|
||||||
@ -62,7 +67,7 @@ export function resolveElectron(resolves: Parameters<typeof resolve>[0] = {}): P
|
|||||||
desktopCapturer,
|
desktopCapturer,
|
||||||
deprecate,
|
deprecate,
|
||||||
} = electron;
|
} = electron;
|
||||||
|
|
||||||
export {
|
export {
|
||||||
electron as default,
|
electron as default,
|
||||||
clipboard,
|
clipboard,
|
||||||
@ -75,24 +80,29 @@ export function resolveElectron(resolves: Parameters<typeof resolve>[0] = {}): P
|
|||||||
desktopCapturer,
|
desktopCapturer,
|
||||||
deprecate,
|
deprecate,
|
||||||
}
|
}
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|
||||||
function builtinModulesExport(modules: string[]) {
|
function builtinModulesExport(modules: string[]) {
|
||||||
return modules.map((moduleId) => {
|
return modules
|
||||||
const nodeModule = require(moduleId)
|
.map((moduleId) => {
|
||||||
const requireModule = `const M = require("${moduleId}");`
|
const nodeModule = require(moduleId)
|
||||||
const exportDefault = `export default M;`
|
const requireModule = `const M = require("${moduleId}");`
|
||||||
const exportMembers = Object.keys(nodeModule).map(attr => `export const ${attr} = M.${attr}`).join(';\n') + ';'
|
const exportDefault = `export default M;`
|
||||||
const nodeModuleCode = `
|
const exportMembers =
|
||||||
|
Object.keys(nodeModule)
|
||||||
|
.map((attr) => `export const ${attr} = M.${attr}`)
|
||||||
|
.join(';\n') + ';'
|
||||||
|
const nodeModuleCode = `
|
||||||
${requireModule}
|
${requireModule}
|
||||||
|
|
||||||
${exportDefault}
|
${exportDefault}
|
||||||
|
|
||||||
${exportMembers}
|
${exportMembers}
|
||||||
`
|
`
|
||||||
|
|
||||||
return { [moduleId]: nodeModuleCode }
|
return { [moduleId]: nodeModuleCode }
|
||||||
}).reduce((memo, item) => Object.assign(memo, item), {})
|
})
|
||||||
|
.reduce((memo, item) => Object.assign(memo, item), {})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -1,25 +1,5 @@
|
|||||||
process.env.NODE_ENV = 'production'
|
|
||||||
|
|
||||||
import { dirname, join } from 'path'
|
|
||||||
import { fileURLToPath } from 'url'
|
|
||||||
import { build } from 'vite'
|
import { build } from 'vite'
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
await build({ configFile: 'packages/main/vite.config.ts' })
|
||||||
|
await build({ configFile: 'packages/preload/vite.config.ts' })
|
||||||
await build({
|
|
||||||
configFile: 'scripts/vite.config.mjs',
|
|
||||||
root: join(__dirname, '../packages/main'),
|
|
||||||
build: {
|
|
||||||
outDir: '../../dist/main',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
await build({
|
|
||||||
configFile: 'scripts/vite.config.mjs',
|
|
||||||
root: join(__dirname, '../packages/preload'),
|
|
||||||
build: {
|
|
||||||
outDir: '../../dist/preload',
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
await build({ configFile: 'packages/renderer/vite.config.ts' })
|
await build({ configFile: 'packages/renderer/vite.config.ts' })
|
||||||
|
@ -1,32 +0,0 @@
|
|||||||
import { builtinModules, createRequire } from 'module'
|
|
||||||
import { defineConfig } from 'vite'
|
|
||||||
|
|
||||||
const require = createRequire(import.meta.url)
|
|
||||||
const pkg = require('../package.json')
|
|
||||||
|
|
||||||
export default defineConfig({
|
|
||||||
mode: process.env.NODE_ENV,
|
|
||||||
// root: [path],
|
|
||||||
build: {
|
|
||||||
// outDir: [path],
|
|
||||||
lib: {
|
|
||||||
entry: 'index.ts',
|
|
||||||
formats: ['cjs'],
|
|
||||||
fileName: () => '[name].cjs',
|
|
||||||
},
|
|
||||||
minify: process.env.NODE_ENV === 'production',
|
|
||||||
emptyOutDir: true,
|
|
||||||
rollupOptions: {
|
|
||||||
external: [
|
|
||||||
'electron',
|
|
||||||
...builtinModules,
|
|
||||||
...Object.keys(pkg.dependencies || {}),
|
|
||||||
],
|
|
||||||
},
|
|
||||||
},
|
|
||||||
})
|
|
||||||
|
|
||||||
/**
|
|
||||||
* 2202-02-05
|
|
||||||
* @todo process.env.NODE_ENV always return true, need to submit PR to vite and improvement vite:define plugin.
|
|
||||||
*/
|
|
@ -1,42 +1,34 @@
|
|||||||
process.env.NODE_ENV = 'development'
|
|
||||||
|
|
||||||
import { fileURLToPath } from 'url'
|
|
||||||
import { join, dirname } from 'path'
|
|
||||||
import { createRequire } from 'module'
|
|
||||||
import { spawn } from 'child_process'
|
import { spawn } from 'child_process'
|
||||||
import { createServer, build } from 'vite'
|
import { createServer, build } from 'vite'
|
||||||
import electron from 'electron'
|
import electron from 'electron'
|
||||||
|
|
||||||
const __dirname = dirname(fileURLToPath(import.meta.url))
|
|
||||||
const require = createRequire(import.meta.url)
|
|
||||||
const pkg = require('../package.json')
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @type {() => Promise<import('rollup').RollupWatcher>}
|
* @type {(server: import('vite').ViteDevServer) => Promise<import('rollup').RollupWatcher>}
|
||||||
*/
|
*/
|
||||||
function watchMain() {
|
function watchMain(server) {
|
||||||
/**
|
/**
|
||||||
* @type {import('child_process').ChildProcessWithoutNullStreams | null}
|
* @type {import('child_process').ChildProcessWithoutNullStreams | null}
|
||||||
*/
|
*/
|
||||||
let electronProcess = null
|
let electronProcess = null
|
||||||
|
const address = server.httpServer.address()
|
||||||
|
const env = Object.assign(process.env, {
|
||||||
|
VITE_DEV_SERVER_HOST: address.address,
|
||||||
|
VITE_DEV_SERVER_PORT: address.port,
|
||||||
|
})
|
||||||
|
|
||||||
return build({
|
return build({
|
||||||
configFile: 'scripts/vite.config.mjs',
|
configFile: 'packages/main/vite.config.ts',
|
||||||
root: join(__dirname, '../packages/main'),
|
mode: 'development',
|
||||||
build: {
|
|
||||||
outDir: '../../dist/main',
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
plugins: [{
|
plugins: [{
|
||||||
name: 'electron-main-watcher',
|
name: 'electron-main-watcher',
|
||||||
writeBundle() {
|
writeBundle() {
|
||||||
electronProcess && electronProcess.kill()
|
electronProcess && electronProcess.kill()
|
||||||
electronProcess = spawn(electron, ['.'], {
|
electronProcess = spawn(electron, ['.'], { stdio: 'inherit', env })
|
||||||
stdio: 'inherit',
|
|
||||||
env: Object.assign(process.env, pkg.env),
|
|
||||||
})
|
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
|
build: {
|
||||||
|
watch: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -45,18 +37,17 @@ function watchMain() {
|
|||||||
*/
|
*/
|
||||||
function watchPreload(server) {
|
function watchPreload(server) {
|
||||||
return build({
|
return build({
|
||||||
configFile: 'scripts/vite.config.mjs',
|
configFile: 'packages/preload/vite.config.ts',
|
||||||
root: join(__dirname, '../packages/preload'),
|
mode: 'development',
|
||||||
build: {
|
|
||||||
outDir: '../../dist/preload',
|
|
||||||
watch: true,
|
|
||||||
},
|
|
||||||
plugins: [{
|
plugins: [{
|
||||||
name: 'electron-preload-watcher',
|
name: 'electron-preload-watcher',
|
||||||
writeBundle() {
|
writeBundle() {
|
||||||
server.ws.send({ type: 'full-reload' })
|
server.ws.send({ type: 'full-reload' })
|
||||||
},
|
},
|
||||||
}],
|
}],
|
||||||
|
build: {
|
||||||
|
watch: true,
|
||||||
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -65,4 +56,4 @@ const server = await createServer({ configFile: 'packages/renderer/vite.config.t
|
|||||||
|
|
||||||
await server.listen()
|
await server.listen()
|
||||||
await watchPreload(server)
|
await watchPreload(server)
|
||||||
await watchMain()
|
await watchMain(server)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user