refactor: preload communication

This commit is contained in:
草鞋没号 2021-09-09 09:37:02 +08:00
parent 4f7f92cbe7
commit 3be1848c8c
13 changed files with 109 additions and 86 deletions

View File

@ -0,0 +1,12 @@
/**
*
*/
/** 退出 */
export const LOGOUT = '@event/logout'
/** 登录 */
export const LOGIN = '@event/login'
/** 切换开发者工具 */
export const TOGGLE_DEVTOOLS = 'toggle-devtools'

View File

@ -0,0 +1,2 @@
export * as event from './event'

View File

@ -1,5 +0,0 @@
/**
* !!! ensure process.cwd() correct
* for load-on preload.js
*/
// process.chdir(__dirname.slice(0, __dirname.lastIndexOf('dist'))) 21-08-05 remove

View File

@ -0,0 +1,7 @@
import Store from 'electron-store'
export default new Store
export const TOKEN = 'token'
export const USER_INFO = '@user/info'

16
src/main/communication.ts Normal file
View File

@ -0,0 +1,16 @@
/**
* Expose something function to renderer
*/
import { BrowserWindow, ipcMain } from 'electron'
import {
LOGIN,
LOGOUT,
TOGGLE_DEVTOOLS,
} from '@/common/constant/event'
export function register(win: BrowserWindow) {
ipcMain.handle(TOGGLE_DEVTOOLS, () => {
win.webContents.toggleDevTools()
})
ipcMain.handle(LOGOUT, () => { })
}

View File

@ -1,31 +1,28 @@
/** import path from 'path'
* electron
*/
import { join } from 'path'
import { app, BrowserWindow } from 'electron' import { app, BrowserWindow } from 'electron'
import dotenv from 'dotenv' import { register } from './communication'
dotenv.config({ path: join(__dirname, '../../.env') }) let win: BrowserWindow | null = null
let win: BrowserWindow function bootstrap() {
function createWin() {
// 创建浏览器窗口
win = new BrowserWindow({ win = new BrowserWindow({
width: 1024,
height: 768,
webPreferences: { webPreferences: {
nodeIntegration: true, preload: path.join(__dirname, '../preload/index.js'),
contextIsolation: false,
preload: join(__dirname, '../preload/index.js'),
}, },
}) })
const URL = app.isPackaged if (app.isPackaged) {
? `file://${join(__dirname, '../render/index.html')}` // vite 构建后的静态文件地址 win.loadFile(path.join(__dirname, '../render/index.html'))
: `http://localhost:${process.env.PORT}` // vite 启动的服务器地址 } else {
win.maximize()
win.webContents.openDevTools()
win.loadURL(`http://localhost:${process.env.PORT}`)
}
win?.loadURL(URL) // something init setup
register(win)
} }
app.whenReady().then(createWin) app.whenReady().then(bootstrap)
app.on('window-all-closed', () => { win = null })

View File

@ -0,0 +1,8 @@
/**
* Renderer and Main bridge
* @refresh https://newbedev.com/how-to-use-preload-js-properly-in-electron
*/
import { contextBridge, ipcRenderer } from 'electron'
contextBridge.exposeInMainWorld('ipcRenderer', ipcRenderer)

5
src/preload/index.ts Normal file
View File

@ -0,0 +1,5 @@
import './communication'
import { domReady } from './utils/dom'
import { loading } from './loading'
domReady().then(loading)

View File

@ -1,5 +1,4 @@
<!-- Just a loading template -->
<!-- This is just a template file -->
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">

View File

