fix(core): global error handler should be registered outside webpack runtime (#8556)
This commit is contained in:
@@ -1,5 +1,4 @@
|
|||||||
// ORDER MATTERS
|
// ORDER MATTERS
|
||||||
import './global-error-handler';
|
|
||||||
import './env';
|
import './env';
|
||||||
import './public-path';
|
import './public-path';
|
||||||
import './polyfill/browser';
|
import './polyfill/browser';
|
||||||
|
|||||||
Binary file not shown.
|
Before Width: | Height: | Size: 37 KiB |
@@ -1,81 +0,0 @@
|
|||||||
/* 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();
|
|
||||||
@@ -5,11 +5,6 @@ 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) {
|
||||||
|
|||||||
@@ -400,11 +400,6 @@ 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,
|
||||||
|
|||||||
73
tools/cli/src/webpack/error-handler.js
Normal file
73
tools/cli/src/webpack/error-handler.js
Normal file
@@ -0,0 +1,73 @@
|
|||||||
|
(function () {
|
||||||
|
var errorEl = 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="https://cdn.affine.pro/error.png" />',
|
||||||
|
'<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 handler(e) {
|
||||||
|
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', handler);
|
||||||
|
globalThis.addEventListener('error', handler);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
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();
|
||||||
|
})();
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
import { execSync } from 'node:child_process';
|
import { execSync } from 'node:child_process';
|
||||||
|
import { readFileSync } from 'node:fs';
|
||||||
import { join, resolve } from 'node:path';
|
import { join, resolve } from 'node:path';
|
||||||
|
|
||||||
import type { BuildFlags } from '@affine/cli/config';
|
import type { BuildFlags } from '@affine/cli/config';
|
||||||
@@ -52,6 +53,14 @@ export function createWebpackConfig(cwd: string, flags: BuildFlags) {
|
|||||||
? undefined
|
? undefined
|
||||||
: new URL(publicPath).origin;
|
: new URL(publicPath).origin;
|
||||||
|
|
||||||
|
const globalErrorHandler = [
|
||||||
|
'js/global-error-handler.js',
|
||||||
|
readFileSync(
|
||||||
|
join(workspaceRoot, 'tools/cli/src/webpack/error-handler.js'),
|
||||||
|
'utf-8'
|
||||||
|
),
|
||||||
|
];
|
||||||
|
|
||||||
const templateParams = {
|
const templateParams = {
|
||||||
GIT_SHORT_SHA: gitShortHash(),
|
GIT_SHORT_SHA: gitShortHash(),
|
||||||
DESCRIPTION,
|
DESCRIPTION,
|
||||||
@@ -86,7 +95,24 @@ export function createWebpackConfig(cwd: string, flags: BuildFlags) {
|
|||||||
HTMLPlugin.getHooks(compilation).beforeAssetTagGeneration.tap(
|
HTMLPlugin.getHooks(compilation).beforeAssetTagGeneration.tap(
|
||||||
'assets-manifest-plugin',
|
'assets-manifest-plugin',
|
||||||
arg => {
|
arg => {
|
||||||
|
if (
|
||||||
|
flags.distribution !== 'desktop' &&
|
||||||
|
!compilation.getAsset(globalErrorHandler[0])
|
||||||
|
) {
|
||||||
|
compilation.emitAsset(
|
||||||
|
globalErrorHandler[0],
|
||||||
|
new webpack.sources.RawSource(globalErrorHandler[1])
|
||||||
|
);
|
||||||
|
arg.assets.js.unshift(
|
||||||
|
arg.assets.publicPath + globalErrorHandler[0]
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
if (!compilation.getAsset('assets-manifest.json')) {
|
if (!compilation.getAsset('assets-manifest.json')) {
|
||||||
|
compilation.emitAsset(
|
||||||
|
globalErrorHandler[0],
|
||||||
|
new webpack.sources.RawSource(globalErrorHandler[1])
|
||||||
|
);
|
||||||
compilation.emitAsset(
|
compilation.emitAsset(
|
||||||
`assets-manifest.json`,
|
`assets-manifest.json`,
|
||||||
new webpack.sources.RawSource(
|
new webpack.sources.RawSource(
|
||||||
|
|||||||
Reference in New Issue
Block a user