feat(core): add global error handler (#8509)

This commit is contained in:
liuyi 2024-10-18 14:34:13 +08:00 committed by GitHub
parent 4b77f6ed34
commit 9b31183bd1
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
17 changed files with 120 additions and 55 deletions

View File

@ -1,3 +1 @@
import { setupBrowser } from '@affine/core/bootstrap'; import '@affine/core/bootstrap/browser';
await setupBrowser();

View File

@ -1,6 +1,3 @@
import '@affine/core/bootstrap/electron';
import '@affine/component/theme'; import '@affine/component/theme';
import './global.css'; import './global.css';
import { setupElectron } from '@affine/core/bootstrap';
setupElectron();

View File

@ -1,6 +1,3 @@
import '@affine/core/bootstrap/electron';
import '@affine/component/theme'; import '@affine/component/theme';
import '../global.css'; import '../global.css';
import { setupElectron } from '@affine/core/bootstrap';
setupElectron();

View File

@ -1,6 +1,3 @@
import '@affine/core/bootstrap/browser';
import '@affine/component/theme'; import '@affine/component/theme';
import '@affine/core/mobile/styles/mobile.css'; import '@affine/core/mobile/styles/mobile.css';
import { setupBrowser } from '@affine/core/bootstrap';
await setupBrowser();

View File

@ -1,5 +1,2 @@
import '@affine/core/bootstrap/browser';
import '@affine/component/theme'; import '@affine/component/theme';
import { setupBrowser } from '@affine/core/bootstrap';
await setupBrowser();

View File

@ -1,4 +0,0 @@
import '@affine/env/constant';
import '../types/types.d.ts';
export { setupGlobal as setupEnvironment } from '@affine/env/global';

View File

@ -0,0 +1,5 @@
// ORDER MATTERS
import './global-error-handler';
import './env';
import './public-path';
import './polyfill/browser';

View File

@ -0,0 +1,4 @@
// ORDER MATTERS
import './env';
import './public-path';
import './polyfill/electron';

View File

@ -0,0 +1,6 @@
import '@affine/env/constant';
import '../types/types.d.ts';
import { setupGlobal } from '@affine/env/global';
setupGlobal();

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

View File

@ -0,0 +1,81 @@
/* eslint-disable no-var */
import errorImg from './error.png';
var errorEl: HTMLDivElement | null = null;
function showGlobalErrorPage() {
if (errorEl) {
return;
}
errorEl = document.createElement('div');
errorEl.innerHTML = [
'<style>',
'.gue {display:flex;flex-direction:column;align-items:center;justify-content:center;width:380px;}',
'.gue img{width:380px;}',
'.gue div{padding:16px 40px 0 40px;text-align:center;}',
'.gue .p1{color:#141414;line-height:24px;font-weight:500;}',
'.gue .p2{color:#7A7A7A;line-height:22px;}',
'</style>',
'<div class="gue">',
'<img src="',
errorImg,
'" />',
'<div>',
'<p class="p1">Unsupported Environment</p>',
'<p class="p2">',
'It looks like AFFiNE cannot run in this environment.',
"Please ensure you are using a supported browser or update your device's operating system to the latest version.",
'If the issue persists, visit our <a href="https://github.com/toeverything/AFFiNE/issues">support page</a> for further assistance.',
'</p>',
'</div>',
'</div>',
].join('');
errorEl.setAttribute(
'style',
'position:absolute;top:0;left:0;height:100vh;width:100vw;display:flex;flex-direction:column;align-items:center;justify-content:center;background:white;z-index:999;'
);
document.body.append(errorEl);
}
function registerGlobalErrorHandler() {
function handleGlobalUnrecoverableError(
e: ErrorEvent | PromiseRejectionEvent
) {
var error =
'error' in e ? e.error : e.reason instanceof Error ? e.reason : null;
console.error('unhandled unrecoverable error', error);
const shouldCache =
// syntax error
error && error instanceof SyntaxError;
if (!shouldCache) {
return;
}
e.stopImmediatePropagation();
showGlobalErrorPage();
}
if (typeof document !== 'undefined') {
globalThis.addEventListener(
'unhandledrejection',
handleGlobalUnrecoverableError
);
globalThis.addEventListener('error', handleGlobalUnrecoverableError);
}
}
function ensureBasicEnvironment() {
var globals = ['Promise', 'Map', 'fetch', 'customElements'];
// eslint-disable-next-line @typescript-eslint/prefer-for-of
for (var i = 0; i < globals.length; i++) {
if (!(globals[i] in globalThis)) {
showGlobalErrorPage();
return;
}
}
}
registerGlobalErrorHandler();
ensureBasicEnvironment();

View File

@ -1,15 +0,0 @@
import '../types/types.d.ts';
import { setupEnvironment } from './app';
import { polyfillBrowser, polyfillElectron } from './polyfill';
export function setupElectron() {
setupEnvironment();
polyfillElectron();
}
export async function setupBrowser() {
setupEnvironment();
__webpack_public_path__ = environment.publicPath;
await polyfillBrowser();
}

View File

@ -3,13 +3,7 @@ import { polyfillPromise } from './promise-with-resolvers';
import { polyfillEventLoop } from './request-idle-callback'; import { polyfillEventLoop } from './request-idle-callback';
import { polyfillResizeObserver } from './resize-observer'; import { polyfillResizeObserver } from './resize-observer';
export function polyfillElectron() { polyfillResizeObserver();
polyfillResizeObserver(); polyfillEventLoop();
} await polyfillPromise();
await polyfillDispose();
export async function polyfillBrowser() {
polyfillResizeObserver();
polyfillEventLoop();
await polyfillPromise();
await polyfillDispose();
}

View File

@ -0,0 +1,3 @@
import { polyfillResizeObserver } from './resize-observer';
polyfillResizeObserver();

View File

@ -0,0 +1 @@
__webpack_public_path__ = environment.publicPath;

View File

@ -5,6 +5,11 @@ function testPackageName(regexp: RegExp): (module: any) => boolean {
// https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758 // https://hackernoon.com/the-100-correct-way-to-split-your-chunks-with-webpack-f8a9df5b7758
export const productionCacheGroups = { export const productionCacheGroups = {
errorHandler: {
test: /global-error-handler/,
priority: 1000,
enforce: true,
},
asyncVendor: { asyncVendor: {
test: /[\\/]node_modules[\\/]/, test: /[\\/]node_modules[\\/]/,
name(module: any) { name(module: any) {

View File

@ -56,13 +56,7 @@ const OptimizeOptionOptions: (
minChunks: 1, minChunks: 1,
maxInitialRequests: Number.MAX_SAFE_INTEGER, maxInitialRequests: Number.MAX_SAFE_INTEGER,
maxAsyncRequests: Number.MAX_SAFE_INTEGER, maxAsyncRequests: Number.MAX_SAFE_INTEGER,
cacheGroups: cacheGroups: productionCacheGroups,
buildFlags.mode === 'production'
? productionCacheGroups
: {
default: false,
vendors: false,
},
}, },
}); });
@ -404,6 +398,11 @@ export const createConfiguration: (
maxInitialRequests: Infinity, maxInitialRequests: Infinity,
chunks: 'all', chunks: 'all',
cacheGroups: { cacheGroups: {
errorHandler: {
test: /global-error-handler/,
priority: 1000,
enforce: true,
},
defaultVendors: { defaultVendors: {
test: `[\\/]node_modules[\\/](?!.*vanilla-extract)`, test: `[\\/]node_modules[\\/](?!.*vanilla-extract)`,
priority: -10, priority: -10,