Skip to content

Commit

Permalink
Add error and node_modules lookup handling to prerender exception hook.
Browse files Browse the repository at this point in the history
Fixes #310.
  • Loading branch information
developit committed Aug 16, 2017
1 parent 2ff31c9 commit 40778ac
Show file tree
Hide file tree
Showing 3 changed files with 53 additions and 23 deletions.
68 changes: 47 additions & 21 deletions src/lib/webpack/prerender.js
Original file line number Diff line number Diff line change
Expand Up @@ -40,35 +40,61 @@ export default function prerender(env, params) {
const handlePrerenderError = (err, env, stack, entry) => {
let errorMessage = err.toString();
let isReferenceError = errorMessage.startsWith('ReferenceError');
let sourceMapContent = JSON.parse(fs.readFileSync(`${entry}.map`));
let sourceMapConsumer = new SourceMapConsumer(sourceMapContent);
let position = sourceMapConsumer.originalPositionFor({
line: stack.getLineNumber(),
column: stack.getColumnNumber()
});
let methodName = stack.getMethodName();
let sourceMapContent, position, sourcePath, sourceLines, sourceCodeHighlight;

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

let sourcePath = resolve(env.src, position.source);
let sourceLines = fs.readFileSync(sourcePath, 'utf-8').split('\n');
let methodName = stack.getMethodName();
let sourceCodeHighlight = '';
if (sourceMapContent) {
let sourceMapConsumer = new SourceMapConsumer(sourceMapContent);
position = sourceMapConsumer.originalPositionFor({
line: stack.getLineNumber(),
column: stack.getColumnNumber()
});

position.source = position.source.replace('webpack://', '.').replace(/^.*~\/((?:@[^/]+\/)?[^/]+)/, (s, name) => require.resolve(name).replace(/^(.*?\/node_modules\/(@[^/]+\/)?[^/]+)(\/.*)$/, '$1') );

for (var i = -4; i <= 4; i++) {
let color = i === 0 ? chalk.red : chalk.yellow;
let line = position.line + i;
let sourceLine = sourceLines[line - 1];
sourceCodeHighlight += sourceLine ? `${color(sourceLine)}\n` : '';
sourcePath = resolve(env.src, position.source);
sourceLines;
try {
sourceLines = fs.readFileSync(sourcePath, 'utf-8').split('\n');
} catch (err) {
try {
sourceLines = fs.readFileSync(require.resolve(position.source), 'utf-8').split('\n');
} catch (err) {
process.stderr.write(chalk.red(`Unable to read file: ${sourcePath}\n`));
}
// process.stderr.write(chalk.red(`Unable to read file: ${sourcePath}\n`));
}
sourceCodeHighlight = '';

if (sourceLines) {
for (var i = -4; i <= 4; i++) {
let color = i === 0 ? chalk.red : chalk.yellow;
let line = position.line + i;
let sourceLine = sourceLines[line - 1];
sourceCodeHighlight += sourceLine ? `${color(sourceLine)}\n` : '';
}
}
}

process.stderr.write('\n');
process.stderr.write(chalk.red(`${errorMessage}\n`));
process.stderr.write(`method: ${methodName}\n`);
process.stderr.write(`at: ${sourcePath}:${position.line}:${position.column}\n`);
process.stderr.write('\n');
process.stderr.write('Source code:\n\n');
process.stderr.write(sourceCodeHighlight);
process.stderr.write('\n');
if (sourceMapContent) {
process.stderr.write(`at: ${sourcePath}:${position.line}:${position.column}\n`);
process.stderr.write('\n');
process.stderr.write('Source code:\n\n');
process.stderr.write(sourceCodeHighlight);
process.stderr.write('\n');
}
else {
process.stderr.write(stack.toString()+'\n');
}
process.stderr.write(`This ${isReferenceError ? 'is most likely' : 'could be'} caused by using DOM or Web APIs.\n`);
process.stderr.write(`Pre-render runs in node and has no access to globals available in browsers.\n\n`);
process.stderr.write(`Consider wrapping code producing error in: 'if (typeof window !== "undefined") { ... }'\n`);
Expand Down
2 changes: 1 addition & 1 deletion src/lib/webpack/webpack-base-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,7 +62,7 @@ export default (env) => {
'node_modules',
resolve(__dirname, '../../../node_modules')
],
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.less', '.scss', '.sass', '.styl','.css'],
extensions: ['.js', '.jsx', '.ts', '.tsx', '.json', '.less', '.scss', '.sass', '.styl', '.css'],
alias: {
'preact-cli-entrypoint': src('index.js'),
style: src('style'),
Expand Down
6 changes: 5 additions & 1 deletion src/lib/webpack/webpack-client-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -222,7 +222,11 @@ const htmlPlugin = (config, src) => {
excludeAssets: [/(bundle|polyfills)(\..*)?\.js$/],
config,
ssr(params) {
return config.prerender ? prerender({ dest: config.dest, src }, { ...params, url }) : '';
return config.prerender ? prerender({
dest: config.dest,
src,
cwd: config.cwd
}, { ...params, url }) : '';
}
});
const pages = readJson(resolve(config.cwd, config.prerenderUrls || '')) || [{ url: "/" }];
Expand Down

0 comments on commit 40778ac

Please sign in to comment.