1
- const { red, yellow } = require ( 'kleur' ) ;
1
+ const { red, gray } = require ( 'kleur' ) ;
2
2
const { resolve } = require ( 'path' ) ;
3
3
const { readFileSync } = require ( 'fs' ) ;
4
4
const stackTrace = require ( 'stack-trace' ) ;
5
5
const { SourceMapConsumer } = require ( 'source-map' ) ;
6
+ const { error, info } = require ( '../../util' ) ;
6
7
7
8
module . exports = function ( env , params ) {
8
9
params = params || { } ;
@@ -14,8 +15,8 @@ module.exports = function(env, params) {
14
15
global . location = { href : url , pathname : url } ;
15
16
16
17
try {
17
- let m = require ( entry ) ,
18
- app = ( m && m . default ) || m ;
18
+ const m = require ( entry ) ;
19
+ const app = ( m && m . default ) || m ;
19
20
20
21
if ( typeof app !== 'function' ) {
21
22
// eslint-disable-next-line no-console
@@ -25,96 +26,144 @@ module.exports = function(env, params) {
25
26
return '' ;
26
27
}
27
28
28
- let preact = require ( 'preact' ) ,
29
- renderToString = require ( 'preact-render-to-string' ) ;
29
+ const preact = require ( 'preact' ) ;
30
+ const renderToString = require ( 'preact-render-to-string' ) ;
30
31
31
32
return renderToString ( preact . h ( app , { ...params , url } ) ) ;
32
33
} catch ( err ) {
33
- let stack = stackTrace . parse ( err ) . filter ( s => s . getFileName ( ) === entry ) [ 0 ] ;
34
+ const stack = stackTrace
35
+ . parse ( err )
36
+ . filter ( s => s . getFileName ( ) . includes ( 'ssr-build' ) ) [ 0 ] ;
34
37
if ( ! stack ) {
35
- throw err ;
38
+ error ( err ) ;
39
+ return '' ;
36
40
}
37
41
38
42
handlePrerenderError ( err , env , stack , entry ) ;
43
+ return '' ;
39
44
}
40
45
} ;
41
46
42
47
async function handlePrerenderError ( err , env , stack , entry ) {
43
- let errorMessage = err . toString ( ) ;
44
- let isReferenceError = errorMessage . startsWith ( 'ReferenceError' ) ;
45
- let methodName = stack . getMethodName ( ) ;
46
- let sourceMapContent , position , sourcePath , sourceLines , sourceCodeHighlight ;
47
-
48
- try {
49
- sourceMapContent = JSON . parse ( readFileSync ( `${ entry } .map` ) ) ;
50
- } catch ( err ) {
51
- process . stderr . write ( red ( `Unable to read sourcemap: ${ entry } .map\n` ) ) ;
52
- }
48
+ const errorMessage = err . toString ( ) ;
49
+ const isReferenceError = errorMessage . startsWith ( 'ReferenceError' ) ;
50
+ const methodName = stack . getMethodName ( ) ;
51
+ const fileName = stack . getFileName ( ) . replace ( / \\ / g, '/' ) ;
52
+ let sourceCodeHighlight = '' ;
53
+
54
+ let position ;
55
+
56
+ info ( fileName ) ;
57
+ if ( / w e b p a c k : / . test ( fileName ) ) {
58
+ position = {
59
+ source : fileName . replace ( / .+ w e b p a c k : / , 'webpack://' ) ,
60
+ line : stack . getLineNumber ( ) ,
61
+ column : stack . getColumnNumber ( ) ,
62
+ } ;
63
+ } else {
64
+ try {
65
+ const sourceMapContent = JSON . parse ( readFileSync ( `${ entry } .map` ) ) ;
53
66
54
- if ( sourceMapContent ) {
55
- await SourceMapConsumer . with ( sourceMapContent , null , consumer => {
56
- position = consumer . originalPositionFor ( {
57
- line : stack . getLineNumber ( ) ,
58
- column : stack . getColumnNumber ( ) ,
67
+ await SourceMapConsumer . with ( sourceMapContent , null , consumer => {
68
+ position = consumer . originalPositionFor ( {
69
+ line : stack . getLineNumber ( ) ,
70
+ column : stack . getColumnNumber ( ) ,
71
+ } ) ;
59
72
} ) ;
60
- } ) ;
73
+ } catch ( err ) {
74
+ error ( `Unable to read sourcemap: ${ entry } .map` ) ;
75
+ return ;
76
+ }
77
+ }
61
78
79
+ if ( position ) {
80
+ info ( position . source ) ;
62
81
position . source = position . source
63
82
. replace ( 'webpack://' , '.' )
64
83
. replace ( / ^ .* ~ \/ ( (?: @ [ ^ / ] + \/ ) ? [ ^ / ] + ) / , ( s , name ) =>
65
84
require
66
85
. resolve ( name )
67
86
. replace ( / ^ ( .* ?\/ n o d e _ m o d u l e s \/ ( @ [ ^ / ] + \/ ) ? [ ^ / ] + ) ( \/ .* ) $ / , '$1' )
68
87
) ;
88
+ info ( position . source ) ;
69
89
70
- sourcePath = resolve ( env . src , position . source ) ;
71
- sourceLines ;
90
+ let sourcePath ;
91
+ let sourceLines ;
72
92
try {
93
+ sourcePath = resolve ( env . src , position . source ) ;
73
94
sourceLines = readFileSync ( sourcePath , 'utf-8' ) . split ( '\n' ) ;
74
95
} catch ( err ) {
75
96
try {
76
- sourceLines = readFileSync (
77
- require . resolve ( position . source ) ,
78
- 'utf-8'
79
- ) . split ( '\n' ) ;
97
+ sourcePath = resolve ( env . cwd , position . source ) ;
98
+ // sourcePath = require.resolve(position.source);
99
+ sourceLines = readFileSync ( sourcePath , 'utf-8' ) . split ( '\n' ) ;
80
100
} catch ( err ) {
81
- process . stderr . write ( red ( `Unable to read file: ${ sourcePath } \n` ) ) ;
101
+ error ( `Unable to read file: ${ sourcePath } (${ position . source } )\n` ) ;
102
+ return ;
82
103
}
83
- // process.stderr.write(red(`Unable to read file: ${sourcePath}\n`));
84
104
}
85
- sourceCodeHighlight = '' ;
86
105
87
106
if ( sourceLines ) {
88
- for ( var i = - 4 ; i <= 4 ; i ++ ) {
89
- let color = i === 0 ? red : yellow ;
90
- let line = position . line + i ;
91
- let sourceLine = sourceLines [ line - 1 ] ;
92
- sourceCodeHighlight += sourceLine ? `${ color ( sourceLine ) } \n` : '' ;
93
- }
107
+ let lnrl = position . line . toString ( ) . length + 1 ;
108
+ sourceCodeHighlight +=
109
+ gray (
110
+ ( position . line - 2 || '' ) . toString ( ) . padStart ( lnrl ) +
111
+ ' | ' +
112
+ sourceLines [ position . line - 3 ] || ''
113
+ ) + '\n' ;
114
+ sourceCodeHighlight +=
115
+ gray (
116
+ ( position . line - 1 || '' ) . toString ( ) . padStart ( lnrl ) +
117
+ ' | ' +
118
+ sourceLines [ position . line - 2 ] || ''
119
+ ) + '\n' ;
120
+ sourceCodeHighlight +=
121
+ red ( position . line . toString ( ) . padStart ( lnrl ) ) +
122
+ gray ( ' | ' ) +
123
+ sourceLines [ position . line - 1 ] +
124
+ '\n' ;
125
+ sourceCodeHighlight +=
126
+ gray ( '| ' . padStart ( lnrl + 3 ) ) +
127
+ red ( '^' . padStart ( position . column + 1 ) ) +
128
+ '\n' ;
129
+ sourceCodeHighlight +=
130
+ gray (
131
+ ( position . line + 1 ) . toString ( ) . padStart ( lnrl ) +
132
+ ' | ' +
133
+ sourceLines [ position . line + 0 ] || ''
134
+ ) + '\n' ;
135
+ sourceCodeHighlight +=
136
+ gray (
137
+ ( position . line + 2 ) . toString ( ) . padStart ( lnrl ) +
138
+ ' | ' +
139
+ sourceLines [ position . line + 1 ] || ''
140
+ ) + '\n' ;
94
141
}
142
+ } else {
143
+ position = {
144
+ source : stack . getFileName ( ) ,
145
+ line : stack . getLineNumber ( ) ,
146
+ column : stack . getColumnNumber ( ) ,
147
+ } ;
95
148
}
96
149
97
150
process . stderr . write ( '\n' ) ;
98
- process . stderr . write ( red ( `${ errorMessage } \n` ) ) ;
99
- process . stderr . write ( `method: ${ methodName } \n` ) ;
100
- if ( sourceMapContent ) {
101
- process . stderr . write (
102
- `at: ${ sourcePath } :${ position . line } :${ position . column } \n`
103
- ) ;
104
- process . stderr . write ( '\n' ) ;
105
- process . stderr . write ( 'Source code:\n\n' ) ;
106
- process . stderr . write ( sourceCodeHighlight ) ;
107
- process . stderr . write ( '\n' ) ;
108
- } else {
109
- process . stderr . write ( stack . toString ( ) + '\n' ) ;
110
- }
151
+ process . stderr . write ( `[PrerenderError]: ${ red ( `${ errorMessage } \n` ) } ` ) ;
152
+ process . stderr . write (
153
+ ` --> ${ position . source } :${ position . line } :${
154
+ position . column
155
+ } (${ methodName || '<anonymous>' } )\n`
156
+ ) ;
157
+ process . stderr . write ( sourceCodeHighlight + '\n' ) ;
158
+ process . stderr . write ( red ( `${ err . stack } \n` ) ) ;
159
+
111
160
process . stderr . write (
112
161
`This ${
113
162
isReferenceError ? 'is most likely' : 'could be'
114
163
} caused by using DOM or Web APIs.\n`
115
164
) ;
116
165
process . stderr . write (
117
- `Pre-render runs in node and has no access to globals available in browsers.\n\n `
166
+ `Pre-render runs in node and has no access to globals available in browsers.\n`
118
167
) ;
119
168
process . stderr . write (
120
169
`Consider wrapping code producing error in: 'if (typeof window !== "undefined") { ... }'\n`
@@ -125,7 +174,7 @@ async function handlePrerenderError(err, env, stack, entry) {
125
174
}
126
175
process . stderr . write ( '\n' ) ;
127
176
process . stderr . write (
128
- ` Alternatively use ' preact build --no-prerender' to disable prerendering.\n\n`
177
+ ' Alternatively use ` preact build --no-prerender` to disable prerendering.\n'
129
178
) ;
130
179
process . stderr . write (
131
180
'See https://github.com/developit/preact-cli#pre-rendering for further information.'
0 commit comments