feat: support hot reload preload script
This commit is contained in:
		
							parent
							
								
									d50f500bbd
								
							
						
					
					
						commit
						91384d9f37
					
				| 
						 | 
					@ -1,16 +1,20 @@
 | 
				
			||||||
import fs from 'fs'
 | 
					import fs from 'fs'
 | 
				
			||||||
import path from 'path'
 | 
					import path from 'path'
 | 
				
			||||||
import { contextBridge, ipcRenderer } from 'electron'
 | 
					import { contextBridge, ipcRenderer } from 'electron'
 | 
				
			||||||
import { domReady } from './utils'
 | 
					import { domReady, injectWsCode } from './utils'
 | 
				
			||||||
import { useLoading } from './loading'
 | 
					import { useLoading } from './loading'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const isDev = process.env.NODE_ENV === 'development'
 | 
				
			||||||
const { appendLoading, removeLoading } = useLoading()
 | 
					const { appendLoading, removeLoading } = useLoading()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
; (async () => {
 | 
					; (async () => {
 | 
				
			||||||
  await domReady()
 | 
					  await domReady()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  appendLoading()
 | 
					  appendLoading()
 | 
				
			||||||
 | 
					  isDev && injectWsCode({
 | 
				
			||||||
 | 
					    host: '127.0.0.1',
 | 
				
			||||||
 | 
					    port: process.env.PORT_WS as string,
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// ---------------------------------------------------
 | 
					// ---------------------------------------------------
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,3 +13,37 @@ export function domReady(condition: DocumentReadyState[] = ['complete', 'interac
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  })
 | 
					  })
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					/** Inject ws related code */
 | 
				
			||||||
 | 
					export function injectWsCode(options: {
 | 
				
			||||||
 | 
					  host: string
 | 
				
			||||||
 | 
					  port: string | number
 | 
				
			||||||
 | 
					}) {
 | 
				
			||||||
 | 
					  const oScript = document.createElement('script')
 | 
				
			||||||
 | 
					  oScript.id = 'ws-preload-hot-reload'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  oScript.innerHTML = `
 | 
				
			||||||
 | 
					${__ws_hot_reload_for_preload.toString()}
 | 
				
			||||||
 | 
					${__ws_hot_reload_for_preload.name}(${JSON.stringify(options)})
 | 
				
			||||||
 | 
					`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  document.body.appendChild(oScript)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					function __ws_hot_reload_for_preload(options: { host: string; port: string | number }) {
 | 
				
			||||||
 | 
					  const ws = new WebSocket(`ws://${options.host}:${options.port}`)
 | 
				
			||||||
 | 
					  ws.onmessage = function (ev) {
 | 
				
			||||||
 | 
					    try {
 | 
				
			||||||
 | 
					      console.log('[preload] ws.onmessage:', ev.data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      const data = JSON.parse(ev.data) // { "cmd": "string", data: "string|number" }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					      if (data.cmd === 'reload') {
 | 
				
			||||||
 | 
					        setTimeout(() => window.location.reload(), 999)
 | 
				
			||||||
 | 
					      }
 | 
				
			||||||
 | 
					    } catch (error) {
 | 
				
			||||||
 | 
					      console.warn(`ws.onmessage should be accept "JSON.string" formatted string.`)
 | 
				
			||||||
 | 
					      console.error(error)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					  }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,21 +1,26 @@
 | 
				
			||||||
 | 
					process.env.NODE_ENV = 'development'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import { join } from 'path'
 | 
					import { join } from 'path'
 | 
				
			||||||
import { spawn, ChildProcess } from 'child_process'
 | 
					 | 
				
			||||||
import electron from 'electron'
 | 
					import electron from 'electron'
 | 
				
			||||||
import { RollupWatcher, RollupWatcherEvent, watch } from 'rollup'
 | 
					import { spawn, ChildProcess } from 'child_process'
 | 
				
			||||||
import { createServer as createViteServer } from 'vite'
 | 
					import { createServer as createViteServer } from 'vite'
 | 
				
			||||||
 | 
					import { RollupWatcher, RollupWatcherEvent, watch } from 'rollup'
 | 
				
			||||||
 | 
					import WebSocket from 'ws'
 | 
				
			||||||
 | 
					import chalk from 'chalk'
 | 
				
			||||||
import pkg from '../package.json'
 | 
					import pkg from '../package.json'
 | 
				
			||||||
import {
 | 
					import {
 | 
				
			||||||
  mainOptions,
 | 
					  mainOptions,
 | 
				
			||||||
  preloadOptions,
 | 
					  preloadOptions,
 | 
				
			||||||
} from './utils'
 | 
					} from './utils'
 | 
				
			||||||
 | 
					import { createWsServer, formatWsSendData } from './ws'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const TAG = '[dev.ts]'
 | 
					const TAG = chalk.bgGray('[dev.ts]')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function eventHandle(ev: RollupWatcherEvent) {
 | 
					function eventHandle(ev: RollupWatcherEvent) {
 | 
				
			||||||
  if (ev.code === 'ERROR') {
 | 
					  if (ev.code === 'ERROR') {
 | 
				
			||||||
    console.error(TAG, ev.error)
 | 
					    console.error(TAG, chalk.red(ev.error))
 | 
				
			||||||
  } else if (ev.code === 'BUNDLE_START') {
 | 
					  } else if (ev.code === 'BUNDLE_START') {
 | 
				
			||||||
    console.log(TAG, `Rebuild - ${ev.output}`)
 | 
					    console.log(TAG, chalk.blue(`Rebuild - ${ev.output}`))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -41,10 +46,16 @@ function watchMain(): RollupWatcher {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
function watchPreload(): RollupWatcher {
 | 
					function watchPreload(): RollupWatcher {
 | 
				
			||||||
 | 
					  const wssObj = createWsServer({ TAG })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
  return watch(preloadOptions())
 | 
					  return watch(preloadOptions())
 | 
				
			||||||
    .on('event', ev => {
 | 
					    .on('event', ev => {
 | 
				
			||||||
      if (ev.code === 'END') {
 | 
					      if (ev.code === 'END') {
 | 
				
			||||||
        // TODO Hot reload
 | 
					        // Hot reload renderer process !!!
 | 
				
			||||||
 | 
					        if (wssObj.instance?.readyState === WebSocket.OPEN) {
 | 
				
			||||||
 | 
					          console.log(TAG, chalk.yellow('Hot reload renderer process'))
 | 
				
			||||||
 | 
					          wssObj.instance.send(formatWsSendData({ cmd: 'reload', data: Date.now() }))
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
      }
 | 
					      }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      eventHandle(ev)
 | 
					      eventHandle(ev)
 | 
				
			||||||
| 
						 | 
					@ -59,11 +70,11 @@ function watchPreload(): RollupWatcher {
 | 
				
			||||||
    })).listen()
 | 
					    })).listen()
 | 
				
			||||||
    const { host = '127.0.0.1', port = 3000 } = server.config.server
 | 
					    const { host = '127.0.0.1', port = 3000 } = server.config.server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    console.log(TAG, `Server run at - http://${host}:${port}`)
 | 
					    console.log(TAG, chalk.yellow(`Server run at - http://${host}:${port}`))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    watchPreload()
 | 
					    watchPreload()
 | 
				
			||||||
    watchMain()
 | 
					    watchMain()
 | 
				
			||||||
  } catch (error) {
 | 
					  } catch (error) {
 | 
				
			||||||
    console.error(TAG, error)
 | 
					    console.error(TAG, chalk.red(error))
 | 
				
			||||||
  }
 | 
					  }
 | 
				
			||||||
})();
 | 
					})();
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,43 @@
 | 
				
			||||||
 | 
					/**
 | 
				
			||||||
 | 
					 * Hot reload from preload script during development
 | 
				
			||||||
 | 
					 */
 | 
				
			||||||
 | 
					import WebSocket from 'ws'
 | 
				
			||||||
 | 
					import chalk from 'chalk'
 | 
				
			||||||
 | 
					import pkg from '../package.json'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export interface CreateWsServerOptions {
 | 
				
			||||||
 | 
					  TAG: string
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function createWsServer(options: CreateWsServerOptions) {
 | 
				
			||||||
 | 
					  const { TAG } = options
 | 
				
			||||||
 | 
					  const port = pkg.env.PORT_WS
 | 
				
			||||||
 | 
					  const host = pkg.env.HOST || '127.0.0.1'
 | 
				
			||||||
 | 
					  const wss = new WebSocket.Server({ host, port })
 | 
				
			||||||
 | 
					  const wssObj: { wss: WebSocket.Server; instance: WebSocket | null } = { wss, instance: null }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  console.log(TAG, 'Wss run at - ' + chalk.yellow(`ws://${host}:${port}`))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wss.on('connection', ws => {
 | 
				
			||||||
 | 
					    console.log(TAG, chalk.yellow(`wss.on('connection')`))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wssObj.instance = ws
 | 
				
			||||||
 | 
					    ws.on('message', message => {
 | 
				
			||||||
 | 
					      console.log(TAG, `ws.on('message'):`, message.toString())
 | 
				
			||||||
 | 
					    })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    ws.send(formatWsSendData({ cmd: 'message', data: 'connected.' }))
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  wss.on('close', () => {
 | 
				
			||||||
 | 
					    console.log(TAG, chalk.gray(`wss.on('close')`))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    wssObj.instance = null
 | 
				
			||||||
 | 
					  })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					  return wssObj
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					export function formatWsSendData(json: { cmd: string, data?: any }) {
 | 
				
			||||||
 | 
					  return JSON.stringify(json)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue