I have this problem regarding electron
, I tried to upgrade my electron version from 7.0.0
to 18.2.3
but I got stumbled in this problem where the screen always give me a blank screen after I try to run it in my staging environment.
before someone want to mark it as duplicate, I want to clarify first that I tried the solution but still not work, this is some thread in here that I already tried but still no luck:
- electron-shows-blank-screen-when-running-in-development-yet-works-in-production
- electron-shows-white-screen-when-built
- getting-blank-screen-in-windows-after-electron-builder-react-electron-app
- blank-screen-when-running-electron-package-app-how-to-debug
- electron-angular-6-blank-screen-on-production-application
for information, I use react
for my project, after try to read some thread I think I'm starting to figure probably the problem occur around the implement of hashRouter
or the way of my directory, but regarding the directory, I think the way I use it already correct since it give a different color of blank screen such as like this:
Blank screen when using wrong path
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'index.html'),
protocol: 'file:',
slashes: true
}));
Result:
Blank screen when using correct path
// mainWindow.loadURL(`file://${__dirname}/app.html`);
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'app.html'),
protocol: 'file:',
slashes: true
}));
Result
I feel like I 1 step closer to solved it but quite confused as what problem happen when electron only return this blank screen.
this is my main.dev.ts looks like:
import path from 'path';
import { app, BrowserWindow, screen, ipcMain } from 'electron';
import { autoUpdater } from 'electron-updater';
import log from 'electron-log';
import MenuBuilder from './menu';
const url = require('url');
const { download } = require('electron-dl');
require('dotenv').config({ path: `.env.${process.env.NODE_ENV}` });
export default class AppUpdater {
constructor() {
log.transports.file.level = 'info';
autoUpdater.logger = log;
autoUpdater.checkForUpdatesAndNotify();
}
}
let mainWindow: BrowserWindow | null = null;
if (process.env.NODE_ENV === 'production') {
const sourceMapSupport = require('source-map-support');
sourceMapSupport.install();
}
if (
process.env.NODE_ENV === 'development' ||
process.env.DEBUG_PROD === 'true'
) {
require('electron-debug')();
}
const installExtensions = async () => {
const installer = require('electron-devtools-installer');
const forceDownload = !!process.env.UPGRADE_EXTENSIONS;
const extensions = ['REACT_DEVELOPER_TOOLS', 'REDUX_DEVTOOLS'];
return Promise.all(
extensions.map(name => installer.default(installer[name], forceDownload))
).catch(console.log);
};
const createWindow = async () => {
if (
process.env.NODE_ENV === 'development' ||
process.env.DEBUG_PROD === 'true'
) {
await installExtensions();
}
const { width, height } = screen.getPrimaryDisplay().workAreaSize;
let widthWindow = 1200;
let heightWindow = 800;
if (width <= 1280 || height <= 800) {
widthWindow = width;
heightWindow = height;
}
mainWindow = new BrowserWindow({
show: false,
width: widthWindow,
height: heightWindow,
resizable: false,
webPreferences:
process.env.NODE_ENV === 'development' || process.env.E2E_BUILD === 'true'
? {
nodeIntegration: true,
zoomFactor: 1.0,
devTools: true
}
: {
preload: path.join(__dirname, 'dist/renderer.prod.js'),
zoomFactor: 1.0
}
});
// mainWindow.loadURL(`file://${__dirname}/app.html`);
mainWindow.loadURL(url.format({
pathname: path.join(__dirname, 'app.html'),
protocol: 'file:',
slashes: true
}));
mainWindow.webContents.on('did-finish-load', () => {
if (!mainWindow) {
throw new Error('"mainWindow" is not defined');
}
if (process.env.START_MINIMIZED) {
mainWindow.minimize();
} else {
// if (width <= 1280 || height <= 800) mainWindow.setFullScreen(true);
mainWindow.show();
mainWindow.focus();
}
});
mainWindow.on('closed', () => {
mainWindow = null;
});
const menuBuilder = new MenuBuilder(mainWindow);
menuBuilder.buildMenu();
ipcMain.on('download', (event, info, id) => {
info.properties.onProgress = status =>
mainWindow.webContents.send('download progress', status, id, info.url);
download(mainWindow, info.url, {
...info.properties,
saveAs: false
}).then(dl => mainWindow.webContents.send('download complete', id));
});
// Remove this if your app does not use auto updates
// eslint-disable-next-line
// if (process.env.NODE_ENV === 'production') new AppUpdater();
};
/**
* Add event listeners...
*/
app.on('window-all-closed', () => {
// Respect the OSX convention of having the application in memory even
// after all windows have been closed
if (process.platform !== 'darwin') {
app.quit();
}
});
// Use app.removeAllListeners('ready'); if you set your windows personalize in Dark Theme
app.removeAllListeners('ready');
app.on('ready', createWindow);
app.on('activate', () => {
// On macOS it's common to re-create a window in the app when the
// dock icon is clicked and there are no other windows open.
if (mainWindow === null) createWindow();
});
ipcMain.on('DEVICE_INFO_SCREEN', event => {
const { width, height } = screen.getPrimaryDisplay().workAreaSize;
event.returnValue = { width, height };
});
as for route, since I have a hunch that probably it has a problem regarding hashroute, currently I'm using Routes
from react-router-dom: 6.3.0
and it looks like this: (this is my Routes.tsx
)
import { Routes as Switch, Route, BrowserRouter as Router } from 'react-router-dom';
<App>
<Router basename={routesPath.SPLASH}>
<Switch>
<Route
path={routesPath.LIVESTREAMREPORT}
element={<LivestreamReport />}
/>
<Route
path={routesPath.LIVESTREAMHISTORY}
element={<LivestreamHistory />}
/>
// Start Section of Another path in my project
...
// End Section of Another path in my project
</Switch>
</Router>
</App>
There is one time that I tried HashRouter
and I change it like this, but it still not solved my problem, am I wrong in implement it, or it is another problem with another solution to solved this problem?
import { Routes as Switch, Route, HashRouter as Router } from 'react-router-dom';
<App>
<Router basename={routesPath.SPLASH}>
<Switch>
<Route
path={routesPath.LIVESTREAMREPORT}
element={<LivestreamReport />}
/>
<Route
path={routesPath.LIVESTREAMHISTORY}
element={<LivestreamHistory />}
/>
// Start Section of Another path in my project
...
// End Section of Another path in my project
</Switch>
</Router>
</App>
Can someone help me to solve this? I'm quite confused since there is no error in my dev console
EDIT 1 After I tried to move back to the initial version and do the step once again, finally my apps show exactly a white screen error like everyone (the dark screen is not show anymore), I think I starting to get closer to solved this problem, but I tried a lot of way based on white screen thread, I still failed to solved it, to make easier,
Here is my index.tsx
looks like:
import React, { Fragment } from 'react';
import { render } from 'react-dom';
import { AppContainer as ReactHotAppContainer } from 'react-hot-loader';
import Root from './Screen/Root';
import { configureStore, history } from './store/configureStore';
import './app.global.css';
const store = configureStore();
const AppContainer = process.env.PLAIN_HMR ? Fragment : ReactHotAppContainer;
document.addEventListener('DOMContentLoaded', () =>
render(
<AppContainer>
<Root store={store} history={history} />
</AppContainer>,
document.getElementById('root')
)
);
and this is how I render my component in Root.tsx
:
import React from 'react';
import { ipcRenderer, shell } from 'electron';
import * as firebase from 'firebase/app';
import 'firebase/analytics';
import 'firebase/database';
import { Provider } from 'react-redux';
import { ConnectedRouter } from 'connected-react-router';
import { hot } from 'react-hot-loader/root';
import { History } from 'history';
import { Store } from '../reducers/types';
import Routes from '../Routes'; // --> you can see this file above
// this is my render function
render() {
return (
<Provider store={this.props.store}>
<ConnectedRouter history={this.props.history}>
<div style={{ height: '100%', overflow: 'auto' }}>
<Routes />
</div>
</ConnectedRouter>
</Provider>
);
}
Am I implement something wrong in here?