Skip to content

Commit

Permalink
improve error logging
Browse files Browse the repository at this point in the history
  • Loading branch information
slorber committed Feb 2, 2024
1 parent 9662027 commit a245b67
Show file tree
Hide file tree
Showing 3 changed files with 45 additions and 52 deletions.
9 changes: 6 additions & 3 deletions packages/docusaurus/bin/docusaurus.mjs
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

// @ts-check

import {inspect} from 'node:util';
import logger from '@docusaurus/logger';
import cli from 'commander';
import {DOCUSAURUS_VERSION} from '@docusaurus/utils';
Expand Down Expand Up @@ -267,9 +268,11 @@ cli.parse(process.argv);

process.on('unhandledRejection', (err) => {
console.log('');
// Do not use logger.error here: it does not print error causes
console.error(err);
console.log('');

// We need to use inspect with increased depth to log the full causal chain
// By default Node logging has depth=2
// see also https://github.com/nodejs/node/issues/51637
logger.error(inspect(err, {depth: Infinity}));

logger.info`Docusaurus version: number=${DOCUSAURUS_VERSION}
Node version: number=${process.version}`;
Expand Down
39 changes: 2 additions & 37 deletions packages/docusaurus/src/client/serverEntry.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -18,31 +18,7 @@ import {
} from './BrokenLinksContext';
import type {PageCollectedData, AppRenderer} from '../common';

function buildSSRErrorMessage({
error,
pathname,
}: {
error: Error;
pathname: string;
}): string {
const parts = [
`Docusaurus server-side rendering could not render static page with path ${pathname} because of error: ${error.message}`,
];

const isNotDefinedErrorRegex =
/(?:window|document|localStorage|navigator|alert|location|buffer|self) is not defined/i;

if (isNotDefinedErrorRegex.test(error.message)) {
// prettier-ignore
parts.push(`It looks like you are using code that should run on the client-side only.
To get around it, try using \`<BrowserOnly>\` (https://docusaurus.io/docs/docusaurus-core/#browseronly) or \`ExecutionEnvironment\` (https://docusaurus.io/docs/docusaurus-core/#executionenvironment).
It might also require to wrap your client code in \`useEffect\` hook and/or import a third-party library dynamically (if any).`);
}

return parts.join('\n');
}

const doRender: AppRenderer = async ({pathname}) => {
const render: AppRenderer = async ({pathname}) => {
await preload(pathname);

const modules = new Set<string>();
Expand All @@ -64,26 +40,15 @@ const doRender: AppRenderer = async ({pathname}) => {
);

const html = await renderToHtml(app);
const {helmet} = helmetContext as FilledContext;

const collectedData: PageCollectedData = {
headTags: (helmetContext as FilledContext).helmet,
anchors: statefulBrokenLinks.getCollectedAnchors(),
links: statefulBrokenLinks.getCollectedLinks(),
headTags: helmet,
modules: Array.from(modules),
};

return {html, collectedData};
};

const render: AppRenderer = async (params) => {
try {
return await doRender(params);
} catch (errorUnknown) {
const error = errorUnknown as Error;
const message = buildSSRErrorMessage({error, pathname: params.pathname});
throw new Error(message, {cause: error});
}
};

export default render;
49 changes: 37 additions & 12 deletions packages/docusaurus/src/ssg.ts
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import _ from 'lodash';
import evaluate from 'eval';
import pMap from 'p-map';
import {minify} from 'html-minifier-terser';
import logger from '@docusaurus/logger';
import {PerfLogger} from './utils';
import {renderSSRTemplate} from './templates/templates';
import type {AppRenderer, AppRenderResult, SiteCollectedData} from './common';
Expand Down Expand Up @@ -136,20 +137,17 @@ export async function generateStaticFiles({
);

if (allSSGErrors.length > 0) {
// TODO AggregateError does not log properly with Error.cause :/
// see also https://github.com/nodejs/node/issues/51637
// throw new AggregateError(allErrors);

// Workaround: log errors individually + emit an aggregated error message
allSSGErrors.forEach((ssgError) => {
console.error(ssgError.error);
});
const message = `Docusaurus static site generation failed for ${
allSSGErrors.length
} path${allSSGErrors.length ? 's' : ''}:\n- ${allSSGErrors
.map((ssgError) => ssgError.pathname)
.map((ssgError) => logger.path(ssgError.pathname))
.join('\n- ')}`;
throw new Error(message);

// Note logging this error properly require using inspect(error,{depth})
// See https://github.com/nodejs/node/issues/51637
throw new Error(message, {
cause: new AggregateError(allSSGErrors.map((ssgError) => ssgError.error)),
});
}

const collectedData: SiteCollectedData = _.chain(allSSGSuccesses)
Expand Down Expand Up @@ -187,12 +185,39 @@ async function generateStaticFile({
});
return result;
} catch (errorUnknown) {
throw new Error(`Can't render static file for pathname=${pathname}`, {
cause: errorUnknown as Error,
const error = errorUnknown as Error;
const tips = getSSGErrorTips(error);
const message = logger.interpolate`Can't render static file for pathname path=${pathname}${
tips ? `\n\n${ tips}` : ''
}`;
throw new Error(message, {
cause: error,
});
}
}

function getSSGErrorTips(error: Error): string {
const parts = [];

const isNotDefinedErrorRegex =
/(?:window|document|localStorage|navigator|alert|location|buffer|self) is not defined/i;
if (isNotDefinedErrorRegex.test(error.message)) {
parts.push(`It looks like you are using code that should run on the client-side only.
To get around it, try using one of:
- ${logger.code('<BrowserOnly>')} (${logger.url(
'https://docusaurus.io/docs/docusaurus-core/#browseronly',
)})
- ${logger.code('ExecutionEnvironment')} (${logger.url(
'https://docusaurus.io/docs/docusaurus-core/#executionenvironment',
)}).
It might also require to wrap your client code in ${logger.code(
'useEffect',
)} hook and/or import a third-party library dynamically (if any).`);
}

return parts.join('\n');
}

async function writeStaticFile({
content,
pathname,
Expand Down

0 comments on commit a245b67

Please sign in to comment.