mirror of
https://github.com/responsively-org/responsively-app
synced 2024-11-10 06:44:13 +00:00
Merge pull request #977 from themohammadsa/feat-hot-reload
feature: hot-reloading for static web files
This commit is contained in:
commit
4d5eb63089
4 changed files with 75 additions and 4 deletions
|
@ -27,6 +27,8 @@ export const IPC_MAIN_CHANNELS = {
|
|||
AUTH_RESPONSE: 'auth-response',
|
||||
OPEN_EXTERNAL: 'open-external',
|
||||
OPEN_URL: 'open-url',
|
||||
START_WATCHING_FILE: 'start-watching-file',
|
||||
STOP_WATCHER: 'stop-watcher',
|
||||
} as const;
|
||||
|
||||
export type Channels = typeof IPC_MAIN_CHANNELS[keyof typeof IPC_MAIN_CHANNELS];
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
/* eslint-disable @typescript-eslint/ban-ts-comment */
|
||||
import BrowserSync, { BrowserSyncInstance } from 'browser-sync';
|
||||
import fs from 'fs-extra';
|
||||
|
||||
export const BROWSER_SYNC_PORT = 12719;
|
||||
export const BROWSER_SYNC_HOST = `localhost:${BROWSER_SYNC_PORT}`;
|
||||
|
@ -7,6 +9,8 @@ export const BROWSER_SYNC_URL = `https://${BROWSER_SYNC_HOST}/browser-sync/brows
|
|||
const browserSyncEmbed: BrowserSyncInstance = BrowserSync.create('embed');
|
||||
|
||||
let created = false;
|
||||
let filesWatcher: ReturnType<BrowserSyncInstance['watch']> | null = null;
|
||||
let cssWatcher: ReturnType<BrowserSyncInstance['watch']> | null = null;
|
||||
|
||||
export async function initInstance(): Promise<BrowserSyncInstance> {
|
||||
if (created) {
|
||||
|
@ -32,3 +36,35 @@ export async function initInstance(): Promise<BrowserSyncInstance> {
|
|||
);
|
||||
});
|
||||
}
|
||||
|
||||
export function watchFiles(filePath: string) {
|
||||
if (filePath && fs.existsSync(filePath)) {
|
||||
const fileDir = filePath.substring(0, filePath.lastIndexOf('/'));
|
||||
|
||||
filesWatcher = browserSyncEmbed
|
||||
// @ts-expect-error
|
||||
.watch([filePath, `${fileDir}/**/**.js`])
|
||||
.on('change', browserSyncEmbed.reload);
|
||||
|
||||
cssWatcher = browserSyncEmbed.watch(
|
||||
`${fileDir}/**/**.css`,
|
||||
// @ts-expect-error
|
||||
(event: string, file: string) => {
|
||||
if (event === 'change') {
|
||||
browserSyncEmbed.reload(file);
|
||||
}
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
export async function stopWatchFiles() {
|
||||
if (filesWatcher) {
|
||||
// @ts-expect-error
|
||||
await filesWatcher.close();
|
||||
}
|
||||
if (cssWatcher) {
|
||||
// @ts-expect-error
|
||||
await cssWatcher.close();
|
||||
}
|
||||
}
|
||||
|
|
|
@ -9,14 +9,19 @@
|
|||
* `./src/main.js` using webpack. This gives us some performance wins.
|
||||
*/
|
||||
import path from 'path';
|
||||
import { app, BrowserWindow, shell, screen } from 'electron';
|
||||
import { app, BrowserWindow, shell, screen, ipcMain } from 'electron';
|
||||
import { autoUpdater } from 'electron-updater';
|
||||
import log from 'electron-log';
|
||||
import cli from './cli';
|
||||
import { PROTOCOL } from '../common/constants';
|
||||
import MenuBuilder from './menu';
|
||||
import { isValidCliArgURL, resolveHtmlPath } from './util';
|
||||
import { BROWSER_SYNC_HOST, initInstance } from './browser-sync';
|
||||
import { resolveHtmlPath } from './util';
|
||||
import {
|
||||
BROWSER_SYNC_HOST,
|
||||
initInstance,
|
||||
stopWatchFiles,
|
||||
watchFiles,
|
||||
} from './browser-sync';
|
||||
import store from '../store';
|
||||
import { initWebviewContextMenu } from './webview-context-menu/register';
|
||||
import { initScreenshotHandlers } from './screenshot';
|
||||
|
@ -197,6 +202,19 @@ const createWindow = async () => {
|
|||
return { action: 'deny' };
|
||||
});
|
||||
|
||||
ipcMain.on('start-watching-file', async (event, fileInfo) => {
|
||||
let filePath = fileInfo.path.replace('file://', '');
|
||||
if (process.platform === 'win32') {
|
||||
filePath = filePath.replace(/^\//, '');
|
||||
}
|
||||
app.addRecentDocument(filePath);
|
||||
await stopWatchFiles();
|
||||
watchFiles(filePath);
|
||||
});
|
||||
|
||||
ipcMain.on('stop-watcher', async () => {
|
||||
await stopWatchFiles();
|
||||
});
|
||||
// Remove this if your app does not use auto updates
|
||||
// eslint-disable-next-line
|
||||
new AppUpdater();
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
import { createSlice } from '@reduxjs/toolkit';
|
||||
import type { PayloadAction } from '@reduxjs/toolkit';
|
||||
import { PreviewLayout } from 'common/constants';
|
||||
import { IPC_MAIN_CHANNELS, PreviewLayout } from 'common/constants';
|
||||
import type { RootState } from '../..';
|
||||
|
||||
export interface RendererState {
|
||||
|
@ -34,12 +34,27 @@ const initialState: RendererState = {
|
|||
isCapturingScreenshot: false,
|
||||
};
|
||||
|
||||
export const updateFileWatcher = (newURL: string) => {
|
||||
if (
|
||||
newURL.startsWith('file://') &&
|
||||
(newURL.endsWith('.html') || newURL.endsWith('.htm'))
|
||||
)
|
||||
window.electron.ipcRenderer.sendMessage(
|
||||
IPC_MAIN_CHANNELS.START_WATCHING_FILE,
|
||||
{
|
||||
path: newURL,
|
||||
}
|
||||
);
|
||||
else window.electron.ipcRenderer.sendMessage(IPC_MAIN_CHANNELS.STOP_WATCHER);
|
||||
};
|
||||
|
||||
export const rendererSlice = createSlice({
|
||||
name: 'renderer',
|
||||
initialState,
|
||||
reducers: {
|
||||
setAddress: (state, action: PayloadAction<string>) => {
|
||||
if (action.payload !== state.address) {
|
||||
updateFileWatcher(action.payload);
|
||||
state.address = action.payload;
|
||||
}
|
||||
},
|
||||
|
|
Loading…
Reference in a new issue