@ -1,28 +1,11 @@
// @ts-nocheck import { contextBridge } from 'electron'
/** docoment 加载完成 */
function domReady(...args) {
const condition = args.length ? [...args] : ['complete', 'interactive']
return new Promise(resolve => {
if (condition.includes(document.readyState)) {
resolve(true)
} else {
document.addEventListener('readystatechange', () => {
if (condition.includes(document.readyState)) {
resolve(true)
}
})
}
})
}
/** 插入 loading */
function loadingBootstrap() { function loadingBootstrap() {
const loadingStyle = document.createElement('style'); const loadingStyle = document.createElement('style')
const loadingBox = document.createElement('div'); const loadingBox = document.createElement('div')
loadingStyle.id = 'preload-loading-style'; loadingStyle.id = 'preload-loading-style'
loadingBox.id = 'preload-loading-box'; loadingBox.id = 'preload-loading-box'
loadingStyle.textContent += ` loadingStyle.textContent += `
/* https://projects.lukehaas.me/css-loaders/ */ /* https://projects.lukehaas.me/css-loaders/ */
@ -96,41 +79,40 @@ function loadingBootstrap() {
box-shadow: 0 -2em; box-shadow: 0 -2em;
height: 5em; height: 5em;
} }
}`; }`
loadingBox.classList.add('loading-box', 'load1'); loadingBox.classList.add('loading-box', 'load1')
loadingBox.innerHTML += '<div class="loader"></div>'; loadingBox.innerHTML += '<div class="loader"></div>'
const appendLoading = () => { const appendLoading = () => {
document.head.appendChild(loadingStyle); document.head.appendChild(loadingStyle)
document.body.appendChild(loadingBox); document.body.appendChild(loadingBox)
}; }
const removeLoading = () => { const removeLoading = () => {
const _loadingStyle = document.getElementById('preload-loading-style'); const _loadingStyle = document.getElementById('preload-loading-style')
const _loadingBox = document.getElementById('preload-loading-box'); const _loadingBox = document.getElementById('preload-loading-box')
// Ensure the remove child exists. // Ensure the remove child exists.
_loadingStyle && document.head.removeChild(_loadingStyle); _loadingStyle && document.head.removeChild(_loadingStyle)
_loadingBox && document.body.removeChild(_loadingBox); _loadingBox && document.body.removeChild(_loadingBox)
}; };
return { loadingStyle, loadingBox, removeLoading, appendLoading } return { loadingStyle, loadingBox, removeLoading, appendLoading }
} }
; (async function () { /** 闪屏 loading */
await domReady(); export function loading() {
let _isCallRemoveLoading = false
let _isCallRemoveLoading = false;
const { removeLoading, appendLoading } = loadingBootstrap(); const { removeLoading, appendLoading } = loadingBootstrap();
window.removeLoading = () => { contextBridge.exposeInMainWorld('removeLoading', () => {
_isCallRemoveLoading = true; _isCallRemoveLoading = true
removeLoading(); removeLoading()
}; })
// 5 秒超时自动关闭 // 5 秒超时自动关闭
setTimeout(() => !_isCallRemoveLoading && removeLoading(), 4999); setTimeout(() => !_isCallRemoveLoading && removeLoading(), 4999)
appendLoading(); appendLoading()
})(); }

15
src/preload/utils/dom.ts Normal file
View File

@ -0,0 +1,15 @@
/** docoment 加载完成 */
export function domReady(condition: DocumentReadyState[] = ['complete', 'interactive']) {
return new Promise(resolve => {
if (condition.includes(document.readyState)) {
resolve(true)
} else {
document.addEventListener('readystatechange', () => {
if (condition.includes(document.readyState)) {
resolve(true)
}
})
}
})
}

View File

@ -3,7 +3,7 @@
<img style="height:200px;" src="./assets/electron.png" alt="Electron logo"> <img style="height:200px;" src="./assets/electron.png" alt="Electron logo">
<img alt="Vue logo" src="./assets/logo.png" /> <img alt="Vue logo" src="./assets/logo.png" />
</div> </div>
<HelloWorld msg="Electron@12、Vue@3、Vite@2" /> <HelloWorld msg="Electron@13、Vue@3、Vite@2" />
</template> </template>
<script> <script>

View File

@ -1,22 +1,7 @@
import { createApp } from 'vue' import { createApp } from 'vue'
import App from './App.vue' import App from './App.vue'
// import fs = require('fs')
import { ipcRenderer } from 'electron'
import Store from 'electron-store'
import './index.css' import './index.css'
setTimeout(() => {
console.log('ipcRenderer:', ipcRenderer)
// Configuration name causes hot updates to be slow | 传递 name 后会导致热更新很慢
// console.log('electron-store', new Store({ name: 'electron-vue' }))
// https://github.com/caoxiemeihao/electron-vue-vite/issues/10
// console.log('electron-store', new Store()) 21-08-05 remove
// new Store 会阻塞线程,导致 preload 动画卡顿
}, 2999)
createApp(App) createApp(App)
.mount('#app') .mount('#app')
.$nextTick(window.removeLoading) .$nextTick(window.removeLoading)