Skip to content

Commit 1ee0114

Browse files
authored
Add error and node_modules lookup handling to prerender exception hook. Fixes #310. (#317)
1 parent 3f97249 commit 1ee0114

File tree

3 files changed

+53
-23
lines changed

3 files changed

+53
-23
lines changed

src/lib/webpack/prerender.js

Lines changed: 47 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -40,35 +40,61 @@ export default function prerender(env, params) {
4040
const handlePrerenderError = (err, env, stack, entry) => {
4141
let errorMessage = err.toString();
4242
let isReferenceError = errorMessage.startsWith('ReferenceError');
43-
let sourceMapContent = JSON.parse(fs.readFileSync(`${entry}.map`));
44-
let sourceMapConsumer = new SourceMapConsumer(sourceMapContent);
45-
let position = sourceMapConsumer.originalPositionFor({
46-
line: stack.getLineNumber(),
47-
column: stack.getColumnNumber()
48-
});
43+
let methodName = stack.getMethodName();
44+
let sourceMapContent, position, sourcePath, sourceLines, sourceCodeHighlight;
4945

50-
position.source = position.source.replace('webpack://', '.');
46+
try {
47+
sourceMapContent = JSON.parse(fs.readFileSync(`${entry}.map`));
48+
} catch (err) {
49+
process.stderr.write(chalk.red(`Unable to read sourcemap: ${entry}.map\n`));
50+
}
5151

52-
let sourcePath = resolve(env.src, position.source);
53-
let sourceLines = fs.readFileSync(sourcePath, 'utf-8').split('\n');
54-
let methodName = stack.getMethodName();
55-
let sourceCodeHighlight = '';
52+
if (sourceMapContent) {
53+
let sourceMapConsumer = new SourceMapConsumer(sourceMapContent);
54+
position = sourceMapConsumer.originalPositionFor({
55+
line: stack.getLineNumber(),
56+
column: stack.getColumnNumber()
57+
});
58+
59+
position.source = position.source.replace('webpack://', '.').replace(/^.*~\/((?:@[^/]+\/)?[^/]+)/, (s, name) => require.resolve(name).replace(/^(.*?\/node_modules\/(@[^/]+\/)?[^/]+)(\/.*)$/, '$1') );
5660

57-
for (var i = -4; i <= 4; i++) {
58-
let color = i === 0 ? chalk.red : chalk.yellow;
59-
let line = position.line + i;
60-
let sourceLine = sourceLines[line - 1];
61-
sourceCodeHighlight += sourceLine ? `${color(sourceLine)}\n` : '';
61+
sourcePath = resolve(env.src, position.source);
62+
sourceLines;
63+
try {
64+
sourceLines = fs.readFileSync(sourcePath, 'utf-8').split('\n');
65+
} catch (err) {
66+
try {
67+
sourceLines = fs.readFileSync(require.resolve(position.source), 'utf-8').split('\n');
68+
} catch (err) {
69+
process.stderr.write(chalk.red(`Unable to read file: ${sourcePath}\n`));
70+
}
71+
// process.stderr.write(chalk.red(`Unable to read file: ${sourcePath}\n`));
72+
}
73+
sourceCodeHighlight = '';
74+
75+
if (sourceLines) {
76+
for (var i = -4; i <= 4; i++) {
77+
let color = i === 0 ? chalk.red : chalk.yellow;
78+
let line = position.line + i;
79+
let sourceLine = sourceLines[line - 1];
80+
sourceCodeHighlight += sourceLine ? `${color(sourceLine)}\n` : '';
81+
}
82+
}
6283
}
6384

6485
process.stderr.write('\n');
6586
process.stderr.write(chalk.red(`${errorMessage}\n`));
6687
process.stderr.write(`method: ${methodName}\n`);
67-
process.stderr.write(`at: ${sourcePath}:${position.line}:${position.column}\n`);
68-
process.stderr.write('\n');
69-
process.stderr.write('Source code:\n\n');
70-
process.stderr.write(sourceCodeHighlight);
71-
process.stderr.write('\n');
88+
if (sourceMapContent) {
89+
process.stderr.write(`at: ${sourcePath}:${position.line}:${position.column}\n`);
90+
process.stderr.write('\n');
91+
process.stderr.write('Source code:\n\n');
92+
process.stderr.write(sourceCodeHighlight);
93+
process.stderr.write('\n');
94+
}
95+
else {
96+
process.stderr.write(stack.toString()+'\n');
97+
}
7298
process.stderr.write(`This ${isReferenceError ? 'is most likely' : 'could be'} caused by using DOM or Web APIs.\n`);
7399
process.stderr.write(`Pre-render runs in node and has no access to globals available in browsers.\n\n`);
74100
process.stderr.write(`Consider wrapping code producing error in: 'if (typeof window !== "undefined") { ... }'\n`);

src/lib/webpack/webpack-base-config.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,7 @@ export default (env) => {
6262
'node_modules',
6363
resolve(__dirname, '../../../node_modules')
6464
],
65-
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.less', '.scss', '.sass', '.styl','.css'],
65+
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.less', '.scss', '.sass', '.styl', '.css'],
6666
alias: {
6767
'preact-cli-entrypoint': src('index.js'),
6868
style: src('style'),

src/lib/webpack/webpack-client-config.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -222,7 +222,11 @@ const htmlPlugin = (config, src) => {
222222
excludeAssets: [/(bundle|polyfills)(\..*)?\.js$/],
223223
config,
224224
ssr(params) {
225-
return config.prerender ? prerender({ dest: config.dest, src }, { ...params, url }) : '';
225+
return config.prerender ? prerender({
226+
dest: config.dest,
227+
src,
228+
cwd: config.cwd
229+
}, { ...params, url }) : '';
226230
}
227231
});
228232
const pages = readJson(resolve(config.cwd, config.prerenderUrls || '')) || [{ url: "/" }];

0 commit comments

Comments
 (0)